Skip to content

Commit 1508675

Browse files
committed
Factorize containers unmarshalling and add support for set and frozenset.
1 parent aeb902e commit 1508675

File tree

1 file changed

+34
-15
lines changed

1 file changed

+34
-15
lines changed

src/marshal.rs

Lines changed: 34 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,8 @@ pub enum Object {
4444
//Dict,
4545
Code(Arc<Object>),
4646
//Unknown,
47-
//Set,
48-
//FrozenSet,
47+
Set(Vec<Object>),
48+
FrozenSet(Vec<Object>),
4949
Ref(u32),
5050

5151
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) ->
117117
Ok((vector, references2))
118118
}
119119

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+
120137
pub fn read_object<R: io::Read>(r: &mut R, mut references: Vec<Object>) -> Result<(Object, Vec<Object>), UnmarshalError> {
121138
let byte = read_byte!(r);
122-
let flag = byte & 0b10000000;
139+
let flag = if (byte & 0b10000000) == 0 { false } else { true };
123140
let opcode = byte & 0b01111111;
124141
let (add_ref, object, mut references) = match opcode as char {
125142
'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
147164
},
148165
')' => { // “small tuple”
149166
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)
152168
},
153169
'(' => { // “tuple”
154170
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)
160172
},
161173
'[' => { // “list”
162174
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)
165184
}
166185
'r' => {
167186
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
170189

171190
_ => panic!(format!("Unsupported opcode: {}", opcode as char)),
172191
};
173-
if flag == 0 || !add_ref {
174-
Ok((object, references))
175-
} else {
192+
if flag && add_ref {
176193
let index = references.len() as u32; // TODO: overflow check
177194
references.push(object);
178195
Ok((Object::Ref(index), references))
196+
} else {
197+
Ok((object, references))
179198
}
180199
}
181200

0 commit comments

Comments
 (0)