allegro_motor_derive/
lib.rs1extern crate proc_macro;
4
5use proc_macro::TokenStream;
6use quote::quote;
7use syn::{parse_macro_input, DeriveInput};
8
9#[proc_macro_derive(AllegroRegister)]
42pub fn allegro_derive(item: TokenStream) -> TokenStream {
43 let DeriveInput { ident, attrs, .. } = parse_macro_input!(item as DeriveInput);
44
45 let bitsize_assignment_function: proc_macro2::TokenStream = match analyze_bitsize(&attrs) {
46 Ok(bitsize) => format!(
47 "bilge::arbitrary_int::u{}::new_unchecked(value)",
48 proc_macro2::Literal::u16_unsuffixed(bitsize)
49 )
50 .parse()
51 .unwrap(),
52 Err(error_msg) => return error_msg.into_compile_error().into(),
53 };
54
55 quote! {
56 impl crate::regs::AllegroRegister for #ident {
57 fn value(&self) -> u16 {
58 self.value.into()
59 }
60
61 fn set_value(&mut self, value: u16) {
62 unsafe { self.value = #bitsize_assignment_function };
63 }
64 }
65 }
66 .into()
67}
68
69fn analyze_bitsize(attrs: &[syn::Attribute]) -> Result<u16, syn::Error> {
70 let mut bitsizes = attrs.iter().filter_map(|attr| {
71 if attr.path().is_ident("bitsize") {
72 let a: syn::LitInt = attr.parse_args().unwrap();
73 Some(a.base10_parse::<u16>().unwrap())
74 } else {
75 None
76 }
77 });
78
79 match bitsizes.next() {
80 Some(bitsize) => Ok(bitsize),
81 None => Err(syn::Error::new_spanned(
82 attrs.iter().next(),
83 "'bitsize' not found in object attributes.",
84 )),
85 }
86}
87
88#[proc_macro_derive(Parity)]
95pub fn parity_derive(item: TokenStream) -> TokenStream {
96 let DeriveInput {
97 ident, generics, ..
98 } = parse_macro_input!(item as DeriveInput);
99 let (impl_generics, type_generics, where_clause) = generics.split_for_impl();
100
101 quote! {
102 impl #impl_generics crate::io::Parity for #ident #type_generics #where_clause {
103 fn set_odd_parity(&mut self) {
104 let calculated_parity = crate::io::parity(self.value);
105 let next_parity = !(self.parity() ^ calculated_parity);
106 self.set_parity(next_parity);
107 }
108 }
109 }
110 .into()
111}