22
33use crate :: datetime:: * ;
44use crate :: exc:: * ;
5+ use crate :: iter:: * ;
56use crate :: typeref:: * ;
67use crate :: unicode:: * ;
78use crate :: uuid:: write_uuid;
@@ -61,6 +62,7 @@ pub fn serialize(
6162 Err ( err) => Err ( JSONEncodeError :: py_err ( err. to_string ( ) ) ) ,
6263 }
6364}
65+
6466struct SerializePyObject {
6567 ptr : * mut pyo3:: ffi:: PyObject ,
6668 default : Option < NonNull < pyo3:: ffi:: PyObject > > ,
@@ -75,14 +77,14 @@ impl<'p> Serialize for SerializePyObject {
7577 S : Serializer ,
7678 {
7779 let obj_ptr = unsafe { ( * self . ptr ) . ob_type } ;
78- if is_type ! ( obj_ptr, STR_PTR ) {
80+ if is_type ! ( obj_ptr, STR_TYPE ) {
7981 let mut str_size: pyo3:: ffi:: Py_ssize_t = 0 ;
8082 let uni = read_utf8_from_str ( self . ptr , & mut str_size) ;
8183 if unlikely ! ( uni. is_null( ) ) {
8284 err ! ( INVALID_STR )
8385 }
8486 serializer. serialize_str ( str_from_slice ! ( uni, str_size) )
85- } else if is_type ! ( obj_ptr, INT_PTR ) {
87+ } else if is_type ! ( obj_ptr, INT_TYPE ) {
8688 let val = ffi ! ( PyLong_AsLongLong ( self . ptr) ) ;
8789 if unlikely ! ( val == -1 && !pyo3:: ffi:: PyErr_Occurred ( ) . is_null( ) ) {
8890 err ! ( "Integer exceeds 64-bit range" )
@@ -92,40 +94,32 @@ impl<'p> Serialize for SerializePyObject {
9294 err ! ( "Integer exceeds 53-bit range" )
9395 }
9496 serializer. serialize_i64 ( val)
95- } else if is_type ! ( obj_ptr, LIST_PTR ) {
96- let len = ffi ! ( PyList_GET_SIZE ( self . ptr) ) as usize ;
97- if len != 0 {
98- let mut seq = serializer. serialize_seq ( Some ( len) ) ?;
99- let mut i = 0 ;
100- while i < len {
101- if unlikely ! ( self . recursion == RECURSION_LIMIT ) {
102- err ! ( "Recursion limit reached" )
103- }
104- let elem = ffi ! ( PyList_GET_ITEM ( self . ptr, i as pyo3:: ffi:: Py_ssize_t ) ) ;
105- i += 1 ;
106- seq. serialize_element ( & SerializePyObject {
107- ptr : elem,
108- default : self . default ,
109- opts : self . opts ,
110- default_calls : self . default_calls ,
111- recursion : self . recursion + 1 ,
112- } ) ?
113- }
114- seq. end ( )
115- } else {
116- serializer. serialize_seq ( None ) . unwrap ( ) . end ( )
97+ } else if is_type ! ( obj_ptr, LIST_TYPE ) {
98+ if unlikely ! ( self . recursion == RECURSION_LIMIT ) {
99+ err ! ( "Recursion limit reached" )
100+ }
101+ let mut seq = serializer. serialize_seq ( None ) . unwrap ( ) ;
102+ for elem in PyListIterator :: new ( self . ptr ) {
103+ seq. serialize_element ( & SerializePyObject {
104+ ptr : elem. as_ptr ( ) ,
105+ default : self . default ,
106+ opts : self . opts ,
107+ default_calls : self . default_calls ,
108+ recursion : self . recursion + 1 ,
109+ } ) ?
110+ }
111+ seq. end ( )
112+ } else if is_type ! ( obj_ptr, DICT_TYPE ) {
113+ if unlikely ! ( self . recursion == RECURSION_LIMIT ) {
114+ err ! ( "Recursion limit reached" )
117115 }
118- } else if is_type ! ( obj_ptr, DICT_PTR ) {
119116 let mut map = serializer. serialize_map ( None ) . unwrap ( ) ;
120117 let mut pos = 0isize ;
121118 let mut str_size: pyo3:: ffi:: Py_ssize_t = 0 ;
122119 let mut key: * mut pyo3:: ffi:: PyObject = std:: ptr:: null_mut ( ) ;
123120 let mut value: * mut pyo3:: ffi:: PyObject = std:: ptr:: null_mut ( ) ;
124121 while unsafe { pyo3:: ffi:: PyDict_Next ( self . ptr , & mut pos, & mut key, & mut value) != 0 } {
125- if unlikely ! ( self . recursion == RECURSION_LIMIT ) {
126- err ! ( "Recursion limit reached" )
127- }
128- if unlikely ! ( ( * key) . ob_type != STR_PTR ) {
122+ if unlikely ! ( ( * key) . ob_type != STR_TYPE ) {
129123 err ! ( "Dict key must be str" )
130124 }
131125 {
@@ -144,59 +138,50 @@ impl<'p> Serialize for SerializePyObject {
144138 } ) ?;
145139 }
146140 map. end ( )
147- } else if is_type ! ( obj_ptr, BOOL_PTR ) {
141+ } else if is_type ! ( obj_ptr, BOOL_TYPE ) {
148142 serializer. serialize_bool ( unsafe { self . ptr == TRUE } )
149- } else if is_type ! ( obj_ptr, NONE_PTR ) {
143+ } else if is_type ! ( obj_ptr, NONE_TYPE ) {
150144 serializer. serialize_unit ( )
151- } else if is_type ! ( obj_ptr, FLOAT_PTR ) {
145+ } else if is_type ! ( obj_ptr, FLOAT_TYPE ) {
152146 serializer. serialize_f64 ( ffi ! ( PyFloat_AS_DOUBLE ( self . ptr) ) )
153- } else if is_type ! ( obj_ptr, TUPLE_PTR ) {
154- let len = ffi ! ( PyTuple_GET_SIZE ( self . ptr) ) as usize ;
155- if len != 0 {
156- let mut seq = serializer. serialize_seq ( Some ( len) ) ?;
157- let mut i = 0 ;
158- while i < len {
159- let elem = ffi ! ( PyTuple_GET_ITEM ( self . ptr, i as pyo3:: ffi:: Py_ssize_t ) ) ;
160- i += 1 ;
161- seq. serialize_element ( & SerializePyObject {
162- ptr : elem,
163- default : self . default ,
164- opts : self . opts ,
165- default_calls : self . default_calls ,
166- recursion : self . recursion ,
167- } ) ?
168- }
169- seq. end ( )
170- } else {
171- serializer. serialize_seq ( None ) . unwrap ( ) . end ( )
147+ } else if is_type ! ( obj_ptr, TUPLE_TYPE ) {
148+ let mut seq = serializer. serialize_seq ( None ) . unwrap ( ) ;
149+ for elem in PyTupleIterator :: new ( self . ptr ) {
150+ seq. serialize_element ( & SerializePyObject {
151+ ptr : elem. as_ptr ( ) ,
152+ default : self . default ,
153+ opts : self . opts ,
154+ default_calls : self . default_calls ,
155+ recursion : self . recursion + 1 ,
156+ } ) ?
172157 }
173- } else if is_type ! ( obj_ptr, DATETIME_PTR ) {
158+ seq. end ( )
159+ } else if is_type ! ( obj_ptr, DATETIME_TYPE ) {
174160 let mut dt: SmallVec < [ u8 ; 32 ] > = SmallVec :: with_capacity ( 32 ) ;
175161 match write_datetime ( self . ptr , self . opts , & mut dt) {
176162 Ok ( _) => serializer. serialize_str ( str_from_slice ! ( dt. as_ptr( ) , dt. len( ) ) ) ,
177163 Err ( DatetimeError :: Library ) => {
178164 err ! ( "datetime's timezone library is not supported: use datetime.timezone.utc, pendulum, pytz, or dateutil" )
179165 }
180166 }
181- } else if is_type ! ( obj_ptr, DATE_PTR ) {
182- let mut dt: SmallVec < [ u8 ; 32 ] > = SmallVec :: with_capacity ( 32 ) ;
183- write_date ( self . ptr , & mut dt) ;
184- serializer. serialize_str ( str_from_slice ! ( dt. as_ptr( ) , dt. len( ) ) )
185- } else if is_type ! ( obj_ptr, TIME_PTR ) {
167+ } else if is_type ! ( obj_ptr, DATE_TYPE ) {
168+ Date :: new ( self . ptr ) . serialize ( serializer)
169+ } else if is_type ! ( obj_ptr, TIME_TYPE ) {
186170 if unsafe { ( * ( self . ptr as * mut pyo3:: ffi:: PyDateTime_Time ) ) . hastzinfo == 1 } {
187171 err ! ( "datetime.time must not have tzinfo set" )
188172 }
189- let mut dt: SmallVec < [ u8 ; 32 ] > = SmallVec :: with_capacity ( 32 ) ;
190- write_time ( self . ptr , self . opts , & mut dt) ;
191- serializer. serialize_str ( str_from_slice ! ( dt. as_ptr( ) , dt. len( ) ) )
192- } else if self . opts & SERIALIZE_UUID == SERIALIZE_UUID && is_type ! ( obj_ptr, UUID_PTR ) {
173+ Time :: new ( self . ptr , self . opts ) . serialize ( serializer)
174+ } else if self . opts & SERIALIZE_UUID == SERIALIZE_UUID && is_type ! ( obj_ptr, UUID_TYPE ) {
193175 let mut buf: SmallVec < [ u8 ; 36 ] > = SmallVec :: with_capacity ( 36 ) ;
194176 write_uuid ( self . ptr , & mut buf) ;
195177 serializer. serialize_str ( str_from_slice ! ( buf. as_ptr( ) , buf. len( ) ) )
196178 } else {
197179 if self . opts & SERIALIZE_DATACLASS == SERIALIZE_DATACLASS
198180 && ffi ! ( PyObject_HasAttr ( self . ptr, DATACLASS_FIELDS_STR ) ) == 1
199181 {
182+ if unlikely ! ( self . recursion == RECURSION_LIMIT ) {
183+ err ! ( "Recursion limit reached" )
184+ }
200185 let fields = ffi ! ( PyObject_GetAttr ( self . ptr, DATACLASS_FIELDS_STR ) ) ;
201186 ffi ! ( Py_DECREF ( fields) ) ;
202187 let mut map = serializer. serialize_map ( None ) . unwrap ( ) ;
@@ -207,9 +192,6 @@ impl<'p> Serialize for SerializePyObject {
207192 while unsafe {
208193 pyo3:: ffi:: PyDict_Next ( fields, & mut pos, & mut attr, & mut field) != 0
209194 } {
210- if unlikely ! ( self . recursion == RECURSION_LIMIT ) {
211- err ! ( "Recursion limit reached" )
212- }
213195 {
214196 let data = read_utf8_from_str ( attr, & mut str_size) ;
215197 if unlikely ! ( data. is_null( ) ) {
0 commit comments