Skip to content

Commit 9a3bd49

Browse files
authored
Merge pull request #3 from hashmismatch/fuzz
Additional fuzz tests for the byte-copying code generator
2 parents 6386b1f + bed628d commit 9a3bd49

File tree

6 files changed

+220
-15
lines changed

6 files changed

+220
-15
lines changed

packed_struct/src/types_num.rs

+12
Original file line numberDiff line numberDiff line change
@@ -650,6 +650,18 @@ fn test_packed_int_msb() {
650650
assert_eq!(val, **unpacked);
651651
}
652652

653+
#[test]
654+
fn test_packed_int_partial() {
655+
let val = 0b10_10101010;
656+
let typed: Integer<u16, Bits10> = val.into();
657+
let endian = typed.as_packed_msb();
658+
let packed = endian.pack();
659+
assert_eq!([0b00000010, 0b10101010], packed);
660+
661+
let unpacked: MsbInteger<_, _, Integer<u16, Bits10>> = MsbInteger::unpack(&packed).unwrap();
662+
assert_eq!(val, **unpacked);
663+
}
664+
653665
#[test]
654666
fn test_packed_int_lsb() {
655667
let val = 0xAABBCCDD;

packed_struct_codegen/src/pack_codegen.rs

+31-10
Original file line numberDiff line numberDiff line change
@@ -188,10 +188,9 @@ fn pack_bits(field: &FieldRegular) -> PackBitsCopy {
188188
}
189189
} else {
190190
let packed_field_len = (field.bit_width as f32 / 8.0).ceil() as usize;
191+
let start_byte = (field.bit_range_rust.start as f32 / 8.0).floor() as usize;
192+
let shift = ((packed_field_len as isize*8) - (field.bit_width as isize)) - (field.bit_range_rust.start as isize - (start_byte as isize * 8));
191193

192-
let start_byte = field.bit_range_rust.start / 8;
193-
let shift = (8 - (field.bit_width as isize)) % 8 - (field.bit_range_rust.start as isize - (start_byte as isize * 8));
194-
195194
let emit_shift = |s: isize| {
196195
if s == 0 {
197196
quote! {}
@@ -203,43 +202,65 @@ fn pack_bits(field: &FieldRegular) -> PackBitsCopy {
203202
}
204203
};
205204

206-
let mut l = field.bit_range_rust.len() as isize;
205+
let mut l = 8 - ((packed_field_len as isize*8) - field.bit_width as isize);
207206
let mut dst_byte = start_byte;
208207

209208
let mut pack = vec![];
210209
let mut unpack = vec![];
211210

211+
let mut bits_to_pack = field.bit_width;
212+
let mut target_bit = field.bit_range.start as usize;
213+
212214
for i in 0..packed_field_len {
213-
let src_mask = ones_u8(l as u8);
214-
215+
let src_mask = ones_u8(l as u8);
215216
let bit_shift = emit_shift(shift);
216217
pack.push(quote! {
218+
let _a = #i;
217219
target[#dst_byte] |= (packed[#i] & #src_mask) #bit_shift;
218220
});
219221

220222
let bit_shift = emit_shift(-shift);
221223
unpack.push(quote! {
224+
let _a = #i;
222225
b[#i] |= (src[#dst_byte] #bit_shift) & #src_mask;
223226
});
224227

225-
if shift < 0 {
226-
let shift = shift + 8;
228+
if shift < 0 && (dst_byte - start_byte) <= packed_field_len {
229+
let shift = (8+shift);
230+
let src_mask = ones_u8(8-shift as u8);
227231

228232
let bit_shift = emit_shift(shift);
229233
pack.push(quote! {
234+
let _b = #i;
230235
target[#dst_byte + 1] |= (((packed[#i] & #src_mask) as u16) #bit_shift) as u8;
231236
});
232237

233238
let bit_shift = emit_shift(-shift);
234239
unpack.push(quote! {
240+
let _b = #i;
235241
b[#i] |= (((src[#dst_byte + 1] as u16) #bit_shift) & #src_mask as u16) as u8;
236242
});
243+
} else if shift > 0 && (dst_byte - start_byte) <= packed_field_len && i < packed_field_len - 1 {
244+
let shift = -(8-shift);
245+
let bit_shift = emit_shift(shift);
246+
let src_mask = !ones_u8(-shift as u8);
247+
248+
pack.push(quote! {
249+
let _c = #i;
250+
target[#dst_byte] |= (((packed[#i + 1] & #src_mask) as u16) #bit_shift) as u8;
251+
});
252+
253+
let bit_shift = emit_shift(-shift);
254+
unpack.push(quote! {
255+
let _c = #i;
256+
b[#i + 1] |= (((src[#dst_byte] as u16) #bit_shift) & #src_mask as u16) as u8;
257+
});
237258
}
238259

239260
dst_byte += 1;
240-
l -= 8;
261+
l += 8;
241262
}
242-
263+
243264
PackBitsCopy {
244265
pack: quote! {
245266
#(#pack)*

packed_struct_tests/tests/packing_bit_positioning.rs

+2-5
Original file line numberDiff line numberDiff line change
@@ -29,19 +29,18 @@ fn test_packing_bit_positions() {
2929
};
3030

3131
let packed = a.pack();
32-
println!("packed: {:?}", packed);
32+
assert_eq!([255], packed);
3333

3434
let unpacked = SmallInts::unpack(&packed).unwrap();
3535
assert_eq!(a, unpacked);
3636
}
3737

3838

39-
/*
4039
#[derive(PackedStruct, PartialEq, Debug)]
4140
#[packed_struct(size_bytes="1", bit_numbering="lsb0")]
4241
pub struct SmallIntsLsb {
4342
#[packed_field(bits="2..0")]
44-
pub val1: UIntBits3,
43+
pub val1: Integer<u8, packed_bits::Bits3>,
4544
#[packed_field(bits="6")]
4645
pub val2: bool
4746
}
@@ -54,7 +53,6 @@ fn test_packing_bit_positions_lsb() {
5453
};
5554

5655
let packed = a.pack();
57-
println!("packed: {:?}", packed);
5856
assert_eq!(&[0b01000111], &packed);
5957

6058
let unpacked = SmallIntsLsb::unpack(&packed).unwrap();
@@ -89,4 +87,3 @@ fn test_packing_byte_position() {
8987

9088
assert_eq!(b, unpacked);
9189
}
92-
*/
+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
extern crate packed_struct;
2+
#[macro_use]
3+
extern crate packed_struct_codegen;
4+
5+
use packed_struct::prelude::*;
6+
7+
#[test]
8+
fn test_serialization_codegen() {
9+
10+
11+
12+
#[derive(PackedStruct, Debug, Default, Copy, Clone)]
13+
#[packed_struct(size_bytes="4", bit_numbering="lsb0", endian="msb")]
14+
pub struct PowerDataObjectFixed {
15+
#[packed_field(bits="31..30")]
16+
pub supply: Integer<u8, packed_bits::Bits2>,
17+
#[packed_field(bits="29")]
18+
pub dual_role_power: bool,
19+
#[packed_field(bits="28")]
20+
pub usb_suspend_supported: bool,
21+
#[packed_field(bits="27")]
22+
pub unconstrained_power: bool,
23+
#[packed_field(bits="26")]
24+
pub usb_communications_capable: bool,
25+
#[packed_field(bits="25")]
26+
pub dual_role_data: bool,
27+
#[packed_field(bits="21..20")]
28+
pub peak_current: Integer<u8, packed_bits::Bits2>,
29+
#[packed_field(bits="19..10")]
30+
pub voltage: Integer<u16, packed_bits::Bits10>,
31+
#[packed_field(bits="9..0")]
32+
pub maximum_current: Integer<u16, packed_bits::Bits10>
33+
}
34+
35+
36+
let mut p: PowerDataObjectFixed = Default::default();
37+
p.dual_role_data = true;
38+
p.voltage = 0b10_11111111.into();
39+
p.maximum_current = 0b10_10101010.into();
40+
41+
let packed = p.pack();
42+
assert_eq!([0b00000010, 0b0000_1011, 0b111111_10, 0b10101010], packed);
43+
44+
let unpacked = PowerDataObjectFixed::unpack(&packed).unwrap();
45+
assert_eq!(unpacked.dual_role_data, true);
46+
assert_eq!(*unpacked.voltage, *p.voltage);
47+
assert_eq!(*unpacked.maximum_current, *p.maximum_current);
48+
49+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
extern crate packed_struct;
2+
#[macro_use]
3+
extern crate packed_struct_codegen;
4+
5+
use packed_struct::prelude::*;
6+
7+
macro_rules! test_int_14 {
8+
($f: ident, $fi: tt) => {
9+
#[test]
10+
fn $f() {
11+
12+
#[derive(PackedStruct, Debug, Default, Copy, Clone, PartialEq)]
13+
#[packed_struct(bit_numbering="msb0", endian="msb")]
14+
pub struct Test {
15+
#[packed_field(bits= $fi )]
16+
pub int1: Integer<u16, packed_bits::Bits14>
17+
}
18+
19+
let roundtrip = |x: u16| {
20+
let mut t: Test = Default::default();
21+
t.int1 = x.into();
22+
let packed = t.pack();
23+
24+
let unpacked = Test::unpack(&packed).unwrap();
25+
assert_eq!(unpacked, t);
26+
};
27+
28+
roundtrip(0b00_101010_10101010);
29+
roundtrip(0b00_010101_01010101);
30+
roundtrip(0b00_111111_11111111);
31+
roundtrip(0b00_111111_01111111);
32+
roundtrip(0b00_111110_11111111);
33+
roundtrip(0b00_111110_01111111);
34+
roundtrip(0b00_100000_00000001);
35+
}
36+
};
37+
}
38+
39+
40+
test_int_14!(test_10_0, "0..");
41+
test_int_14!(test_10_1, "1..");
42+
test_int_14!(test_10_2, "2..");
43+
test_int_14!(test_10_3, "3..");
44+
test_int_14!(test_10_4, "4..");
45+
test_int_14!(test_10_5, "5..");
46+
test_int_14!(test_10_6, "6..");
47+
test_int_14!(test_10_7, "7..");
48+
test_int_14!(test_10_8, "8..");
49+
test_int_14!(test_10_9, "9..");
50+
test_int_14!(test_10_10, "10..");
51+
test_int_14!(test_10_11, "11..");
52+
test_int_14!(test_10_12, "12..");
53+
test_int_14!(test_10_13, "13..");
54+
test_int_14!(test_10_14, "14..");
55+
test_int_14!(test_10_15, "15..");
56+
test_int_14!(test_10_16, "16..");
57+
test_int_14!(test_10_17, "17..");
58+
test_int_14!(test_10_18, "18..");
59+
test_int_14!(test_10_19, "19..");
60+
61+
62+
test_int_14!(test_10_100, "100..");
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
extern crate packed_struct;
2+
#[macro_use]
3+
extern crate packed_struct_codegen;
4+
5+
use packed_struct::prelude::*;
6+
7+
macro_rules! test_int_50 {
8+
($f: ident, $fi: tt) => {
9+
#[test]
10+
fn $f() {
11+
12+
#[derive(PackedStruct, Debug, Default, Copy, Clone, PartialEq)]
13+
#[packed_struct(bit_numbering="msb0", endian="msb")]
14+
pub struct Test {
15+
#[packed_field(bits= $fi )]
16+
pub int1: Integer<u64, packed_bits::Bits50>
17+
}
18+
19+
let roundtrip = |x: u64| {
20+
let mut t: Test = Default::default();
21+
t.int1 = x.into();
22+
let packed = t.pack();
23+
24+
let unpacked = Test::unpack(&packed).unwrap();
25+
assert_eq!(unpacked, t);
26+
};
27+
28+
roundtrip(0b00_101010_10101010);
29+
roundtrip(0b00_010101_01010101);
30+
roundtrip(0b00_111111_11111111);
31+
roundtrip(0b00_111111_01111111);
32+
roundtrip(0b00_111110_11111111);
33+
roundtrip(0b00_111110_01111111);
34+
roundtrip(0b00_100000_00000001);
35+
}
36+
};
37+
}
38+
39+
40+
test_int_50!(test_50_0, "0..");
41+
test_int_50!(test_50_1, "1..");
42+
test_int_50!(test_50_2, "2..");
43+
test_int_50!(test_50_3, "3..");
44+
test_int_50!(test_50_4, "4..");
45+
test_int_50!(test_50_5, "5..");
46+
test_int_50!(test_50_6, "6..");
47+
test_int_50!(test_50_7, "7..");
48+
test_int_50!(test_50_8, "8..");
49+
test_int_50!(test_50_9, "9..");
50+
test_int_50!(test_50_10, "10..");
51+
test_int_50!(test_50_11, "11..");
52+
test_int_50!(test_50_12, "12..");
53+
test_int_50!(test_50_13, "13..");
54+
test_int_50!(test_50_14, "14..");
55+
test_int_50!(test_50_15, "15..");
56+
test_int_50!(test_50_16, "16..");
57+
test_int_50!(test_50_17, "17..");
58+
test_int_50!(test_50_18, "18..");
59+
test_int_50!(test_50_19, "19..");
60+
61+
62+
63+
64+
test_int_50!(test_50_100, "100..");

0 commit comments

Comments
 (0)