Skip to content

Commit 530ebcd

Browse files
committed
feat: allowing a custom resolver per raw struct
1 parent 471ddb6 commit 530ebcd

File tree

2 files changed

+49
-3
lines changed

2 files changed

+49
-3
lines changed
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
use raw_struct::{
2+
raw_struct,
3+
Reference,
4+
};
5+
6+
#[test]
7+
fn test_custom_resolver() {
8+
#[allow(dead_code)]
9+
enum Offset {
10+
FieldA,
11+
FieldB,
12+
}
13+
14+
impl Offset {
15+
fn resolve(self) -> u64 {
16+
match self {
17+
Self::FieldA => 0x00,
18+
Self::FieldB => 0x01,
19+
}
20+
}
21+
}
22+
23+
#[raw_struct(resolver = "Offset::resolve")]
24+
struct Dummy {
25+
#[field(Offset::FieldA)]
26+
field_a: u8,
27+
28+
#[field(Offset::FieldB)]
29+
field_b: u8,
30+
}
31+
32+
let data = [0xFFu8, 0x10].as_slice();
33+
let value = Reference::<Dummy, _>::new(&data, 0x00);
34+
assert_eq!(value.field_b(), Ok(0x10));
35+
}

raw_struct_derive/src/derive_raw_struct.rs

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ impl Parse for FieldArgs {
108108
struct StructArgs {
109109
memory: Option<TokenStream>,
110110
inherits: Option<Path>,
111+
resolver: Path,
111112
}
112113

113114
impl Parse for StructArgs {
@@ -118,6 +119,7 @@ impl Parse for StructArgs {
118119
let mut size = None;
119120
let mut memory = None;
120121
let mut inherits = None;
122+
let mut resolver = None;
121123

122124
for kv in &vars {
123125
if kv.path.is_ident("size") {
@@ -138,6 +140,11 @@ impl Parse for StructArgs {
138140
Lit::Str(value) => inherits = Some(value.parse::<Path>()?),
139141
_ => return Err(Error::new(kv.lit.span(), "expected a string")),
140142
}
143+
} else if kv.path.is_ident("resolver") {
144+
match &kv.lit {
145+
Lit::Str(value) => resolver = Some(value.parse::<Path>()?),
146+
_ => return Err(Error::new(kv.lit.span(), "expected a string")),
147+
}
141148
} else {
142149
return Err(Error::new(kv.path.span(), "unknown attribute"));
143150
}
@@ -147,6 +154,7 @@ impl Parse for StructArgs {
147154
Ok(Self {
148155
memory: memory.or(size),
149156
inherits,
157+
resolver: resolver.unwrap_or_else(|| syn::parse_quote! { ::core::convert::identity }),
150158
})
151159
}
152160
}
@@ -201,7 +209,10 @@ fn extract_struct_fields(fields: &Fields) -> Result<Vec<(FieldArgs, Field)>> {
201209
Ok(result)
202210
}
203211

204-
fn generate_reference_accessors(fields: &[(FieldArgs, Field)]) -> Result<TokenStream> {
212+
fn generate_reference_accessors(
213+
resolver: &Path,
214+
fields: &[(FieldArgs, Field)],
215+
) -> Result<TokenStream> {
205216
let mut result = Vec::<TokenStream>::with_capacity(fields.len() * 2);
206217

207218
for (field_args, field) in fields.iter() {
@@ -234,7 +245,7 @@ fn generate_reference_accessors(fields: &[(FieldArgs, Field)]) -> Result<TokenSt
234245
#vis fn #name (&self) -> Result<#ty, raw_struct::MemoryDecodeError<#IDENT_MEMORY_VIEW_T::AccessError, <#ty as raw_struct::FromMemoryView>::DecodeError>> {
235246
use raw_struct::{ ViewableImplementation, FromMemoryView };
236247

237-
let offset = (#offset) as u64;
248+
let offset = #resolver(#offset) as u64;
238249
<#ty as FromMemoryView>::read_object(self.memory_view(), offset)
239250
}
240251
});
@@ -301,7 +312,7 @@ pub fn raw_struct(attr: TokenStream, input: TokenStream) -> Result<TokenStream>
301312
let struct_name_str = format!("{}", target.ident);
302313

303314
let fields = extract_struct_fields(&target.fields)?;
304-
let accessors = generate_reference_accessors(&fields)?;
315+
let accessors = generate_reference_accessors(&args.resolver, &fields)?;
305316

306317
let (vanilla_impl_generics, vanilla_ty_generics, vanilla_where_clause) =
307318
target.generics.split_for_impl();

0 commit comments

Comments
 (0)