Add repeat count support to struct.pack() (#1518)

* Add struct.pack() repeat count test

* Add repeat count support to struct.pack()

* Refactor parse_format_codes()

* Refactor parse_format_codes() again
This commit is contained in:
ChJR
2019-10-16 02:25:51 +09:00
committed by Windel Bouwman
parent ea803d1ed4
commit b2126829e9
2 changed files with 50 additions and 6 deletions

View File

@@ -1,4 +1,5 @@
from testutils import assert_raises
import struct
data = struct.pack('IH', 14, 12)
@@ -22,3 +23,18 @@ v1, v2 = struct.unpack('>IH', data)
assert v1 == 14
assert v2 == 12
data = struct.pack('3B', 65, 66, 67)
assert data == bytes([65, 66, 67])
v1, v2, v3 = struct.unpack('3B', data)
assert v1 == 65
assert v2 == 66
assert v3 == 67
with assert_raises(Exception):
data = struct.pack('B0B', 65, 66)
with assert_raises(Exception):
data = struct.pack('B2B', 65, 66)
data = struct.pack('B1B', 65, 66)

View File

@@ -88,20 +88,48 @@ where
I: Sized + Iterator<Item = char>,
{
let mut codes = vec![];
for c in chars {
while chars.peek().is_some() {
// determine repeat operator:
let repeat = match chars.peek() {
Some('0'..='9') => {
let mut repeat = 0;
while let Some('0'..='9') = chars.peek() {
if let Some(c) = chars.next() {
let current_digit = c.to_digit(10).unwrap();
repeat = repeat * 10 + current_digit;
}
}
Some(repeat)
}
_ => None,
};
// determine format char:
let c = chars.next();
match c {
'b' | 'B' | 'h' | 'H' | 'i' | 'I' | 'l' | 'L' | 'q' | 'Q' | 'f' | 'd' => {
codes.push(FormatCode { code: c })
}
c => {
return Err(format!("Illegal format code {:?}", c));
Some(c) if is_supported_format_character(c) => {
if let Some(repeat) = repeat {
for _ in 0..repeat {
codes.push(FormatCode { code: c })
}
} else {
codes.push(FormatCode { code: c })
}
}
_ => return Err(format!("Illegal format code {:?}", c)),
}
}
Ok(codes)
}
fn is_supported_format_character(c: char) -> bool {
match c {
'b' | 'B' | 'h' | 'H' | 'i' | 'I' | 'l' | 'L' | 'q' | 'Q' | 'f' | 'd' => true,
_ => false,
}
}
fn get_int(vm: &VirtualMachine, arg: &PyObjectRef) -> PyResult<BigInt> {
objint::to_int(vm, arg, &BigInt::from(10))
}