11use std:: fmt;
22use std:: io;
33
4- use super :: super :: objects:: { Code , ObjectContent , ObjectRef , ObjectStore } ;
4+ use super :: super :: objects:: { Code , ObjectContent , ObjectRef , ObjectStore , PrimitiveObjects } ;
55
66#[ derive( Debug ) ]
77pub enum UnmarshalError {
@@ -73,11 +73,11 @@ fn read_unicode_string<R: io::Read>(reader: &mut R, size: usize) -> Result<Strin
7373}
7474
7575/// Read an arbitrary number of contiguous marshal objects
76- fn read_objects < R : io:: Read > ( reader : & mut R , store : & mut ObjectStore , references : & mut Vec < ObjectRef > , size : usize ) -> Result < Vec < ObjectRef > , UnmarshalError > {
76+ fn read_objects < R : io:: Read > ( reader : & mut R , store : & mut ObjectStore , primitive_objects : & PrimitiveObjects , references : & mut Vec < ObjectRef > , size : usize ) -> Result < Vec < ObjectRef > , UnmarshalError > {
7777 let mut vector = Vec :: < ObjectRef > :: new ( ) ;
7878 vector. reserve ( size) ;
7979 for _ in 0 ..size {
80- let object = try!( read_object ( reader, store, references) ) ;
80+ let object = try!( read_object ( reader, store, primitive_objects , references) ) ;
8181 vector. push ( object) ;
8282 } ;
8383 Ok ( vector)
@@ -108,19 +108,17 @@ macro_rules! deref_checktype {
108108/// If the flag is true, add this object to the vector of objects before reading its content
109109/// (required, as the order of objects matter for references).
110110macro_rules! build_container {
111- ( $reader: expr, $store: ident, $references: ident, $container : expr , $size: expr, $flag: expr) => { {
111+ ( $reader: expr, $store: ident, $references: ident, $primitive_objects : ident , $factory : ident , $size: expr, $flag: expr) => { {
112112 if $flag {
113- let index = $references. len( ) ;
114- let obj_ref = $store. allocate( ObjectContent :: Hole ) ;
113+ let obj_ref = ObjectRef :: new( ) ;
115114 $references. push( obj_ref. clone( ) ) ;
116- let objects = try!( read_objects( $reader, $store, $references, $size) ) ;
117- $store. replace_hole( & obj_ref, $container( objects) ) ;
118- $references[ index] = obj_ref. clone( ) ;
115+ let objects = try!( read_objects( $reader, $store, $primitive_objects, $references, $size) ) ;
116+ $store. allocate_at( obj_ref. clone( ) , $primitive_objects. $factory( objects) ) ;
119117 Ok ( obj_ref)
120118 }
121119 else {
122- let objects = try!( read_objects( $reader, $store, $references, $size) ) ;
123- Ok ( $store. allocate( $container ( objects) ) )
120+ let objects = try!( read_objects( $reader, $store, $primitive_objects , $ references, $size) ) ;
121+ Ok ( $store. allocate( $primitive_objects . $factory ( objects) ) )
124122 }
125123 } }
126124}
@@ -129,33 +127,33 @@ macro_rules! build_container {
129127/// If it is a container, read its content too.
130128/// If the first bit is 1 and the marshal protocol allows the type to be referenced,
131129/// add it to the list of references too.
132- pub fn read_object < R : io:: Read > ( reader : & mut R , store : & mut ObjectStore , references : & mut Vec < ObjectRef > ) -> Result < ObjectRef , UnmarshalError > {
130+ pub fn read_object < R : io:: Read > ( reader : & mut R , store : & mut ObjectStore , primitive_objects : & PrimitiveObjects , references : & mut Vec < ObjectRef > ) -> Result < ObjectRef , UnmarshalError > {
133131 let byte = read_byte ! ( reader) ;
134132 let flag = byte & 0b10000000 != 0 ;
135133 let opcode = byte & 0b01111111 ;
136134 match opcode as char {
137135 '0' => return Err ( UnmarshalError :: UnexpectedCode ( "NULL object in marshal data for object" . to_string ( ) ) ) ,
138- 'N' => Ok ( store . allocate ( ObjectContent :: None ) ) ,
139- 'F' => Ok ( store . allocate ( ObjectContent :: False ) ) ,
140- 'T' => Ok ( store . allocate ( ObjectContent :: True ) ) ,
136+ 'N' => Ok ( primitive_objects . none . clone ( ) ) ,
137+ 'F' => Ok ( primitive_objects . false_obj . clone ( ) ) ,
138+ 'T' => Ok ( primitive_objects . true_obj . clone ( ) ) ,
141139 'i' => {
142- let obj_ref = store. allocate ( ObjectContent :: Int ( try!( read_long ( reader) ) ) ) ;
140+ let obj_ref = store. allocate ( primitive_objects . new_int ( try!( read_long ( reader) ) ) ) ;
143141 if flag {
144142 references. push ( obj_ref. clone ( ) ) ;
145143 }
146144 Ok ( obj_ref)
147145 } ,
148146 'z' | 'Z' => { // “short ascii”, “short ascii interned”
149147 let size = read_byte ! ( reader) as usize ;
150- let obj_ref = store. allocate ( ObjectContent :: String ( try!( read_ascii_string ( reader, size) ) ) ) ;
148+ let obj_ref = store. allocate ( primitive_objects . new_string ( try!( read_ascii_string ( reader, size) ) ) ) ;
151149 if flag {
152150 references. push ( obj_ref. clone ( ) ) ;
153151 }
154152 Ok ( obj_ref)
155153 } ,
156154 'u' => { // “unicode”
157155 let size = try!( read_long ( reader) ) as usize ; // TODO: overflow check if usize is smaller than u32
158- let obj_ref = store. allocate ( ObjectContent :: String ( try!( read_unicode_string ( reader, size) ) ) ) ;
156+ let obj_ref = store. allocate ( primitive_objects . new_string ( try!( read_unicode_string ( reader, size) ) ) ) ;
159157 if flag {
160158 references. push ( obj_ref. clone ( ) ) ;
161159 }
@@ -169,31 +167,31 @@ pub fn read_object<R: io::Read>(reader: &mut R, store: &mut ObjectStore, referen
169167 Err ( err) => return Err ( UnmarshalError :: Io ( err) ) ,
170168 Ok ( ( ) ) => ( )
171169 } ;
172- let obj_ref = store. allocate ( ObjectContent :: Bytes ( buf) ) ;
170+ let obj_ref = store. allocate ( primitive_objects . new_bytes ( buf) ) ;
173171 if flag {
174172 references. push ( obj_ref. clone ( ) ) ;
175173 }
176174 Ok ( obj_ref)
177175 } ,
178176 ')' => { // “small tuple”
179177 let size = read_byte ! ( reader) as usize ;
180- build_container ! ( reader, store, references, ObjectContent :: Tuple , size, flag)
178+ build_container ! ( reader, store, references, primitive_objects , new_tuple , size, flag)
181179 } ,
182180 '(' => { // “tuple”
183181 let size = try!( read_long ( reader) ) as usize ; // TODO: overflow check if usize is smaller than u32
184- build_container ! ( reader, store, references, ObjectContent :: Tuple , size, flag)
182+ build_container ! ( reader, store, references, primitive_objects , new_tuple , size, flag)
185183 } ,
186184 '[' => { // “list”
187185 let size = try!( read_long ( reader) ) as usize ; // TODO: overflow check if usize is smaller than u32
188- build_container ! ( reader, store, references, ObjectContent :: List , size, flag)
186+ build_container ! ( reader, store, references, primitive_objects , new_list , size, flag)
189187 }
190188 '<' => { // “set”
191189 let size = try!( read_long ( reader) ) as usize ; // TODO: overflow check if usize is smaller than u32
192- build_container ! ( reader, store, references, ObjectContent :: Set , size, flag)
190+ build_container ! ( reader, store, references, primitive_objects , new_set , size, flag)
193191 }
194192 '>' => { // “frozenset”
195193 let size = try!( read_long ( reader) ) as usize ; // TODO: overflow check if usize is smaller than u32
196- build_container ! ( reader, store, references, ObjectContent :: FrozenSet , size, false )
194+ build_container ! ( reader, store, references, primitive_objects , new_frozenset , size, false )
197195 }
198196 'r' => {
199197 let index = try!( read_long ( reader) ) ;
@@ -202,7 +200,7 @@ pub fn read_object<R: io::Read>(reader: &mut R, store: &mut ObjectStore, referen
202200 } ,
203201 'c' => { // “code”
204202 let allocate_at = if flag {
205- let obj_ref = store . allocate ( ObjectContent :: Hole ) ;
203+ let obj_ref = ObjectRef :: new ( ) ;
206204 references. push ( obj_ref. clone ( ) ) ;
207205 Some ( obj_ref)
208206 }
@@ -214,16 +212,16 @@ pub fn read_object<R: io::Read>(reader: &mut R, store: &mut ObjectStore, referen
214212 let nlocals = try!( read_long ( reader) ) ;
215213 let stacksize = try!( read_long ( reader) ) ;
216214 let flags = try!( read_long ( reader) ) ;
217- let code = try!( read_object ( reader, store, references) ) ;
218- let consts = try!( read_object ( reader, store, references) ) ;
219- let names = try!( read_object ( reader, store, references) ) ;
220- let varnames = try!( read_object ( reader, store, references) ) ;
221- let freevars = try!( read_object ( reader, store, references) ) ;
222- let cellvars = try!( read_object ( reader, store, references) ) ;
223- let filename = try!( read_object ( reader, store, references) ) ;
224- let name = try!( read_object ( reader, store, references) ) ;
215+ let code = try!( read_object ( reader, store, primitive_objects , references) ) ;
216+ let consts = try!( read_object ( reader, store, primitive_objects , references) ) ;
217+ let names = try!( read_object ( reader, store, primitive_objects , references) ) ;
218+ let varnames = try!( read_object ( reader, store, primitive_objects , references) ) ;
219+ let freevars = try!( read_object ( reader, store, primitive_objects , references) ) ;
220+ let cellvars = try!( read_object ( reader, store, primitive_objects , references) ) ;
221+ let filename = try!( read_object ( reader, store, primitive_objects , references) ) ;
222+ let name = try!( read_object ( reader, store, primitive_objects , references) ) ;
225223 let firstlineno = try!( read_long ( reader) ) ;
226- let lnotab = try!( read_object ( reader, store, references) ) ; // TODO: decode this
224+ let lnotab = try!( read_object ( reader, store, primitive_objects , references) ) ; // TODO: decode this
227225 let code = Code {
228226 argcount : argcount as usize ,
229227 kwonlyargcount : kwonlyargcount,
@@ -242,11 +240,11 @@ pub fn read_object<R: io::Read>(reader: &mut R, store: &mut ObjectStore, referen
242240 lnotab : lnotab,
243241 } ;
244242
245- let obj = ObjectContent :: Code ( Box :: new ( code) ) ;
243+ let obj = primitive_objects . new_code ( code) ;
246244 let obj_ref = match allocate_at {
247245 None => store. allocate ( obj) ,
248246 Some ( obj_ref) => {
249- store. replace_hole ( & obj_ref, obj) ;
247+ store. allocate_at ( obj_ref. clone ( ) , obj) ;
250248 obj_ref
251249 } ,
252250 } ;
@@ -261,7 +259,8 @@ macro_rules! get_obj {
261259 ( $store: ident, $bytecode: expr ) => { {
262260 let mut reader: & [ u8 ] = $bytecode;
263261 let mut refs = Vec :: new( ) ;
264- let obj_ref = read_object( & mut reader, & mut $store, & mut refs) . unwrap( ) ;
262+ let primitive_objects = PrimitiveObjects :: new( $store) ;
263+ let obj_ref = read_object( & mut reader, & mut $store, primitive_objects, & mut refs) . unwrap( ) ;
265264 $store. deref( & obj_ref) . content. clone( )
266265 } } ;
267266}
0 commit comments