@@ -44,8 +44,8 @@ pub enum Object {
44
44
//Dict,
45
45
Code ( Arc < Object > ) ,
46
46
//Unknown,
47
- // Set,
48
- // FrozenSet,
47
+ Set ( Vec < Object > ) ,
48
+ FrozenSet ( Vec < Object > ) ,
49
49
Ref ( u32 ) ,
50
50
51
51
Bytes ( Vec < u8 > ) , // aka. ASCII in CPython's marshal
@@ -117,9 +117,26 @@ fn read_objects<R: io::Read>(r: &mut R, references: Vec<Object>, size: usize) ->
117
117
Ok ( ( vector, references2) )
118
118
}
119
119
120
+ macro_rules! build_container {
121
+ ( $reader: expr, $references: expr, $container: expr, $size: expr, $flag: expr) => { {
122
+ let mut references = $references;
123
+ if $flag {
124
+ let index = references. len( ) as u32 ; // TODO: overflow check
125
+ references. push( Object :: Hole ) ;
126
+ let ( objects, mut references) = try!( read_objects( $reader, references, $size) ) ;
127
+ references[ index as usize ] = $container( objects) ; // TODO: overflow check
128
+ ( false , Object :: Ref ( index) , references)
129
+ }
130
+ else {
131
+ let ( objects, mut references) = try!( read_objects( $reader, references, $size) ) ;
132
+ ( false , $container( objects) , references)
133
+ }
134
+ } }
135
+ }
136
+
120
137
pub fn read_object < R : io:: Read > ( r : & mut R , mut references : Vec < Object > ) -> Result < ( Object , Vec < Object > ) , UnmarshalError > {
121
138
let byte = read_byte ! ( r) ;
122
- let flag = byte & 0b10000000 ;
139
+ let flag = if ( byte & 0b10000000 ) == 0 { false } else { true } ;
123
140
let opcode = byte & 0b01111111 ;
124
141
let ( add_ref, object, mut references) = match opcode as char {
125
142
'0' => return Err ( UnmarshalError :: UnexpectedCode ( "NULL object in marshal data for object" . to_string ( ) ) ) ,
@@ -147,21 +164,23 @@ pub fn read_object<R: io::Read>(r: &mut R, mut references: Vec<Object>) -> Resul
147
164
} ,
148
165
')' => { // “small tuple”
149
166
let size = read_byte ! ( r) as usize ;
150
- let ( objects, references) = try!( read_objects ( r, references, size) ) ;
151
- ( true , Object :: Tuple ( objects) , references)
167
+ build_container ! ( r, references, Object :: Tuple , size, flag)
152
168
} ,
153
169
'(' => { // “tuple”
154
170
let size = try!( read_long ( r) ) as usize ; // TODO: overflow check if usize is smaller than u32
155
- let index = references. len ( ) as u32 ; // TODO: overflow check
156
- references. push ( Object :: Hole ) ;
157
- let ( objects, mut references) = try!( read_objects ( r, references, size) ) ;
158
- references[ index as usize ] = Object :: Tuple ( objects) ; // TODO: overflow check
159
- ( false , Object :: Ref ( index) , references)
171
+ build_container ! ( r, references, Object :: Tuple , size, flag)
160
172
} ,
161
173
'[' => { // “list”
162
174
let size = try!( read_long ( r) ) as usize ; // TODO: overflow check if usize is smaller than u32
163
- let ( objects, references) = try!( read_objects ( r, references, size) ) ;
164
- ( true , Object :: List ( objects) , references)
175
+ build_container ! ( r, references, Object :: List , size, flag)
176
+ }
177
+ '<' => { // “set”
178
+ let size = try!( read_long ( r) ) as usize ; // TODO: overflow check if usize is smaller than u32
179
+ build_container ! ( r, references, Object :: Set , size, flag)
180
+ }
181
+ '>' => { // “frozenset”
182
+ let size = try!( read_long ( r) ) as usize ; // TODO: overflow check if usize is smaller than u32
183
+ build_container ! ( r, references, Object :: FrozenSet , size, false )
165
184
}
166
185
'r' => {
167
186
let index = try!( read_long ( r) ) ;
@@ -170,12 +189,12 @@ pub fn read_object<R: io::Read>(r: &mut R, mut references: Vec<Object>) -> Resul
170
189
171
190
_ => panic ! ( format!( "Unsupported opcode: {}" , opcode as char ) ) ,
172
191
} ;
173
- if flag == 0 || !add_ref {
174
- Ok ( ( object, references) )
175
- } else {
192
+ if flag && add_ref {
176
193
let index = references. len ( ) as u32 ; // TODO: overflow check
177
194
references. push ( object) ;
178
195
Ok ( ( Object :: Ref ( index) , references) )
196
+ } else {
197
+ Ok ( ( object, references) )
179
198
}
180
199
}
181
200
0 commit comments