From 1b0be30908983946b2492150ba99e8e34f128eb1 Mon Sep 17 00:00:00 2001 From: Wataru Otsubo Date: Sat, 7 Jun 2025 05:04:39 +0900 Subject: [PATCH] update(generator): use u8 and u16 for register value when possible --- CHANGELOG.md | 1 + src/generator.rs | 15 +++++++++++ src/generator/codegen_register.rs | 41 +++++++++++++++++++------------ 3 files changed, 41 insertions(+), 16 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0f7d9a0..b256eb0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Improve error message from syn in generator. !15 - Removed top level module (register_interface), and now it can have arbitrary name. - Use full path `RegisterSpec`s to avoid unused `use` +- Use `u8` and `u16` for `T` of registers when the mask is 0xff or 0xffff, instead of defining new tuple struct. ## [0.3.1] - 2025-04-11 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.