Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 66bc051

Browse files
committed
Add padding size calculation to DekuSize
1 parent 9410d9d commit 66bc051

2 files changed

Lines changed: 168 additions & 0 deletions

File tree

deku-derive/src/macros/deku_size.rs

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,21 @@ fn calculate_fields_size<'a>(
3636
components.push(quote! { #magic_size });
3737
}
3838

39+
#[cfg(feature = "bits")]
40+
{
41+
if let Some(pad_before) =
42+
calculate_padding_size(f.pad_bits_before.as_ref(), f.pad_bytes_before.as_ref())
43+
{
44+
components.push(pad_before);
45+
}
46+
}
47+
#[cfg(not(feature = "bits"))]
48+
{
49+
if let Some(pad_before) = calculate_padding_size(f.pad_bytes_before.as_ref()) {
50+
components.push(pad_before);
51+
}
52+
}
53+
3954
let field_type = &f.ty;
4055
#[cfg(feature = "bits")]
4156
if let Some(bits) = &f.bits {
@@ -53,6 +68,21 @@ fn calculate_fields_size<'a>(
5368
components.push(quote! { <#field_type as ::#crate_::DekuSize>::SIZE_BITS });
5469
}
5570

71+
#[cfg(feature = "bits")]
72+
{
73+
if let Some(pad_after) =
74+
calculate_padding_size(f.pad_bits_after.as_ref(), f.pad_bytes_after.as_ref())
75+
{
76+
components.push(pad_after);
77+
}
78+
}
79+
#[cfg(not(feature = "bits"))]
80+
{
81+
if let Some(pad_after) = calculate_padding_size(f.pad_bytes_after.as_ref()) {
82+
components.push(pad_after);
83+
}
84+
}
85+
5686
if components.is_empty() {
5787
None
5888
} else {
@@ -85,6 +115,29 @@ fn calculate_magic_size(magic: &syn::LitByteStr) -> TokenStream {
85115
quote! { #magic_len * 8 }
86116
}
87117

118+
/// Calculate padding size (with bits feature)
119+
#[cfg(feature = "bits")]
120+
fn calculate_padding_size(
121+
pad_bits: Option<&TokenStream>,
122+
pad_bytes: Option<&TokenStream>,
123+
) -> Option<TokenStream> {
124+
match (pad_bits, pad_bytes) {
125+
(Some(bits), Some(bytes)) => Some(quote! { (#bits) + ((#bytes) * 8) }),
126+
(Some(bits), None) => Some(quote! { (#bits) }),
127+
(None, Some(bytes)) => Some(quote! { ((#bytes) * 8) }),
128+
(None, None) => None,
129+
}
130+
}
131+
132+
/// Calculate padding size (without bits feature)
133+
#[cfg(not(feature = "bits"))]
134+
fn calculate_padding_size(pad_bytes: Option<&TokenStream>) -> Option<TokenStream> {
135+
match pad_bytes {
136+
Some(bytes) => Some(quote! { ((#bytes) * 8) }),
137+
None => None,
138+
}
139+
}
140+
88141
/// Add DekuSize trait bounds to where clause for fields that need them
89142
fn add_field_bounds<'a>(
90143
where_clause: &mut Option<syn::WhereClause>,

tests/test_size.rs

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -562,3 +562,118 @@ fn test_nested_struct_with_magic() {
562562
assert_eq!(InnerWithMagic::SIZE_BYTES, Some(4));
563563
assert_eq!(OuterWithMagic::SIZE_BYTES, Some(8));
564564
}
565+
566+
#[test]
567+
fn test_struct_with_pad_bytes_before() {
568+
#[derive(DekuRead, DekuWrite, DekuSize)]
569+
struct PadBeforeStruct {
570+
field_a: u8,
571+
#[deku(pad_bytes_before = "2")]
572+
field_b: u8,
573+
}
574+
575+
assert_eq!(PadBeforeStruct::SIZE_BYTES, Some(4));
576+
assert_eq!(PadBeforeStruct::SIZE_BITS, 32);
577+
}
578+
579+
#[test]
580+
fn test_struct_with_pad_bytes_after() {
581+
#[derive(DekuRead, DekuWrite, DekuSize)]
582+
struct PadAfterStruct {
583+
#[deku(pad_bytes_after = "3")]
584+
field_a: u8,
585+
field_b: u8,
586+
}
587+
588+
assert_eq!(PadAfterStruct::SIZE_BYTES, Some(5));
589+
assert_eq!(PadAfterStruct::SIZE_BITS, 40);
590+
}
591+
592+
#[test]
593+
fn test_struct_with_pad_bytes_before_and_after() {
594+
#[derive(DekuRead, DekuWrite, DekuSize)]
595+
struct PadBothStruct {
596+
#[deku(pad_bytes_before = "1", pad_bytes_after = "2")]
597+
field_a: u8,
598+
field_b: u16,
599+
}
600+
601+
assert_eq!(PadBothStruct::SIZE_BYTES, Some(6));
602+
assert_eq!(PadBothStruct::SIZE_BITS, 48);
603+
}
604+
605+
#[test]
606+
#[cfg(feature = "bits")]
607+
fn test_struct_with_pad_bits_before() {
608+
#[derive(DekuRead, DekuWrite, DekuSize)]
609+
#[deku(endian = "big")]
610+
struct PadBitsBefore {
611+
#[deku(bits = 4)]
612+
field_a: u8,
613+
#[deku(pad_bits_before = "4")]
614+
#[deku(bits = 4)]
615+
field_b: u8,
616+
}
617+
618+
assert_eq!(PadBitsBefore::SIZE_BITS, 12);
619+
assert_eq!(PadBitsBefore::SIZE_BYTES, None);
620+
}
621+
622+
#[test]
623+
#[cfg(feature = "bits")]
624+
fn test_struct_with_pad_bits_after() {
625+
#[derive(DekuRead, DekuWrite, DekuSize)]
626+
#[deku(endian = "big")]
627+
struct PadBitsAfter {
628+
#[deku(bits = 3, pad_bits_after = "5")]
629+
field_a: u8,
630+
field_b: u8,
631+
}
632+
633+
assert_eq!(PadBitsAfter::SIZE_BITS, 16);
634+
assert_eq!(PadBitsAfter::SIZE_BYTES, Some(2));
635+
}
636+
637+
#[test]
638+
#[cfg(feature = "bits")]
639+
fn test_struct_with_mixed_padding() {
640+
#[derive(DekuRead, DekuWrite, DekuSize)]
641+
#[deku(endian = "big")]
642+
struct MixedPadding {
643+
#[deku(pad_bits_before = "2", pad_bytes_before = "1")]
644+
#[deku(bits = 6)]
645+
field_a: u8,
646+
field_b: u8,
647+
}
648+
649+
assert_eq!(MixedPadding::SIZE_BITS, 24);
650+
assert_eq!(MixedPadding::SIZE_BYTES, Some(3));
651+
}
652+
653+
#[test]
654+
fn test_struct_without_padding() {
655+
#[derive(DekuRead, DekuWrite, DekuSize)]
656+
struct NoPaddingStruct {
657+
field_a: u8,
658+
field_b: u16,
659+
}
660+
661+
assert_eq!(NoPaddingStruct::SIZE_BYTES, Some(3));
662+
assert_eq!(NoPaddingStruct::SIZE_BITS, 24);
663+
}
664+
665+
#[test]
666+
fn test_multiple_fields_with_padding() {
667+
#[derive(DekuRead, DekuWrite, DekuSize)]
668+
struct MultiplePadding {
669+
#[deku(pad_bytes_before = "1")]
670+
field_a: u8,
671+
#[deku(pad_bytes_after = "2")]
672+
field_b: u8,
673+
#[deku(pad_bytes_before = "1", pad_bytes_after = "1")]
674+
field_c: u8,
675+
}
676+
677+
assert_eq!(MultiplePadding::SIZE_BYTES, Some(8));
678+
assert_eq!(MultiplePadding::SIZE_BITS, 64);
679+
}

0 commit comments

Comments
 (0)