Skip to content

Commit e8bb4bb

Browse files
Merge pull request RustPython#1549 from palaviv/refactor-pystruct
pystruct refactor
2 parents 618c62d + d0184a7 commit e8bb4bb

File tree

4 files changed

+69
-134
lines changed

4 files changed

+69
-134
lines changed

Cargo.lock

Lines changed: 23 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/snippets/stdlib_struct.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,3 +38,6 @@
3838
data = struct.pack('B2B', 65, 66)
3939

4040
data = struct.pack('B1B', 65, 66)
41+
42+
with assert_raises(Exception):
43+
struct.pack('<IH', "14", 12)

vm/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ nix = "0.15.0"
6565
wtf8 = "0.0.3"
6666
arr_macro = "0.1.2"
6767
csv = "1.1.1"
68+
paste = "0.1"
6869

6970
flame = { version = "0.2", optional = true }
7071
flamer = { version = "0.3", optional = true }

vm/src/stdlib/pystruct.rs

Lines changed: 42 additions & 134 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,10 @@ use std::io::{Cursor, Read, Write};
1313
use std::iter::Peekable;
1414

1515
use byteorder::{ReadBytesExt, WriteBytesExt};
16-
use num_bigint::BigInt;
17-
use num_traits::ToPrimitive;
1816

1917
use crate::function::PyFuncArgs;
20-
use crate::obj::{objbool, objbytes, objfloat, objint, objstr, objtype};
21-
use crate::pyobject::{PyObjectRef, PyResult};
18+
use crate::obj::{objbytes, objstr, objtype};
19+
use crate::pyobject::{PyObjectRef, PyResult, TryFromObject};
2220
use crate::VirtualMachine;
2321

2422
#[derive(Debug)]
@@ -130,144 +128,54 @@ fn is_supported_format_character(c: char) -> bool {
130128
}
131129
}
132130

133-
fn get_int(vm: &VirtualMachine, arg: &PyObjectRef) -> PyResult<BigInt> {
134-
objint::to_int(vm, arg, &BigInt::from(10))
135-
}
136-
137-
fn pack_i8(vm: &VirtualMachine, arg: &PyObjectRef, data: &mut dyn Write) -> PyResult<()> {
138-
let v = get_int(vm, arg)?.to_i8().unwrap();
139-
data.write_i8(v).unwrap();
140-
Ok(())
131+
macro_rules! make_pack_no_endianess {
132+
($T:ty) => {
133+
paste::item! {
134+
fn [<pack_ $T>](vm: &VirtualMachine, arg: &PyObjectRef, data: &mut dyn Write) -> PyResult<()> {
135+
let v = $T::try_from_object(vm, arg.clone())?;
136+
data.[<write_$T>](v).unwrap();
137+
Ok(())
138+
}
139+
}
140+
};
141+
}
142+
143+
macro_rules! make_pack_with_endianess {
144+
($T:ty) => {
145+
paste::item! {
146+
fn [<pack_ $T>]<Endianness>(vm: &VirtualMachine, arg: &PyObjectRef, data: &mut dyn Write) -> PyResult<()>
147+
where
148+
Endianness: byteorder::ByteOrder,
149+
{
150+
let v = $T::try_from_object(vm, arg.clone())?;
151+
data.[<write_$T>]::<Endianness>(v).unwrap();
152+
Ok(())
153+
}
154+
}
155+
};
141156
}
142157

143-
fn pack_u8(vm: &VirtualMachine, arg: &PyObjectRef, data: &mut dyn Write) -> PyResult<()> {
144-
let v = get_int(vm, arg)?.to_u8().unwrap();
145-
data.write_u8(v).unwrap();
146-
Ok(())
147-
}
158+
make_pack_no_endianess!(i8);
159+
make_pack_no_endianess!(u8);
160+
make_pack_with_endianess!(i16);
161+
make_pack_with_endianess!(u16);
162+
make_pack_with_endianess!(i32);
163+
make_pack_with_endianess!(u32);
164+
make_pack_with_endianess!(i64);
165+
make_pack_with_endianess!(u64);
166+
make_pack_with_endianess!(f32);
167+
make_pack_with_endianess!(f64);
148168

149169
fn pack_bool(vm: &VirtualMachine, arg: &PyObjectRef, data: &mut dyn Write) -> PyResult<()> {
150-
if objtype::isinstance(&arg, &vm.ctx.bool_type()) {
151-
let v = if objbool::get_value(arg) { 1 } else { 0 };
152-
data.write_u8(v).unwrap();
153-
Ok(())
170+
let v = if bool::try_from_object(vm, arg.clone())? {
171+
1
154172
} else {
155-
Err(vm.new_type_error("Expected boolean".to_string()))
156-
}
157-
}
158-
159-
fn pack_i16<Endianness>(
160-
vm: &VirtualMachine,
161-
arg: &PyObjectRef,
162-
data: &mut dyn Write,
163-
) -> PyResult<()>
164-
where
165-
Endianness: byteorder::ByteOrder,
166-
{
167-
let v = get_int(vm, arg)?.to_i16().unwrap();
168-
data.write_i16::<Endianness>(v).unwrap();
169-
Ok(())
170-
}
171-
172-
fn pack_u16<Endianness>(
173-
vm: &VirtualMachine,
174-
arg: &PyObjectRef,
175-
data: &mut dyn Write,
176-
) -> PyResult<()>
177-
where
178-
Endianness: byteorder::ByteOrder,
179-
{
180-
let v = get_int(vm, arg)?.to_u16().unwrap();
181-
data.write_u16::<Endianness>(v).unwrap();
182-
Ok(())
183-
}
184-
185-
fn pack_i32<Endianness>(
186-
vm: &VirtualMachine,
187-
arg: &PyObjectRef,
188-
data: &mut dyn Write,
189-
) -> PyResult<()>
190-
where
191-
Endianness: byteorder::ByteOrder,
192-
{
193-
let v = get_int(vm, arg)?.to_i32().unwrap();
194-
data.write_i32::<Endianness>(v).unwrap();
195-
Ok(())
196-
}
197-
198-
fn pack_u32<Endianness>(
199-
vm: &VirtualMachine,
200-
arg: &PyObjectRef,
201-
data: &mut dyn Write,
202-
) -> PyResult<()>
203-
where
204-
Endianness: byteorder::ByteOrder,
205-
{
206-
let v = get_int(vm, arg)?.to_u32().unwrap();
207-
data.write_u32::<Endianness>(v).unwrap();
208-
Ok(())
209-
}
210-
211-
fn pack_i64<Endianness>(
212-
vm: &VirtualMachine,
213-
arg: &PyObjectRef,
214-
data: &mut dyn Write,
215-
) -> PyResult<()>
216-
where
217-
Endianness: byteorder::ByteOrder,
218-
{
219-
let v = get_int(vm, arg)?.to_i64().unwrap();
220-
data.write_i64::<Endianness>(v).unwrap();
221-
Ok(())
222-
}
223-
224-
fn pack_u64<Endianness>(
225-
vm: &VirtualMachine,
226-
arg: &PyObjectRef,
227-
data: &mut dyn Write,
228-
) -> PyResult<()>
229-
where
230-
Endianness: byteorder::ByteOrder,
231-
{
232-
let v = get_int(vm, arg)?.to_u64().unwrap();
233-
data.write_u64::<Endianness>(v).unwrap();
234-
Ok(())
235-
}
236-
237-
fn pack_f32<Endianness>(
238-
vm: &VirtualMachine,
239-
arg: &PyObjectRef,
240-
data: &mut dyn Write,
241-
) -> PyResult<()>
242-
where
243-
Endianness: byteorder::ByteOrder,
244-
{
245-
let v = get_float(vm, arg)? as f32;
246-
data.write_f32::<Endianness>(v).unwrap();
247-
Ok(())
248-
}
249-
250-
fn pack_f64<Endianness>(
251-
vm: &VirtualMachine,
252-
arg: &PyObjectRef,
253-
data: &mut dyn Write,
254-
) -> PyResult<()>
255-
where
256-
Endianness: byteorder::ByteOrder,
257-
{
258-
let v = get_float(vm, arg)?;
259-
data.write_f64::<Endianness>(v).unwrap();
173+
0
174+
};
175+
data.write_u8(v).unwrap();
260176
Ok(())
261177
}
262178

263-
fn get_float(vm: &VirtualMachine, arg: &PyObjectRef) -> PyResult<f64> {
264-
if objtype::isinstance(&arg, &vm.ctx.float_type()) {
265-
Ok(objfloat::get_value(arg))
266-
} else {
267-
Err(vm.new_type_error("Expected float".to_string()))
268-
}
269-
}
270-
271179
fn pack_item<Endianness>(
272180
vm: &VirtualMachine,
273181
code: &FormatCode,

0 commit comments

Comments
 (0)