Skip to content

Commit 6489ef1

Browse files
committed
bytes, none, ellipsis
1 parent 619bc15 commit 6489ef1

File tree

2 files changed

+90
-82
lines changed

2 files changed

+90
-82
lines changed

Lib/test/test_marshal.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -101,8 +101,6 @@ def test_string(self):
101101
for s in ["", "Andr\xe8 Previn", "abc", " "*10000]:
102102
self.helper(s)
103103

104-
# TODO: RUSTPYTHON
105-
@unittest.expectedFailure
106104
def test_bytes(self):
107105
for s in [b"", b"Andr\xe8 Previn", b"abc", b" "*10000]:
108106
self.helper(s)
@@ -337,8 +335,6 @@ def readinto(self, buf):
337335
self.assertRaises(ValueError, marshal.load,
338336
BadReader(marshal.dumps(value)))
339337

340-
# TODO: RUSTPYTHON
341-
@unittest.expectedFailure
342338
def test_eof(self):
343339
data = marshal.dumps(("hello", "dolly", None))
344340
for i in range(len(data)):

vm/src/stdlib/marshal.rs

Lines changed: 90 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -14,19 +14,17 @@ mod decl {
1414
protocol::PyBuffer,
1515
PyObjectRef, PyResult, TryFromObject, VirtualMachine,
1616
};
17-
/// TODO
18-
/// PyBytes: Currently getting recursion error with match_class!
1917
use num_bigint::{BigInt, Sign};
2018
use num_traits::Zero;
2119

2220
#[repr(u8)]
2321
enum Type {
2422
// Null = b'0',
25-
// None = b'N',
23+
None = b'N',
2624
False = b'F',
2725
True = b'T',
2826
// StopIter = b'S',
29-
// Ellipsis = b'.',
27+
Ellipsis = b'.',
3028
Int = b'i',
3129
Float = b'g',
3230
// Complex = b'y',
@@ -56,11 +54,11 @@ mod decl {
5654
use Type::*;
5755
Ok(match value {
5856
// b'0' => Null,
59-
// b'N' => None,
57+
b'N' => None,
6058
b'F' => False,
6159
b'T' => True,
6260
// b'S' => StopIter,
63-
// b'.' => Ellipsis,
61+
b'.' => Ellipsis,
6462
b'i' => Int,
6563
b'g' => Float,
6664
// b'y' => Complex,
@@ -109,80 +107,92 @@ mod decl {
109107

110108
/// Dumping helper function to turn a value into bytes.
111109
fn dump_obj(buf: &mut Vec<u8>, value: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> {
112-
match_class!(match value {
113-
pyint @ PyInt => {
114-
if pyint.class().is(vm.ctx.types.bool_type) {
115-
let typ = if pyint.as_bigint().is_zero() {
116-
Type::False
110+
if vm.is_none(&value) {
111+
buf.push(Type::None as u8);
112+
} else if value.is(&vm.ctx.ellipsis) {
113+
buf.push(Type::Ellipsis as u8);
114+
} else {
115+
match_class!(match value {
116+
pyint @ PyInt => {
117+
if pyint.class().is(vm.ctx.types.bool_type) {
118+
let typ = if pyint.as_bigint().is_zero() {
119+
Type::False
120+
} else {
121+
Type::True
122+
};
123+
buf.push(typ as u8);
117124
} else {
118-
Type::True
119-
};
120-
buf.push(typ as u8);
121-
} else {
122-
buf.push(Type::Int as u8);
123-
let (sign, int_bytes) = pyint.as_bigint().to_bytes_le();
124-
let mut len = int_bytes.len() as i32;
125-
if sign == Sign::Minus {
126-
len = -len;
125+
buf.push(Type::Int as u8);
126+
let (sign, int_bytes) = pyint.as_bigint().to_bytes_le();
127+
let mut len = int_bytes.len() as i32;
128+
if sign == Sign::Minus {
129+
len = -len;
130+
}
131+
buf.extend(len.to_le_bytes());
132+
buf.extend(int_bytes);
127133
}
128-
buf.extend(len.to_le_bytes());
129-
buf.extend(int_bytes);
130134
}
131-
}
132-
pyfloat @ PyFloat => {
133-
buf.push(Type::Float as u8);
134-
buf.extend(pyfloat.to_f64().to_le_bytes());
135-
}
136-
pystr @ PyStr => {
137-
buf.push(Type::Str as u8);
138-
write_size(buf, pystr.as_str().len(), vm)?;
139-
buf.extend(pystr.as_str().as_bytes());
140-
}
141-
pylist @ PyList => {
142-
buf.push(Type::List as u8);
143-
let pylist_items = pylist.borrow_vec();
144-
dump_seq(buf, pylist_items.iter(), vm)?;
145-
}
146-
pyset @ PySet => {
147-
buf.push(Type::Set as u8);
148-
let elements = pyset.elements();
149-
dump_seq(buf, elements.iter(), vm)?;
150-
}
151-
pyfrozen @ PyFrozenSet => {
152-
buf.push(Type::FrozenSet as u8);
153-
let elements = pyfrozen.elements();
154-
dump_seq(buf, elements.iter(), vm)?;
155-
}
156-
pytuple @ PyTuple => {
157-
buf.push(Type::Tuple as u8);
158-
dump_seq(buf, pytuple.iter(), vm)?;
159-
}
160-
pydict @ PyDict => {
161-
buf.push(Type::Dict as u8);
162-
write_size(buf, pydict.len(), vm)?;
163-
for (key, value) in pydict {
164-
dump_obj(buf, key, vm)?;
165-
dump_obj(buf, value, vm)?;
135+
pyfloat @ PyFloat => {
136+
buf.push(Type::Float as u8);
137+
buf.extend(pyfloat.to_f64().to_le_bytes());
166138
}
167-
}
168-
bytes @ PyByteArray => {
169-
buf.push(Type::Bytes as u8);
170-
let data = bytes.borrow_buf();
171-
write_size(buf, data.len(), vm)?;
172-
buf.extend(&*data);
173-
}
174-
co @ PyCode => {
175-
buf.push(Type::Code as u8);
176-
let bytes = co.code.map_clone_bag(&bytecode::BasicBag).to_bytes();
177-
write_size(buf, bytes.len(), vm)?;
178-
buf.extend(bytes);
179-
}
180-
_ => {
181-
return Err(vm.new_not_implemented_error(
182-
"TODO: not implemented yet or marshal unsupported type".to_owned(),
183-
));
184-
}
185-
});
139+
pystr @ PyStr => {
140+
buf.push(Type::Str as u8);
141+
write_size(buf, pystr.as_str().len(), vm)?;
142+
buf.extend(pystr.as_str().as_bytes());
143+
}
144+
pylist @ PyList => {
145+
buf.push(Type::List as u8);
146+
let pylist_items = pylist.borrow_vec();
147+
dump_seq(buf, pylist_items.iter(), vm)?;
148+
}
149+
pyset @ PySet => {
150+
buf.push(Type::Set as u8);
151+
let elements = pyset.elements();
152+
dump_seq(buf, elements.iter(), vm)?;
153+
}
154+
pyfrozen @ PyFrozenSet => {
155+
buf.push(Type::FrozenSet as u8);
156+
let elements = pyfrozen.elements();
157+
dump_seq(buf, elements.iter(), vm)?;
158+
}
159+
pytuple @ PyTuple => {
160+
buf.push(Type::Tuple as u8);
161+
dump_seq(buf, pytuple.iter(), vm)?;
162+
}
163+
pydict @ PyDict => {
164+
buf.push(Type::Dict as u8);
165+
write_size(buf, pydict.len(), vm)?;
166+
for (key, value) in pydict {
167+
dump_obj(buf, key, vm)?;
168+
dump_obj(buf, value, vm)?;
169+
}
170+
}
171+
bytes @ PyBytes => {
172+
buf.push(Type::Bytes as u8);
173+
let data = bytes.as_bytes();
174+
write_size(buf, data.len(), vm)?;
175+
buf.extend(&*data);
176+
}
177+
bytes @ PyByteArray => {
178+
buf.push(Type::Bytes as u8);
179+
let data = bytes.borrow_buf();
180+
write_size(buf, data.len(), vm)?;
181+
buf.extend(&*data);
182+
}
183+
co @ PyCode => {
184+
buf.push(Type::Code as u8);
185+
let bytes = co.code.map_clone_bag(&bytecode::BasicBag).to_bytes();
186+
write_size(buf, bytes.len(), vm)?;
187+
buf.extend(bytes);
188+
}
189+
_ => {
190+
return Err(vm.new_not_implemented_error(
191+
"TODO: not implemented yet or marshal unsupported type".to_owned(),
192+
));
193+
}
194+
})
195+
}
186196
Ok(())
187197
}
188198

@@ -248,8 +258,10 @@ mod decl {
248258
let typ = Type::try_from(*type_indicator)
249259
.map_err(|_| vm.new_value_error("bad marshal data (unknown type code)".to_owned()))?;
250260
let (obj, buf) = match typ {
251-
Type::True => ((true).to_pyobject(vm), buf),
252-
Type::False => ((false).to_pyobject(vm), buf),
261+
Type::True => (true.to_pyobject(vm), buf),
262+
Type::False => (false.to_pyobject(vm), buf),
263+
Type::None => (vm.ctx.none(), buf),
264+
Type::Ellipsis => (vm.ctx.ellipsis(), buf),
253265
Type::Int => {
254266
if buf.len() < 4 {
255267
return Err(too_short_error(vm));

0 commit comments

Comments
 (0)