@@ -4,16 +4,11 @@ use serde;
4
4
use serde:: de:: { DeserializeSeed , Visitor } ;
5
5
use serde:: ser:: { Serialize , SerializeMap , SerializeSeq } ;
6
6
7
- use crate :: obj:: {
8
- objbool,
9
- objdict:: PyDictRef ,
10
- objfloat, objint, objsequence,
11
- objstr:: { self , PyString } ,
12
- objtype,
13
- } ;
7
+ use crate :: obj:: { objbool, objdict:: PyDictRef , objfloat, objint, objsequence, objstr, objtype} ;
14
8
use crate :: pyobject:: { IdProtocol , ItemProtocol , PyObjectRef , TypeProtocol } ;
15
9
use crate :: VirtualMachine ;
16
10
use num_traits:: cast:: ToPrimitive ;
11
+ use num_traits:: sign:: Signed ;
17
12
18
13
#[ inline]
19
14
pub fn serialize < S > (
@@ -79,9 +74,16 @@ impl<'s> serde::Serialize for PyObjectSerializer<'s> {
79
74
serializer. serialize_bool ( objbool:: get_value ( self . pyobject ) )
80
75
} else if objtype:: isinstance ( self . pyobject , & self . vm . ctx . int_type ( ) ) {
81
76
let v = objint:: get_value ( self . pyobject ) ;
82
- serializer. serialize_i64 ( v. to_i64 ( ) . unwrap ( ) )
83
- // Although this may seem nice, it does not give the right result:
84
- // v.serialize(serializer)
77
+ let int_too_large = || serde:: ser:: Error :: custom ( "int too large to serialize" ) ;
78
+ // TODO: serialize BigInt when it does not fit into i64
79
+ // BigInt implements serialization to a tuple of sign and a list of u32s,
80
+ // eg. -1 is [-1, [1]], 0 is [0, []], 12345678900000654321 is [1, [2710766577,2874452364]]
81
+ // CPython serializes big ints as long decimal integer literals
82
+ if v. is_positive ( ) {
83
+ serializer. serialize_u64 ( v. to_u64 ( ) . ok_or_else ( int_too_large) ?)
84
+ } else {
85
+ serializer. serialize_i64 ( v. to_i64 ( ) . ok_or_else ( int_too_large) ?)
86
+ }
85
87
} else if objtype:: isinstance ( self . pyobject , & self . vm . ctx . list_type ( ) ) {
86
88
let elements = objsequence:: get_elements_list ( self . pyobject ) ;
87
89
serialize_seq_elements ( serializer, & elements)
@@ -138,35 +140,26 @@ impl<'de> Visitor<'de> for PyObjectDeserializer<'de> {
138
140
formatter. write_str ( "a type that can deserialise in Python" )
139
141
}
140
142
141
- fn visit_str < E > ( self , value : & str ) -> Result < Self :: Value , E >
142
- where
143
- E : serde:: de:: Error ,
144
- {
145
- Ok ( self . vm . ctx . new_str ( value. to_string ( ) ) )
146
- }
147
-
148
- fn visit_string < E > ( self , value : String ) -> Result < Self :: Value , E >
143
+ fn visit_bool < E > ( self , value : bool ) -> Result < Self :: Value , E >
149
144
where
150
145
E : serde:: de:: Error ,
151
146
{
152
- Ok ( self . vm . ctx . new_str ( value) )
147
+ Ok ( self . vm . ctx . new_bool ( value) )
153
148
}
154
149
150
+ // Other signed integers delegate to this method by default, it’s the only one needed
155
151
fn visit_i64 < E > ( self , value : i64 ) -> Result < Self :: Value , E >
156
152
where
157
153
E : serde:: de:: Error ,
158
154
{
159
- // The JSON deserializer always uses the i64/u64 deserializers, so we only need to
160
- // implement those for now
161
155
Ok ( self . vm . ctx . new_int ( value) )
162
156
}
163
157
158
+ // Other unsigned integers delegate to this method by default, it’s the only one needed
164
159
fn visit_u64 < E > ( self , value : u64 ) -> Result < Self :: Value , E >
165
160
where
166
161
E : serde:: de:: Error ,
167
162
{
168
- // The JSON deserializer always uses the i64/u64 deserializers, so we only need to
169
- // implement those for now
170
163
Ok ( self . vm . ctx . new_int ( value) )
171
164
}
172
165
@@ -177,11 +170,26 @@ impl<'de> Visitor<'de> for PyObjectDeserializer<'de> {
177
170
Ok ( self . vm . ctx . new_float ( value) )
178
171
}
179
172
180
- fn visit_bool < E > ( self , value : bool ) -> Result < Self :: Value , E >
173
+ fn visit_str < E > ( self , value : & str ) -> Result < Self :: Value , E >
181
174
where
182
175
E : serde:: de:: Error ,
183
176
{
184
- Ok ( self . vm . ctx . new_bool ( value) )
177
+ // Owned value needed anyway, delegate to visit_string
178
+ self . visit_string ( value. to_string ( ) )
179
+ }
180
+
181
+ fn visit_string < E > ( self , value : String ) -> Result < Self :: Value , E >
182
+ where
183
+ E : serde:: de:: Error ,
184
+ {
185
+ Ok ( self . vm . ctx . new_str ( value) )
186
+ }
187
+
188
+ fn visit_unit < E > ( self ) -> Result < Self :: Value , E >
189
+ where
190
+ E : serde:: de:: Error ,
191
+ {
192
+ Ok ( self . vm . get_none ( ) )
185
193
}
186
194
187
195
fn visit_seq < A > ( self , mut access : A ) -> Result < Self :: Value , A :: Error >
@@ -200,23 +208,11 @@ impl<'de> Visitor<'de> for PyObjectDeserializer<'de> {
200
208
M : serde:: de:: MapAccess < ' de > ,
201
209
{
202
210
let dict = self . vm . ctx . new_dict ( ) ;
203
- // TODO: Given keys must be strings, we can probably do something more efficient
204
- // than wrapping the given object up and then unwrapping it to determine whether or
205
- // not it is a string
211
+ // Although JSON keys must be strings, implementation accepts any keys
212
+ // and can be reused by other deserializers without such limit
206
213
while let Some ( ( key_obj, value) ) = access. next_entry_seed ( self . clone ( ) , self . clone ( ) ) ? {
207
- let key: String = match key_obj. payload :: < PyString > ( ) {
208
- Some ( PyString { ref value } ) => value. clone ( ) ,
209
- _ => unimplemented ! ( "map keys must be strings" ) ,
210
- } ;
211
- dict. set_item ( & key, value, self . vm ) . unwrap ( ) ;
214
+ dict. set_item ( key_obj, value, self . vm ) . unwrap ( ) ;
212
215
}
213
216
Ok ( dict. into_object ( ) )
214
217
}
215
-
216
- fn visit_unit < E > ( self ) -> Result < Self :: Value , E >
217
- where
218
- E : serde:: de:: Error ,
219
- {
220
- Ok ( self . vm . get_none ( ) )
221
- }
222
218
}
0 commit comments