Skip to content

Commit e86e9e6

Browse files
czalojcsnover
authored andcommitted
Small write impl
1 parent d243f6e commit e86e9e6

File tree

3 files changed

+59
-1
lines changed

3 files changed

+59
-1
lines changed

binrw/tests/derive/write/padding.rs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,3 +73,37 @@ fn padding_one_way() {
7373

7474
assert_eq!(x.into_inner(), data);
7575
}
76+
77+
#[test]
78+
fn padding_struct() {
79+
#[derive(BinRead, BinWrite)]
80+
#[brw(pad_size_to = 20)]
81+
struct Test {
82+
#[brw(pad_before = 0x2_u32, align_after = 0x8)]
83+
x: u8,
84+
85+
#[brw(align_before = 0x4_u32, pad_after = 0x3_u32)]
86+
y: u8,
87+
88+
#[brw(pad_size_to = 0x6_u32)]
89+
z: u32,
90+
}
91+
92+
let data = &[
93+
/* pad_before: */ 0, 0, /* x */ 1, /* align: */ 0, 0, 0, 0, 0,
94+
/* align_before: (none)*/ /* y */ 2, /* pad_after: */ 0, 0, 0, /* z */ 0xef,
95+
0xcd, 0xab, 0, /* pad_size_to */ 0, 0, /* struct padding */ 0, 0,
96+
];
97+
98+
let mut x = Cursor::new(Vec::new());
99+
100+
Test {
101+
x: 1,
102+
y: 2,
103+
z: 0xabcdef,
104+
}
105+
.write_options(&mut x, Endian::Little, ())
106+
.unwrap();
107+
108+
assert_eq!(x.into_inner(), data);
109+
}

binrw_derive/src/binrw/codegen/sanitization.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ ident_str! {
7474
pub(crate) READ_FUNCTION = "__binrw_generated_read_function";
7575
pub(crate) WRITE_FUNCTION = "__binrw_generated_write_function";
7676
pub(crate) BEFORE_POS = "__binrw_generated_before_pos";
77+
pub(crate) STRUCT_POS = "__binrw_generated_struct_pos";
7778
pub(crate) DBG_EPRINTLN = from_crate!(__private::eprintln);
7879
}
7980

binrw_derive/src/binrw/codegen/write_options/struct.rs

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use super::{prelude::PreludeGenerator, struct_field::write_field};
22
use crate::binrw::{
3-
codegen::sanitization::{THIS, WRITER},
3+
codegen::sanitization::{SEEK_TRAIT, STRUCT_POS, THIS, WRITER, WRITE_ZEROES},
44
parser::{Input, Struct},
55
};
66
use proc_macro2::TokenStream;
@@ -10,6 +10,7 @@ use syn::Ident;
1010
pub(super) fn generate_struct(input: &Input, name: Option<&Ident>, st: &Struct) -> TokenStream {
1111
StructGenerator::new(input, st, name, &input.stream_ident_or(WRITER))
1212
.write_fields()
13+
.wrap_pad_size()
1314
.prefix_prelude()
1415
.prefix_borrow_fields()
1516
.prefix_imports()
@@ -59,6 +60,28 @@ impl<'input> StructGenerator<'input> {
5960
self
6061
}
6162

63+
fn wrap_pad_size(mut self) -> Self {
64+
if let Some(size) = &self.st.pad_size_to {
65+
let writer_var = self.writer_var;
66+
let out = self.out;
67+
self.out = quote! {
68+
let #STRUCT_POS = #SEEK_TRAIT::stream_position(#writer_var)?;
69+
#out
70+
{
71+
let pad_to_size = (#size) as u64;
72+
let after_pos = #SEEK_TRAIT::stream_position(#writer_var)?;
73+
if let Some(size) = after_pos.checked_sub(#STRUCT_POS) {
74+
if let Some(padding) = pad_to_size.checked_sub(size) {
75+
#WRITE_ZEROES(#writer_var, padding)?;
76+
}
77+
}
78+
}
79+
};
80+
}
81+
82+
self
83+
}
84+
6285
pub(super) fn write_fields(mut self) -> Self {
6386
let write_fields = self
6487
.st

0 commit comments

Comments
 (0)