Skip to content

Commit 7086ee2

Browse files
mkroeningwrenger
authored andcommitted
Add support for custom inner types
Signed-off-by: Martin Kröning <martin.kroening@eonerc.rwth-aachen.de>
1 parent cc9aae2 commit 7086ee2

File tree

2 files changed

+78
-11
lines changed

2 files changed

+78
-11
lines changed

src/lib.rs

+51-11
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,9 @@ fn bitfield_inner(args: TokenStream, input: TokenStream) -> syn::Result<TokenStr
4747
let input = syn::parse2::<syn::ItemStruct>(input)?;
4848
let Params {
4949
ty,
50+
inner,
51+
into,
52+
from,
5053
bits,
5154
debug,
5255
default,
@@ -66,7 +69,15 @@ fn bitfield_inner(args: TokenStream, input: TokenStream) -> syn::Result<TokenStr
6669
let mut offset = 0;
6770
let mut members = Vec::with_capacity(fields.named.len());
6871
for field in fields.named {
69-
let f = Member::new(ty.clone(), bits, field, offset, order)?;
72+
let f = Member::new(
73+
ty.clone(),
74+
bits,
75+
into.clone(),
76+
from.clone(),
77+
field,
78+
offset,
79+
order,
80+
)?;
7081
offset += f.bits;
7182
members.push(f);
7283
}
@@ -122,11 +133,11 @@ fn bitfield_inner(args: TokenStream, input: TokenStream) -> syn::Result<TokenStr
122133
let conversion = if conversion {
123134
quote! {
124135
/// Convert from bits.
125-
#vis const fn from_bits(bits: #ty) -> Self {
136+
#vis const fn from_bits(bits: #inner) -> Self {
126137
Self(bits)
127138
}
128139
/// Convert into bits.
129-
#vis const fn into_bits(self) -> #ty {
140+
#vis const fn into_bits(self) -> #inner {
130141
self.0
131142
}
132143
}
@@ -138,12 +149,12 @@ fn bitfield_inner(args: TokenStream, input: TokenStream) -> syn::Result<TokenStr
138149
#attrs
139150
#[derive(Copy, Clone)]
140151
#[repr(transparent)]
141-
#vis struct #name(#ty);
152+
#vis struct #name(#inner);
142153

143154
impl #name {
144155
/// Creates a new default initialized bitfield.
145156
#vis const fn new() -> Self {
146-
let mut this = Self(0);
157+
let mut this = Self(#from(0));
147158
#( #defaults )*
148159
this
149160
}
@@ -154,13 +165,13 @@ fn bitfield_inner(args: TokenStream, input: TokenStream) -> syn::Result<TokenStr
154165

155166
#default_impl
156167

157-
impl From<#ty> for #name {
158-
fn from(v: #ty) -> Self {
168+
impl From<#inner> for #name {
169+
fn from(v: #inner) -> Self {
159170
Self(v)
160171
}
161172
}
162-
impl From<#name> for #ty {
163-
fn from(v: #name) -> #ty {
173+
impl From<#name> for #inner {
174+
fn from(v: #name) -> #inner {
164175
v.0
165176
}
166177
}
@@ -174,6 +185,8 @@ struct Member {
174185
offset: usize,
175186
bits: usize,
176187
base_ty: syn::Type,
188+
inner_into: Option<syn::Path>,
189+
inner_from: Option<syn::Path>,
177190
default: TokenStream,
178191
inner: Option<MemberInner>,
179192
}
@@ -191,6 +204,8 @@ impl Member {
191204
fn new(
192205
base_ty: syn::Type,
193206
base_bits: usize,
207+
inner_into: Option<syn::Path>,
208+
inner_from: Option<syn::Path>,
194209
f: syn::Field,
195210
offset: usize,
196211
order: Order,
@@ -259,6 +274,8 @@ impl Member {
259274
offset,
260275
bits,
261276
base_ty,
277+
inner_into,
278+
inner_from,
262279
default,
263280
inner: Some(MemberInner {
264281
ident,
@@ -278,6 +295,8 @@ impl Member {
278295
offset,
279296
bits,
280297
base_ty,
298+
inner_into,
299+
inner_from,
281300
default,
282301
inner: None,
283302
})
@@ -316,6 +335,8 @@ impl ToTokens for Member {
316335
offset,
317336
bits,
318337
base_ty,
338+
inner_into,
339+
inner_from,
319340
default: _,
320341
inner:
321342
Some(MemberInner {
@@ -361,7 +382,7 @@ impl ToTokens for Member {
361382
#[doc = #location]
362383
#vis const fn #ident(&self) -> #ty {
363384
let mask = #base_ty::MAX >> (#base_ty::BITS - Self::#bits_ident as u32);
364-
let this = (self.0 >> Self::#offset_ident) & mask;
385+
let this = (#inner_into(self.0) >> Self::#offset_ident) & mask;
365386
#from
366387
}
367388
});
@@ -378,7 +399,8 @@ impl ToTokens for Member {
378399
let mask = #base_ty::MAX >> (#base_ty::BITS - Self::#bits_ident as u32);
379400
#[allow(unused_comparisons)]
380401
debug_assert!(value <= mask, "value out of bounds");
381-
Self(self.0 & !(mask << Self::#offset_ident) | (value & mask) << Self::#offset_ident)
402+
let bits = #inner_into(self.0) & !(mask << Self::#offset_ident) | (value & mask) << Self::#offset_ident;
403+
Self(#inner_from(bits))
382404
}
383405

384406
#doc
@@ -656,6 +678,9 @@ enum Order {
656678
/// The bitfield macro parameters
657679
struct Params {
658680
ty: syn::Type,
681+
inner: syn::Type,
682+
into: Option<syn::Path>,
683+
from: Option<syn::Path>,
659684
bits: usize,
660685
debug: bool,
661686
default: bool,
@@ -673,6 +698,9 @@ impl Parse for Params {
673698
return Err(s_err(input.span(), "unsupported type"));
674699
}
675700

701+
let mut inner = ty.clone();
702+
let mut from = None;
703+
let mut into = None;
676704
let mut debug = true;
677705
let mut default = true;
678706
let mut order = Order::Lsb;
@@ -683,6 +711,15 @@ impl Parse for Params {
683711
let ident = Ident::parse(input)?;
684712
<Token![=]>::parse(input)?;
685713
match ident.to_string().as_str() {
714+
"inner" => {
715+
inner = input.parse()?;
716+
}
717+
"from" => {
718+
from = Some(input.parse()?);
719+
}
720+
"into" => {
721+
into = Some(input.parse()?);
722+
}
686723
"debug" => {
687724
debug = syn::LitBool::parse(input)?.value;
688725
}
@@ -705,6 +742,9 @@ impl Parse for Params {
705742

706743
Ok(Self {
707744
ty,
745+
inner,
746+
from,
747+
into,
708748
bits,
709749
debug,
710750
default,

tests/test.rs

+27
Original file line numberDiff line numberDiff line change
@@ -398,3 +398,30 @@ fn raw() {
398398
assert_eq!(raw.r#type(), 0xff);
399399
assert_eq!(raw.into_bits(), 0xff);
400400
}
401+
402+
#[test]
403+
fn custom_inner() {
404+
#[bitfield(u32, inner = CustomInner, from = CustomInner::from_inner, into = CustomInner::to_inner)]
405+
#[derive(PartialEq, Eq)]
406+
struct MyBitfield {
407+
data: u32,
408+
}
409+
410+
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
411+
#[repr(transparent)]
412+
struct CustomInner(u32);
413+
414+
impl CustomInner {
415+
const fn to_inner(self) -> u32 {
416+
self.0
417+
}
418+
419+
const fn from_inner(inner: u32) -> Self {
420+
Self(inner)
421+
}
422+
}
423+
424+
let my_bitfield = MyBitfield::new();
425+
assert_eq!(my_bitfield, MyBitfield::from_bits(CustomInner(0)));
426+
assert_eq!(my_bitfield.into_bits(), CustomInner(0));
427+
}

0 commit comments

Comments
 (0)