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

Skip to content

Commit b688927

Browse files
committed
Add padding size calculation to DekuSize
1 parent 7a112e2 commit b688927

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
@@ -35,6 +35,21 @@ fn calculate_fields_size<'a>(
3535
components.push(quote! { #magic_size });
3636
}
3737

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

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

101+
/// Calculate padding size (with bits feature)
102+
#[cfg(feature = "bits")]
103+
fn calculate_padding_size(
104+
pad_bits: Option<&TokenStream>,
105+
pad_bytes: Option<&TokenStream>,
106+
) -> Option<TokenStream> {
107+
match (pad_bits, pad_bytes) {
108+
(Some(bits), Some(bytes)) => Some(quote! { (#bits) + ((#bytes) * 8) }),
109+
(Some(bits), None) => Some(quote! { (#bits) }),
110+
(None, Some(bytes)) => Some(quote! { ((#bytes) * 8) }),
111+
(None, None) => None,
112+
}
113+
}
114+
115+
/// Calculate padding size (without bits feature)
116+
#[cfg(not(feature = "bits"))]
117+
fn calculate_padding_size(pad_bytes: Option<&TokenStream>) -> Option<TokenStream> {
118+
match pad_bytes {
119+
Some(bytes) => Some(quote! { ((#bytes) * 8) }),
120+
None => None,
121+
}
122+
}
123+
71124
/// Add DekuSize trait bounds to where clause for fields that need them
72125
fn add_field_bounds<'a>(
73126
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)