Skip to content

Commit 69be66c

Browse files
committed
Add compile-time error for seek attributes on DekuSize fields
1 parent 798c0bb commit 69be66c

File tree

5 files changed

+85
-0
lines changed

5 files changed

+85
-0
lines changed

deku-derive/src/macros/deku_size.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,18 @@ fn emit_struct(input: &DekuData) -> Result<TokenStream, syn::Error> {
133133
fields,
134134
} = DekuDataStruct::try_from(input)?;
135135

136+
for field in fields.iter().copied() {
137+
if field_has_seek_attributes(field) {
138+
let field_name = field.ident.as_ref()
139+
.map(|i| i.to_string())
140+
.unwrap_or_else(|| "unnamed field".to_string());
141+
return Err(syn::Error::new(
142+
field.ty.span(),
143+
format!("DekuSize cannot be derived for types with seek attributes on field '{}'. Seek operations make size unpredictable.", field_name),
144+
));
145+
}
146+
}
147+
136148
let size_calculation = calculate_fields_size(fields.iter().copied(), &crate_);
137149

138150
let (imp_generics, ty_generics, where_clause) = input.generics.split_for_impl();
@@ -171,6 +183,20 @@ fn emit_enum(input: &DekuData) -> Result<TokenStream, syn::Error> {
171183
id_args: _,
172184
} = DekuDataEnum::try_from(input)?;
173185

186+
for variant in variants.iter() {
187+
for field in variant.fields.iter() {
188+
if field_has_seek_attributes(field) {
189+
let field_name = field.ident.as_ref()
190+
.map(|i| i.to_string())
191+
.unwrap_or_else(|| "unnamed field".to_string());
192+
return Err(syn::Error::new(
193+
field.ty.span(),
194+
format!("DekuSize cannot be derived for types with seek attributes on field '{}'. Seek operations make size unpredictable.", field_name),
195+
));
196+
}
197+
}
198+
}
199+
174200
let discriminant_size = calculate_discriminant_size(input, id, id_type, &crate_);
175201

176202
let variant_sizes = variants
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
use deku::prelude::*;
2+
3+
#[derive(DekuRead, DekuWrite, DekuSize)]
4+
struct SeekFieldStruct {
5+
offset: u8,
6+
#[deku(seek_from_current = "*offset")]
7+
field: u8,
8+
}
9+
10+
fn main() {
11+
let _ = SeekFieldStruct::SIZE_BITS;
12+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
error: DekuSize cannot be derived for types with seek attributes on field 'field'. Seek operations make size unpredictable.
2+
--> tests/test_compile/cases/deku_size_seek_field.rs:7:12
3+
|
4+
7 | field: u8,
5+
| ^^
6+
7+
error[E0599]: no associated item named `SIZE_BITS` found for struct `SeekFieldStruct` in the current scope
8+
--> tests/test_compile/cases/deku_size_seek_field.rs:11:30
9+
|
10+
4 | struct SeekFieldStruct {
11+
| ---------------------- associated item `SIZE_BITS` not found for this struct
12+
...
13+
11 | let _ = SeekFieldStruct::SIZE_BITS;
14+
| ^^^^^^^^^ associated item not found in `SeekFieldStruct`
15+
|
16+
= help: items from traits can only be used if the trait is implemented and in scope
17+
= note: the following trait defines an item `SIZE_BITS`, perhaps you need to implement it:
18+
candidate #1: `deku::DekuSize`
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
use deku::prelude::*;
2+
3+
#[derive(DekuRead, DekuWrite, DekuSize)]
4+
struct SeekRewindStruct {
5+
#[deku(seek_rewind)]
6+
field: u8,
7+
}
8+
9+
fn main() {
10+
let _ = SeekRewindStruct::SIZE_BITS;
11+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
error: DekuSize cannot be derived for types with seek attributes on field 'field'. Seek operations make size unpredictable.
2+
--> tests/test_compile/cases/deku_size_seek_rewind.rs:6:12
3+
|
4+
6 | field: u8,
5+
| ^^
6+
7+
error[E0599]: no associated item named `SIZE_BITS` found for struct `SeekRewindStruct` in the current scope
8+
--> tests/test_compile/cases/deku_size_seek_rewind.rs:10:31
9+
|
10+
4 | struct SeekRewindStruct {
11+
| ----------------------- associated item `SIZE_BITS` not found for this struct
12+
...
13+
10 | let _ = SeekRewindStruct::SIZE_BITS;
14+
| ^^^^^^^^^ associated item not found in `SeekRewindStruct`
15+
|
16+
= help: items from traits can only be used if the trait is implemented and in scope
17+
= note: the following trait defines an item `SIZE_BITS`, perhaps you need to implement it:
18+
candidate #1: `deku::DekuSize`

0 commit comments

Comments
 (0)