Skip to content

Commit c0156c8

Browse files
committed
🚀 Release 5.6
1 parent 35b324e commit c0156c8

File tree

3 files changed

+29
-28
lines changed

3 files changed

+29
-28
lines changed

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "bitfield-struct"
3-
version = "0.5.5"
3+
version = "0.5.6"
44
edition = "2021"
55
authors = ["Lars Wrenger <lars@wrenger.net>"]
66
description = "Struct-like procedural macro for bitfields."

src/lib.rs

Lines changed: 27 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
// Generate docs from readme
22
#![doc = include_str!("../README.md")]
3-
43
#![warn(clippy::unwrap_used)]
54

65
use proc_macro as pc;
@@ -29,8 +28,8 @@ use syn::Token;
2928
/// - the number of bits
3029
/// - `access` to specify the access mode (RW, RO, WO, None)
3130
/// - `default` to set a default value
32-
/// - `into` to specify a conversion from the underlying type to the field type
33-
/// - `from` to specify a conversion from the field type to the underlying type
31+
/// - `into` to specify a conversion function from the field type to the bitfield type
32+
/// - `from` to specify a conversion function from the bitfield type to the field type
3433
#[proc_macro_attribute]
3534
pub fn bitfield(args: pc::TokenStream, input: pc::TokenStream) -> pc::TokenStream {
3635
match bitfield_inner(args.into(), input.into()) {
@@ -51,7 +50,6 @@ fn bitfield_inner(args: TokenStream, input: TokenStream) -> syn::Result<TokenStr
5150

5251
let span = input.fields.span();
5352
let name = input.ident;
54-
let name_str = name.to_string();
5553
let vis = input.vis;
5654
let attrs: TokenStream = input.attrs.iter().map(ToTokens::to_token_stream).collect();
5755

@@ -91,7 +89,7 @@ fn bitfield_inner(args: TokenStream, input: TokenStream) -> syn::Result<TokenStr
9189
quote! {
9290
impl core::fmt::Debug for #name {
9391
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
94-
f.debug_struct(#name_str)
92+
f.debug_struct(stringify!(#name))
9593
#( #debug_fields )*
9694
.finish()
9795
}
@@ -484,49 +482,52 @@ fn parse_field(
484482
}
485483
ret.bits = bits;
486484
}
487-
// padding
488-
if ignore && (into.is_some() || from.is_some()) {
489-
return Err(syn::Error::new(
490-
default.span(),
491-
"'into' and 'from' are not supported on padding",
492-
));
493-
}
494485

495-
// Ensure padding fields remain inaccesible
496-
if ignore && access.is_some_and(|mode| mode != Access::None) {
497-
return Err(syn::Error::new(
498-
default.span(),
499-
"'access' may only be 'None' (or unset) for padding",
500-
));
486+
// read/write access
487+
if let Some(access) = access {
488+
if ignore {
489+
return Err(syn::Error::new(
490+
tokens.span(),
491+
"'access' is not supported for padding",
492+
));
493+
}
494+
ret.access = access;
501495
}
502496

503497
// conversion
504498
if let Some(into) = into {
499+
if ret.access == Access::None {
500+
return Err(syn::Error::new(
501+
into.span(),
502+
"'into' and 'from' are not supported on padding",
503+
));
504+
}
505505
ret.into = quote!(#into(this));
506506
}
507507
if let Some(from) = from {
508+
if ret.access == Access::None {
509+
return Err(syn::Error::new(
510+
from.span(),
511+
"'into' and 'from' are not supported on padding",
512+
));
513+
}
508514
ret.from = quote!(#from(this));
509515
}
510516
if let Some(default) = default {
511517
ret.default = default.into_token_stream();
512518
}
513-
514-
// read/write access
515-
if let Some(access) = access {
516-
ret.access = access;
517-
}
518519
}
519520
}
520521

521522
if ret.bits == 0 {
522523
return Err(syn::Error::new(
523524
ty.span(),
524-
"Custom types and isize/usize require the size in the #[bits] attribute",
525+
"Custom types and isize/usize require an explicit bit size",
525526
));
526527
}
527528

528529
// Signed integers need some special handling...
529-
if !ignore && class == TypeClass::SInt {
530+
if !ignore && ret.access != Access::None && class == TypeClass::SInt {
530531
let bits = ret.bits as u32;
531532
let mask = u128::MAX >> (u128::BITS - ret.bits as u32);
532533
let mask = syn::LitInt::new(&format!("0x{mask:x}"), Span::mixed_site());
@@ -627,7 +628,7 @@ impl Parse for Access {
627628
} else {
628629
Err(syn::Error::new(
629630
mode.span(),
630-
"Invalid access mode, only RW/RO/WO/None are allowed",
631+
"Invalid access mode, only RW, RO, WO, or None are allowed",
631632
))
632633
}
633634
}

0 commit comments

Comments
 (0)