mirror of
https://gitlab.cern.ch/wotsubo/endcap-sl-software-ri-generator.git
synced 2025-02-23 00:57:08 +09:00
new(codegen_register): add multiple custom value fields generator
This commit is contained in:
parent
30279dc2b3
commit
9728af3551
1 changed files with 87 additions and 1 deletions
|
@ -421,8 +421,15 @@ fn generate_multiple_field(
|
|||
.map(|mask| util::parse_to_literal(&format!("0x{mask:x}")).unwrap())
|
||||
.collect();
|
||||
debug_assert_eq!(masks.len(), num_multiple.try_into().unwrap());
|
||||
let value_const_enumdefs = match single_field_type {
|
||||
FieldType::RustType(_) => quote! {},
|
||||
FieldType::CustomValue(values) => {
|
||||
generate_custom_values_const_enumdef(&base_type, &snake_case_name, values)
|
||||
}
|
||||
};
|
||||
let code_mask = quote! {
|
||||
const #mask_name: [#base_type; #id_num_multiple] = [#(#masks),*];
|
||||
#value_const_enumdefs
|
||||
};
|
||||
|
||||
let (code_getter, code_setter) = match single_field_type {
|
||||
|
@ -438,7 +445,13 @@ fn generate_multiple_field(
|
|||
masks,
|
||||
),
|
||||
},
|
||||
FieldType::CustomValue(_) => todo!("HERE NEXT"),
|
||||
FieldType::CustomValue(values) => generate_multiple_custom_values_field(
|
||||
mask_name,
|
||||
base_type,
|
||||
snake_case_name,
|
||||
masks,
|
||||
values,
|
||||
),
|
||||
};
|
||||
|
||||
(code_mask, code_getter, code_setter)
|
||||
|
@ -528,3 +541,76 @@ fn generate_multiple_ux_field(
|
|||
|
||||
(code_getter, code_setter)
|
||||
}
|
||||
|
||||
fn generate_multiple_custom_values_field(
|
||||
mask_name: Ident,
|
||||
base_type: Ident,
|
||||
snake_case_name: Ident,
|
||||
masks: Vec<Literal>,
|
||||
values: &[Value],
|
||||
) -> (TokenStream, TokenStream) {
|
||||
let value_enum_name =
|
||||
util::parse_to_ident(&snake_case_name.to_string().to_upper_camel_case()).unwrap();
|
||||
let num_multiple = masks.len();
|
||||
let (getter_match_arms, setter_match_arms): (Vec<_>, Vec<_>) = values
|
||||
.iter()
|
||||
.map(|value| {
|
||||
let const_name = custom_value_const_name(&snake_case_name, &value.name);
|
||||
let variant_name = util::parse_to_ident(&value.name.to_upper_camel_case()).unwrap();
|
||||
(
|
||||
quote! {
|
||||
#const_name => #value_enum_name::#variant_name
|
||||
},
|
||||
quote! {
|
||||
#value_enum_name::#variant_name => #const_name
|
||||
},
|
||||
)
|
||||
})
|
||||
.unzip();
|
||||
|
||||
let elem_getter = masks.iter().enumerate().map(|(i, _mask)| {
|
||||
quote! {
|
||||
match ((self.inner & #mask_name[#i]))
|
||||
>> (#mask_name[#i].trailing_zeros())
|
||||
{
|
||||
#(#getter_match_arms),*,
|
||||
_ => panic!("must not reachable"),
|
||||
}
|
||||
}
|
||||
});
|
||||
let code_getter = quote! {
|
||||
pub fn #snake_case_name(&self) -> [#value_enum_name; #num_multiple] {
|
||||
[
|
||||
#(#elem_getter),*
|
||||
]
|
||||
}
|
||||
};
|
||||
|
||||
let setter_name = util::parse_to_ident(&format!("set_{}", snake_case_name)).unwrap();
|
||||
let elem_setter = masks.iter().enumerate().map(|(i, _mask)| {
|
||||
quote! {
|
||||
match val[#i] {
|
||||
#(#setter_match_arms),*
|
||||
}
|
||||
}
|
||||
});
|
||||
let code_setter = quote! {
|
||||
pub fn #setter_name(&self, val: [#value_enum_name; #num_multiple]) -> Self {
|
||||
let val: [#base_type; #num_multiple] = [
|
||||
#(#elem_setter),*
|
||||
];
|
||||
let mask: #base_type = #mask_name.iter().sum();
|
||||
let update: #base_type = #mask_name
|
||||
.iter()
|
||||
.zip(val)
|
||||
.map(|(mask, val)| (#base_type::from(val)) << (mask.trailing_zeros()))
|
||||
.sum();
|
||||
let mut inner = self.inner;
|
||||
inner &= !mask;
|
||||
inner |= update;
|
||||
Self { inner }
|
||||
}
|
||||
};
|
||||
|
||||
(code_getter, code_setter)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue