diff --git a/Cargo.toml b/Cargo.toml index 83426da..6bcb4e7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,6 +10,8 @@ members = [ "peripherals/standalone-ads1256/*", # Peripheral components "peripheral-components/ads1256/*", + # Macros + "macros/node-poll-variants", # Examples "examples/ads1256" ] @@ -87,6 +89,14 @@ features = ["defmt", "unstable-traits", "unstable-pac", "nightly"] [workspace.dependencies.embassy-nrf] version = "0.1.*" features = ["defmt", "unstable-traits", "nightly"] +# Macros +[workspace.dependencies.syn] +version = "2.0.*" +features = ["extra-traits"] +[workspace.dependencies.quote] +version = "1.0.*" +[workspace.dependencies.trybuild] +version = "1.0.*" #--------------------------------------------------------------------------------------------------------------------- #----- Patch ------------------------ diff --git a/macros/node-poll-variants/Cargo.toml b/macros/node-poll-variants/Cargo.toml new file mode 100644 index 0000000..85c0a16 --- /dev/null +++ b/macros/node-poll-variants/Cargo.toml @@ -0,0 +1,23 @@ +[package] +name = "node-poll-variants" +description = "Macros for physical nodes." +version.workspace = true +edition.workspace = true +repository.workspace = true +readme.workspace = true +license.workspace = true + +[lib] +proc-macro = true + +[[test]] +name = "tests" +path = "tests/test_build.rs" + +[dependencies.syn] +workspace = true +[dependencies.quote] +workspace = true + +[dev-dependencies.trybuild] +workspace = true \ No newline at end of file diff --git a/macros/node-poll-variants/src/lib.rs b/macros/node-poll-variants/src/lib.rs new file mode 100644 index 0000000..a75bde3 --- /dev/null +++ b/macros/node-poll-variants/src/lib.rs @@ -0,0 +1,46 @@ +use proc_macro::TokenStream; +use std::ops::Deref; +use quote::quote; +use syn::{parse_macro_input, DeriveInput, Data, Ident}; + +// Struct name: Ads1256PollStateful, Ads1256PollPublish, Ads1256PollStatePub +#[proc_macro_derive(PollVariants)] +pub fn transducer_macro(input: TokenStream) -> TokenStream { + let input = parse_macro_input!(input as DeriveInput); + let DeriveInput { + attrs, + vis, + ident, + generics, + data, + } = &input; + // Check that item the macro was used on is valid + match data { + Data::Struct(struct_data) => struct_data, + Data::Enum(_) => panic!("Stateful struct cannot be derived from an enum."), + Data::Union(_) => panic!("Stateful struct cannot be derived from a union.") + }; + // Check if generics contains T + + // If it does make sure it is T: Copy + // If it isn't Copy, panic + + // If it doesn't contain T, add it for use in the type that will be generated + + let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); + + let stateful_name = format!("{ident}Stateful"); + let stateful_ident = Ident::new(stateful_name.deref(), ident.span()); + + eprintln!("input: {input:#?}"); + eprintln!("impl_generics: {impl_generics:#?}"); + + let expanded = quote! { + #vis struct #stateful_ident #generics { + pub poll: #ident #ty_generics, + pub state: physical::transducer::State, + } + }; + + TokenStream::from(expanded) +} diff --git a/macros/node-poll-variants/tests/generate.rs b/macros/node-poll-variants/tests/generate.rs new file mode 100644 index 0000000..d24d483 --- /dev/null +++ b/macros/node-poll-variants/tests/generate.rs @@ -0,0 +1,11 @@ +use node_poll_variants::{PollVariants}; + +#[derive(PollVariants)] +struct ExamplePoll<'a, FirstT: Copy, SecondT> { + a: &'a i32, + b: i32, + first: FirstT, + second: SecondT, +} + +fn main() {} diff --git a/macros/node-poll-variants/tests/test_build.rs b/macros/node-poll-variants/tests/test_build.rs new file mode 100644 index 0000000..6661c9d --- /dev/null +++ b/macros/node-poll-variants/tests/test_build.rs @@ -0,0 +1,5 @@ +#[test] +fn tests() { + let t = trybuild::TestCases::new(); + t.pass("tests/generate.rs"); +} \ No newline at end of file diff --git a/src/transducer/output.rs b/src/transducer/output.rs index be5e963..eb43a0d 100644 --- a/src/transducer/output.rs +++ b/src/transducer/output.rs @@ -1,7 +1,9 @@ pub trait Output { type Value: Copy; - //TODO: return result - //TODO: Make maybe async - fn output(&mut self, setting: Self::Value); -} \ No newline at end of file + //TODO: Should this be maybe async? + fn output(&mut self, setting: Self::Value) -> Result<(), InvalidOutputSetting>; +} + +/// Indicates the setting given for an [Output] is statically known to be an impossible setting to achieve. +pub struct InvalidOutputSetting; \ No newline at end of file