inline_int · ijl/orjson@4ba2c7f (original) (raw)
1
1
`// SPDX-License-Identifier: (Apache-2.0 OR MIT)
`
2
2
``
3
``
`-
use crate::ffi::{pylong_fits_in_i32, pylong_get_inline_value, pylong_is_unsigned, pylong_is_zero};
`
4
3
`use crate::opt::{Opt, STRICT_INTEGER};
`
5
4
`use crate::serialize::error::SerializeError;
`
6
5
`use serde::ser::{Serialize, Serializer};
`
7
6
``
8
``
`-
use core::ffi::c_uchar;
`
9
``
`-
use core::mem::transmute;
`
10
``
-
11
7
`// https://tools.ietf.org/html/rfc7159#section-6
`
12
8
`// "[-(253)+1, (253)-1]"
`
13
9
`const STRICT_INT_MIN: i64 = -9007199254740991;
`
`@@ -29,26 +25,27 @@ impl IntSerializer {
`
29
25
``
30
26
`impl Serialize for IntSerializer {
`
31
27
`#[inline(always)]
`
``
28
`+
#[cfg(feature = "inline_int")]
`
32
29
`fn serialize(&self, serializer: S) -> Result<S::Ok, S::Error>
`
33
30
`where
`
34
31
`S: Serializer,
`
35
32
`{
`
36
33
`unsafe {
`
37
``
`-
if pylong_is_zero(self.ptr) {
`
``
34
`+
if crate::ffi::pylong_is_zero(self.ptr) {
`
38
35
`return serializer.serialize_bytes(b"0");
`
39
36
`}
`
40
``
`-
let is_signed = !pylong_is_unsigned(self.ptr) as i32;
`
41
``
`-
if pylong_fits_in_i32(self.ptr) {
`
``
37
`+
let is_signed = !crate::ffi::pylong_is_unsigned(self.ptr) as i32;
`
``
38
`+
if crate::ffi::pylong_fits_in_i32(self.ptr) {
`
42
39
`if is_signed == 0 {
`
43
``
`-
serializer.serialize_u64(pylong_get_inline_value(self.ptr) as u64)
`
``
40
`+
serializer.serialize_u64(crate::ffi::pylong_get_inline_value(self.ptr) as u64)
`
44
41
`} else {
`
45
``
`-
serializer.serialize_i64(pylong_get_inline_value(self.ptr) as i64)
`
``
42
`+
serializer.serialize_i64(crate::ffi::pylong_get_inline_value(self.ptr) as i64)
`
46
43
`}
`
47
44
`} else {
`
48
45
`let mut buffer: [u8; 8] = [0; 8];
`
49
46
`let ret = pyo3_ffi::_PyLong_AsByteArray(
`
50
47
`self.ptr as *mut pyo3_ffi::PyLongObject,
`
51
``
`-
buffer.as_mut_ptr() as *mut c_uchar,
`
``
48
`+
buffer.as_mut_ptr() as *mut core::ffi::c_uchar,
`
52
49
`8,
`
53
50
`1,
`
54
51
` is_signed,
`
`@@ -58,15 +55,15 @@ impl Serialize for IntSerializer {
`
58
55
`err!(SerializeError::Integer64Bits)
`
59
56
`}
`
60
57
`if is_signed == 0 {
`
61
``
`-
let val = transmute::<[u8; 8], u64>(buffer);
`
``
58
`+
let val = core::mem::transmute::<[u8; 8], u64>(buffer);
`
62
59
`if unlikely!(opt_enabled!(self.opts, STRICT_INTEGER))
`
63
60
` && val > STRICT_INT_MAX as u64
`
64
61
`{
`
65
62
`err!(SerializeError::Integer53Bits)
`
66
63
`}
`
67
64
` serializer.serialize_u64(val)
`
68
65
`} else {
`
69
``
`-
let val = transmute::<[u8; 8], i64>(buffer);
`
``
66
`+
let val = core::mem::transmute::<[u8; 8], i64>(buffer);
`
70
67
`if unlikely!(opt_enabled!(self.opts, STRICT_INTEGER))
`
71
68
` && !(STRICT_INT_MIN..=STRICT_INT_MAX).contains(&val)
`
72
69
`{
`
`@@ -77,4 +74,39 @@ impl Serialize for IntSerializer {
`
77
74
`}
`
78
75
`}
`
79
76
`}
`
``
77
+
``
78
`+
#[inline(always)]
`
``
79
`+
#[cfg(not(feature = "inline_int"))]
`
``
80
`+
fn serialize(&self, serializer: S) -> Result<S::Ok, S::Error>
`
``
81
`+
where
`
``
82
`+
S: Serializer,
`
``
83
`+
{
`
``
84
`+
unsafe {
`
``
85
`+
if crate::ffi::pylong_is_unsigned(self.ptr) {
`
``
86
`+
let val = ffi!(PyLong_AsUnsignedLongLong(self.ptr));
`
``
87
`+
if unlikely!(val == u64::MAX) && !ffi!(PyErr_Occurred()).is_null() {
`
``
88
`+
ffi!(PyErr_Clear());
`
``
89
`+
err!(SerializeError::Integer64Bits)
`
``
90
`+
} else if unlikely!(opt_enabled!(self.opts, STRICT_INTEGER))
`
``
91
`+
&& val > STRICT_INT_MAX as u64
`
``
92
`+
{
`
``
93
`+
err!(SerializeError::Integer53Bits)
`
``
94
`+
} else {
`
``
95
`+
serializer.serialize_u64(val)
`
``
96
`+
}
`
``
97
`+
} else {
`
``
98
`+
let val = ffi!(PyLong_AsLongLong(self.ptr));
`
``
99
`+
if unlikely!(val == -1) && !ffi!(PyErr_Occurred()).is_null() {
`
``
100
`+
ffi!(PyErr_Clear());
`
``
101
`+
err!(SerializeError::Integer64Bits)
`
``
102
`+
} else if unlikely!(opt_enabled!(self.opts, STRICT_INTEGER))
`
``
103
`+
&& !(STRICT_INT_MIN..=STRICT_INT_MAX).contains(&val)
`
``
104
`+
{
`
``
105
`+
err!(SerializeError::Integer53Bits)
`
``
106
`+
} else {
`
``
107
`+
serializer.serialize_i64(val)
`
``
108
`+
}
`
``
109
`+
}
`
``
110
`+
}
`
``
111
`+
}
`
80
112
`}
`