1
- use std:: collections:: HashMap ;
2
1
use std:: fmt;
3
2
4
3
use serde;
5
- use serde:: de:: Visitor ;
4
+ use serde:: de:: { DeserializeSeed , Visitor } ;
6
5
use serde:: ser:: { SerializeMap , SerializeSeq } ;
7
6
use serde_json;
8
7
9
8
use super :: super :: obj:: { objdict, objfloat, objint, objlist, objstr, objtuple, objtype} ;
10
9
use super :: super :: objbool;
11
10
use super :: super :: pyobject:: {
12
- DictProtocol , PyContext , PyFuncArgs , PyObject , PyObjectKind , PyObjectRef , PyResult ,
13
- TypeProtocol ,
11
+ DictProtocol , PyContext , PyFuncArgs , PyObjectKind , PyObjectRef , PyResult , TypeProtocol ,
14
12
} ;
15
13
use super :: super :: VirtualMachine ;
16
14
17
15
// We need to have a VM available to serialise a PyObject based on its subclass, so we implement
18
16
// PyObject serialisation via a proxy object which holds a reference to a VM
19
17
struct PyObjectSerializer < ' s > {
20
18
pyobject : & ' s PyObjectRef ,
21
- vm : & ' s VirtualMachine ,
19
+ ctx : & ' s PyContext ,
22
20
}
23
21
24
22
impl < ' s > PyObjectSerializer < ' s > {
25
23
fn clone_with_object ( & self , pyobject : & ' s PyObjectRef ) -> PyObjectSerializer {
26
24
PyObjectSerializer {
27
25
pyobject,
28
- vm : self . vm ,
26
+ ctx : self . ctx ,
29
27
}
30
28
}
31
29
}
@@ -43,21 +41,21 @@ impl<'s> serde::Serialize for PyObjectSerializer<'s> {
43
41
}
44
42
seq. end ( )
45
43
} ;
46
- if objtype:: isinstance ( self . pyobject , self . vm . ctx . str_type ( ) ) {
44
+ if objtype:: isinstance ( self . pyobject , self . ctx . str_type ( ) ) {
47
45
serializer. serialize_str ( & objstr:: get_value ( & self . pyobject ) )
48
- } else if objtype:: isinstance ( self . pyobject , self . vm . ctx . float_type ( ) ) {
46
+ } else if objtype:: isinstance ( self . pyobject , self . ctx . float_type ( ) ) {
49
47
serializer. serialize_f64 ( objfloat:: get_value ( self . pyobject ) )
50
- } else if objtype:: isinstance ( self . pyobject , self . vm . ctx . bool_type ( ) ) {
48
+ } else if objtype:: isinstance ( self . pyobject , self . ctx . bool_type ( ) ) {
51
49
serializer. serialize_bool ( objbool:: get_value ( self . pyobject ) )
52
- } else if objtype:: isinstance ( self . pyobject , self . vm . ctx . int_type ( ) ) {
50
+ } else if objtype:: isinstance ( self . pyobject , self . ctx . int_type ( ) ) {
53
51
serializer. serialize_i32 ( objint:: get_value ( self . pyobject ) )
54
- } else if objtype:: isinstance ( self . pyobject , self . vm . ctx . list_type ( ) ) {
52
+ } else if objtype:: isinstance ( self . pyobject , self . ctx . list_type ( ) ) {
55
53
let elements = objlist:: get_elements ( self . pyobject ) ;
56
54
serialize_seq_elements ( serializer, elements)
57
- } else if objtype:: isinstance ( self . pyobject , self . vm . ctx . tuple_type ( ) ) {
55
+ } else if objtype:: isinstance ( self . pyobject , self . ctx . tuple_type ( ) ) {
58
56
let elements = objtuple:: get_elements ( self . pyobject ) ;
59
57
serialize_seq_elements ( serializer, elements)
60
- } else if objtype:: isinstance ( self . pyobject , self . vm . ctx . dict_type ( ) ) {
58
+ } else if objtype:: isinstance ( self . pyobject , self . ctx . dict_type ( ) ) {
61
59
let elements = objdict:: get_elements ( self . pyobject ) ;
62
60
let mut map = serializer. serialize_map ( Some ( elements. len ( ) ) ) ?;
63
61
for ( key, e) in elements {
@@ -75,136 +73,134 @@ impl<'s> serde::Serialize for PyObjectSerializer<'s> {
75
73
}
76
74
}
77
75
78
- struct PyObjectKindVisitor ;
79
-
80
- impl < ' de > Visitor < ' de > for PyObjectKindVisitor {
81
- type Value = PyObjectKind ;
76
+ // This object is used as the seed for deserialization so we have access to the PyContext for type
77
+ // creation
78
+ #[ derive( Clone ) ]
79
+ struct PyObjectDeserializer < ' c > {
80
+ ctx : & ' c PyContext ,
81
+ }
82
82
83
- fn expecting ( & self , formatter : & mut fmt:: Formatter ) -> fmt:: Result {
84
- formatter. write_str ( "a type that can deserialise in Python" )
85
- }
83
+ impl < ' de > serde:: de:: DeserializeSeed < ' de > for PyObjectDeserializer < ' de > {
84
+ type Value = PyObjectRef ;
86
85
87
- fn visit_str < E > ( self , value : & str ) -> Result < Self :: Value , E >
86
+ fn deserialize < D > ( self , deserializer : D ) -> Result < Self :: Value , D :: Error >
88
87
where
89
- E : serde:: de :: Error ,
88
+ D : serde:: Deserializer < ' de > ,
90
89
{
91
- Ok ( PyObjectKind :: String {
92
- value : value. to_string ( ) ,
93
- } )
94
- }
90
+ impl < ' de > Visitor < ' de > for PyObjectDeserializer < ' de > {
91
+ type Value = PyObjectRef ;
95
92
96
- fn visit_string < E > ( self , value : String ) -> Result < Self :: Value , E >
97
- where
98
- E : serde:: de:: Error ,
99
- {
100
- Ok ( PyObjectKind :: String { value } )
101
- }
93
+ fn expecting ( & self , formatter : & mut fmt:: Formatter ) -> fmt:: Result {
94
+ formatter. write_str ( "a type that can deserialise in Python" )
95
+ }
102
96
103
- fn visit_i64 < E > ( self , value : i64 ) -> Result < Self :: Value , E >
104
- where
105
- E : serde:: de:: Error ,
106
- {
107
- // The JSON deserialiser always uses the i64/u64 deserialisers, so we only need to
108
- // implement those for now
109
- use std:: i32;
110
- if value >= i32:: MIN as i64 && value <= i32:: MAX as i64 {
111
- Ok ( PyObjectKind :: Integer {
112
- value : value as i32 ,
113
- } )
114
- } else {
115
- Err ( E :: custom ( format ! ( "i64 out of range: {}" , value) ) )
116
- }
117
- }
97
+ fn visit_str < E > ( self , value : & str ) -> Result < Self :: Value , E >
98
+ where
99
+ E : serde:: de:: Error ,
100
+ {
101
+ Ok ( self . ctx . new_str ( value. to_string ( ) ) )
102
+ }
118
103
119
- fn visit_u64 < E > ( self , value : u64 ) -> Result < Self :: Value , E >
120
- where
121
- E : serde:: de:: Error ,
122
- {
123
- // The JSON deserialiser always uses the i64/u64 deserialisers, so we only need to
124
- // implement those for now
125
- use std:: i32;
126
- if value <= i32:: MAX as u64 {
127
- Ok ( PyObjectKind :: Integer {
128
- value : value as i32 ,
129
- } )
130
- } else {
131
- Err ( E :: custom ( format ! ( "u64 out of range: {}" , value) ) )
132
- }
133
- }
104
+ fn visit_string < E > ( self , value : String ) -> Result < Self :: Value , E >
105
+ where
106
+ E : serde:: de:: Error ,
107
+ {
108
+ Ok ( self . ctx . new_str ( value) )
109
+ }
134
110
135
- fn visit_f64 < E > ( self , value : f64 ) -> Result < Self :: Value , E >
136
- where
137
- E : serde:: de:: Error ,
138
- {
139
- Ok ( PyObjectKind :: Float { value } )
140
- }
111
+ fn visit_i64 < E > ( self , value : i64 ) -> Result < Self :: Value , E >
112
+ where
113
+ E : serde:: de:: Error ,
114
+ {
115
+ // The JSON deserialiser always uses the i64/u64 deserialisers, so we only need to
116
+ // implement those for now
117
+ use std:: i32;
118
+ if value >= i32:: MIN as i64 && value <= i32:: MAX as i64 {
119
+ Ok ( self . ctx . new_int ( value as i32 ) )
120
+ } else {
121
+ Err ( E :: custom ( format ! ( "i64 out of range: {}" , value) ) )
122
+ }
123
+ }
141
124
142
- fn visit_bool < E > ( self , value : bool ) -> Result < Self :: Value , E >
143
- where
144
- E : serde:: de:: Error ,
145
- {
146
- Ok ( PyObjectKind :: Integer {
147
- value : if value { 1 } else { 0 } ,
148
- } )
149
- }
125
+ fn visit_u64 < E > ( self , value : u64 ) -> Result < Self :: Value , E >
126
+ where
127
+ E : serde:: de:: Error ,
128
+ {
129
+ // The JSON deserialiser always uses the i64/u64 deserialisers, so we only need to
130
+ // implement those for now
131
+ use std:: i32;
132
+ if value <= i32:: MAX as u64 {
133
+ Ok ( self . ctx . new_int ( value as i32 ) )
134
+ } else {
135
+ Err ( E :: custom ( format ! ( "u64 out of range: {}" , value) ) )
136
+ }
137
+ }
150
138
151
- fn visit_seq < A > ( self , mut access : A ) -> Result < Self :: Value , A :: Error >
152
- where
153
- A : serde:: de:: SeqAccess < ' de > ,
154
- {
155
- let mut seq = Vec :: with_capacity ( access. size_hint ( ) . unwrap_or ( 0 ) ) ;
156
- while let Some ( value) = access. next_element ( ) ? {
157
- seq. push (
158
- PyObject {
159
- kind : value,
160
- typ : None , // TODO: Determine the effect this None will have
161
- } . into_ref ( ) ,
162
- ) ;
163
- }
164
- Ok ( PyObjectKind :: List { elements : seq } )
165
- }
139
+ fn visit_f64 < E > ( self , value : f64 ) -> Result < Self :: Value , E >
140
+ where
141
+ E : serde:: de:: Error ,
142
+ {
143
+ Ok ( self . ctx . new_float ( value) )
144
+ }
166
145
167
- fn visit_map < M > ( self , mut access : M ) -> Result < Self :: Value , M :: Error >
168
- where
169
- M : serde:: de:: MapAccess < ' de > ,
170
- {
171
- let mut map = HashMap :: with_capacity ( access. size_hint ( ) . unwrap_or ( 0 ) ) ;
172
-
173
- while let Some ( ( key, value) ) = access. next_entry ( ) ? {
174
- map. insert (
175
- key,
176
- PyObject {
177
- kind : value,
178
- typ : None , // TODO: Determine the effect this None will have
179
- } . into_ref ( ) ,
180
- ) ;
181
- }
146
+ fn visit_bool < E > ( self , value : bool ) -> Result < Self :: Value , E >
147
+ where
148
+ E : serde:: de:: Error ,
149
+ {
150
+ Ok ( self . ctx . new_bool ( value) )
151
+ }
182
152
183
- Ok ( PyObjectKind :: Dict { elements : map } )
184
- }
153
+ fn visit_seq < A > ( self , mut access : A ) -> Result < Self :: Value , A :: Error >
154
+ where
155
+ A : serde:: de:: SeqAccess < ' de > ,
156
+ {
157
+ let mut seq = Vec :: with_capacity ( access. size_hint ( ) . unwrap_or ( 0 ) ) ;
158
+ while let Some ( value) = access. next_element_seed ( self . clone ( ) ) ? {
159
+ seq. push ( value) ;
160
+ }
161
+ Ok ( self . ctx . new_list ( seq) )
162
+ }
185
163
186
- fn visit_unit < E > ( self ) -> Result < Self :: Value , E >
187
- where
188
- E : serde:: de:: Error ,
189
- {
190
- Ok ( PyObjectKind :: None )
191
- }
192
- }
164
+ fn visit_map < M > ( self , mut access : M ) -> Result < Self :: Value , M :: Error >
165
+ where
166
+ M : serde:: de:: MapAccess < ' de > ,
167
+ {
168
+ let dict = self . ctx . new_dict ( ) ;
169
+ // TODO: Given keys must be strings, we can probably do something more efficient
170
+ // than wrapping the given object up and then unwrapping it to determine whether or
171
+ // not it is a string
172
+ while let Some ( ( key_obj, value) ) =
173
+ access. next_entry_seed ( self . clone ( ) , self . clone ( ) ) ?
174
+ {
175
+ let key = match key_obj. borrow ( ) . kind {
176
+ PyObjectKind :: String { ref value } => value. clone ( ) ,
177
+ _ => unimplemented ! ( "map keys must be strings" ) ,
178
+ } ;
179
+ dict. set_item ( & key, value) ;
180
+ }
181
+ Ok ( dict)
182
+ }
193
183
194
- impl < ' de > serde:: Deserialize < ' de > for PyObjectKind {
195
- fn deserialize < D > ( deserializer : D ) -> Result < PyObjectKind , D :: Error >
196
- where
197
- D : serde:: Deserializer < ' de > ,
198
- {
199
- deserializer. deserialize_any ( PyObjectKindVisitor )
184
+ fn visit_unit < E > ( self ) -> Result < Self :: Value , E >
185
+ where
186
+ E : serde:: de:: Error ,
187
+ {
188
+ Ok ( self . ctx . none . clone ( ) )
189
+ }
190
+ }
191
+
192
+ deserializer. deserialize_any ( self . clone ( ) )
200
193
}
201
194
}
202
195
203
196
fn dumps ( vm : & mut VirtualMachine , args : PyFuncArgs ) -> PyResult {
204
197
// TODO: Implement non-trivial serialisation case
205
198
arg_check ! ( vm, args, required = [ ( obj, None ) ] ) ;
206
199
// TODO: Raise an exception for serialisation errors
207
- let serializer = PyObjectSerializer { pyobject : obj, vm } ;
200
+ let serializer = PyObjectSerializer {
201
+ pyobject : obj,
202
+ ctx : & vm. ctx ,
203
+ } ;
208
204
let string = serde_json:: to_string ( & serializer) . unwrap ( ) ;
209
205
Ok ( vm. context ( ) . new_str ( string) )
210
206
}
@@ -213,11 +209,12 @@ fn loads(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
213
209
// TODO: Implement non-trivial deserialisation case
214
210
arg_check ! ( vm, args, required = [ ( string, Some ( vm. ctx. str_type( ) ) ) ] ) ;
215
211
// TODO: Raise an exception for deserialisation errors
216
- let kind: PyObjectKind = match string. borrow ( ) . kind {
217
- PyObjectKind :: String { ref value } => serde_json:: from_str ( & value) . unwrap ( ) ,
218
- _ => unimplemented ! ( "json.loads only handles strings" ) ,
219
- } ;
220
- Ok ( PyObject :: new ( kind, vm. get_type ( ) ) )
212
+ let de = PyObjectDeserializer { ctx : & vm. ctx } ;
213
+ // TODO: Support deserializing string sub-classes
214
+ Ok ( de
215
+ . deserialize ( & mut serde_json:: Deserializer :: from_str ( & objstr:: get_value (
216
+ & string,
217
+ ) ) ) . unwrap ( ) )
221
218
}
222
219
223
220
pub fn mk_module ( ctx : & PyContext ) -> PyObjectRef {
0 commit comments