use proc_macro2::TokenStream as TokenStream2;
use quote::{format_ident, quote};
use syn::Ident;
use crate::parser::InterfaceObjectsDefinition;
#[allow(clippy::too_many_arguments)]
pub fn generate_register_trait_implementations(
interface_def: &InterfaceObjectsDefinition,
register_name: &Ident,
unpacked_name: &Ident,
addr: &TokenStream2,
mode: &str,
size: usize,
codec_error: &TokenStream2,
i2c_codec: &TokenStream2,
spi_codec: &TokenStream2,
) -> syn::Result<TokenStream2> {
let register_traits = generate_register_traits(
interface_def,
register_name,
unpacked_name,
addr,
size,
codec_error,
i2c_codec,
spi_codec,
)?;
let mode_traits = generate_mode_traits(register_name, mode)?;
Ok(quote! {
#register_traits
#mode_traits
})
}
#[allow(clippy::too_many_arguments)]
fn generate_register_traits(
interface_def: &InterfaceObjectsDefinition,
register_name: &Ident,
unpacked_name: &Ident,
addr: &TokenStream2,
size: usize,
codec_error: &TokenStream2,
i2c_codec: &TokenStream2,
spi_codec: &TokenStream2,
) -> syn::Result<TokenStream2> {
let register_marker_impls: Vec<_> = interface_def
.register_devices
.as_ref()
.map(|x| x.devices.clone())
.unwrap_or_default()
.iter()
.map(|device| {
let mut device_register = device.clone();
if let Some(ref mut last) = device_register.segments.last_mut() {
last.ident = format_ident!("{}Register", last.ident);
}
quote! {
impl #device_register for #register_name {}
}
})
.collect();
Ok(quote! {
#(#register_marker_impls)*
impl embedded_interfaces::registers::Register for #register_name {
type Unpacked = #unpacked_name;
type CodecError = #codec_error;
type SpiCodec = #spi_codec;
type I2cCodec = #i2c_codec;
const REGISTER_SIZE: usize = #size;
const ADDRESS: u64 = #addr;
}
})
}
fn generate_mode_traits(register_name: &Ident, mode: &str) -> syn::Result<TokenStream2> {
match mode {
"r" => Ok(quote! { impl embedded_interfaces::registers::ReadableRegister for #register_name {} }),
"w" => Ok(quote! { impl embedded_interfaces::registers::WritableRegister for #register_name {} }),
"rw" => Ok(quote! {
impl embedded_interfaces::registers::ReadableRegister for #register_name {}
impl embedded_interfaces::registers::WritableRegister for #register_name {}
}),
_ => Err(syn::Error::new_spanned(register_name, format!("Invalid mode: {mode}"))),
}
}