Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions src/attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ pub struct Params {
pub into: Option<syn::Path>,
pub from: Option<syn::Path>,
pub bits: usize,
pub binread: Enable,
pub binwrite: Enable,
pub new: Enable,
pub clone: Enable,
pub debug: Enable,
Expand All @@ -41,6 +43,8 @@ impl Parse for Params {
into: None,
from: None,
bits,
binread: Enable::No,
binwrite: Enable::No,
new: Enable::Yes,
clone: Enable::Yes,
debug: Enable::Yes,
Expand Down Expand Up @@ -93,6 +97,17 @@ impl Parse for Params {
"conversion" => {
ret.conversion = syn::LitBool::parse(input)?.value;
}
"binrw" => {
let enable: Enable = input.parse()?;
ret.binread = enable.clone();
ret.binwrite = enable;
}
"binread" => {
ret.binread = input.parse()?;
}
"binwrite" => {
ret.binwrite = input.parse()?;
}
_ => return Err(s_err(ident.span(), "unknown argument")),
};
}
Expand Down
11 changes: 11 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ fn s_err(span: proc_macro2::Span, msg: impl fmt::Display) -> syn::Error {
/// - `from` to specify a conversion function from repr to the bitfield's integer type
/// - `into` to specify a conversion function from the bitfield's integer type to repr
/// - `new` to disable the `new` function generation
/// - `binread` to enable the `BinRead` trait generation
/// - `binwrite` to enable the `BinWrite` trait generation
/// - `binrw` to enable both `BinRead` and `BinWrite` trait generation
/// - `clone` to disable the `Clone` trait generation
/// - `debug` to disable the `Debug` trait generation
/// - `defmt` to enable the `defmt::Format` trait generation
Expand Down Expand Up @@ -64,6 +67,8 @@ fn bitfield_inner(args: TokenStream, input: TokenStream) -> syn::Result<TokenStr
into,
from,
bits,
binread,
binwrite,
new,
clone,
debug,
Expand Down Expand Up @@ -133,6 +138,12 @@ fn bitfield_inner(args: TokenStream, input: TokenStream) -> syn::Result<TokenStr
if let Some(cfg) = hash.cfg() {
impl_debug.extend(traits::hash(&name, &members, cfg));
}
if let Some(cfg) = binread.cfg() {
impl_debug.extend(traits::binread(&name, &repr, cfg));
}
if let Some(cfg) = binwrite.cfg() {
impl_debug.extend(traits::binwrite(&name, cfg));
}

let defaults = members.iter().map(Member::default).collect::<Vec<_>>();

Expand Down
66 changes: 66 additions & 0 deletions src/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -131,3 +131,69 @@ pub fn hash(
}
}
}

/// Implements the `binrw::BinWrite` trait for the given bitfield struct.
pub fn binwrite(
name: &syn::Ident,
cfg: Option<TokenStream>,
) -> TokenStream {
let attr = cfg.map(|cfg| quote!(#[cfg(#cfg)]));

quote! {
#attr
impl binrw::BinWrite for #name {
type Args<'a> = ();

fn write_options<W: binrw::io::Write + binrw::io::Seek>(
&self,
writer: &mut W,
endian: binrw::Endian,
args: Self::Args<'_>,
) -> binrw::BinResult<()> {
let raw = self.into_bits();

let bytes = match endian {
binrw::Endian::Big => raw.to_be_bytes(),
binrw::Endian::Little => raw.to_le_bytes(),
};

writer.write_all(&bytes)?;

Ok(())
}
}
}
}

/// Implements the `binrw::BinRead` trait for the given bitfield struct.
pub fn binread(
name: &syn::Ident,
repr: &syn::Type,
cfg: Option<TokenStream>,
) -> TokenStream {
let attr = cfg.map(|cfg| quote!(#[cfg(#cfg)]));

quote! {
#attr
impl binrw::BinRead for #name {
type Args<'a> = ();

fn read_options<R: binrw::io::Read + binrw::io::Seek>(
reader: &mut R,
endian: binrw::Endian,
args: Self::Args<'_>,
) -> binrw::BinResult<Self> {
let mut buf = [0u8; core::mem::size_of::<#repr>()];

reader.read_exact(&mut buf)?;

let raw = match endian {
binrw::Endian::Big => <#repr>::from_be_bytes(buf),
binrw::Endian::Little => <#repr>::from_le_bytes(buf),
};

Ok(Self::from_bits(raw))
}
}
}
}