diff --git a/src/generator.rs b/src/generator.rs index 94ea55f..83d3dfd 100644 --- a/src/generator.rs +++ b/src/generator.rs @@ -82,6 +82,21 @@ mod util { } } + /// Derive appropriate rust type for right aligned `mask`ed value. + pub(super) fn from_exact_mask(mask: u32) -> Option { + if mask.trailing_zeros() != 0 { + return None; + } + match 32 - mask.leading_zeros() { + 0 => panic!("mask cannot be 0"), + 1 => Some(RustUxTypes::Bool), + 8 => Some(RustUxTypes::U8), + 16 => Some(RustUxTypes::U16), + 32 => Some(RustUxTypes::U32), + _ => None, + } + } + pub(super) fn to_rust_type_token(&self) -> proc_macro2::Ident { match self { RustUxTypes::Bool => parse_to_ident("bool").unwrap(), diff --git a/src/generator/codegen_register.rs b/src/generator/codegen_register.rs index 931ed3a..4936ad9 100644 --- a/src/generator/codegen_register.rs +++ b/src/generator/codegen_register.rs @@ -71,26 +71,35 @@ fn reg_type_def_masked( let x: RustUxTypes = basetype.into(); x.to_rust_type_token() }; + let type_t = RustUxTypes::from_exact_mask(mask); - let out = quote! { - #[derive(Debug, Clone, Copy, Default)] - pub struct #upper_camel_name(pub #type_ux); - impl TryFrom<#type_ux> for #upper_camel_name { - type Error = crate::register_spec::DataConversionError<#type_ux, Self>; + // u8, u16 already implements Into and TryFrom with u32 + // but bool doen't implement TryFrom, so it cannot be used as `T` here + match type_t { + None | Some(RustUxTypes::Bool) => { + let out = quote! { + #[derive(Debug, Clone, Copy, Default)] + pub struct #upper_camel_name(pub #type_ux); + impl TryFrom<#type_ux> for #upper_camel_name { + type Error = crate::register_spec::DataConversionError<#type_ux, Self>; - fn try_from(value: #type_ux) -> Result { - Ok(Self(value & #mask)) - } + fn try_from(value: #type_ux) -> Result { + Ok(Self(value & #mask)) + } + } + impl From<#upper_camel_name> for #type_ux { + fn from(value: #upper_camel_name) -> Self { + value.0 + } + } + }; + (out, upper_camel_name.clone(), type_ux) } - impl From<#upper_camel_name> for #type_ux { - fn from(value: #upper_camel_name) -> Self { - value.0 - } + Some(type_t) => { + let out = quote! {}; + (out, type_t.to_rust_type_token(), type_ux) } - - }; - - (out, upper_camel_name.clone(), type_ux) + } } /// Where `T` has fields.