-
Notifications
You must be signed in to change notification settings - Fork 12
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(config): add a
config
attribute macro
This attribute macro allows to register specific functions for customizing the initial driver setup.
- Loading branch information
1 parent
1c675e0
commit 1417237
Showing
22 changed files
with
431 additions
and
129 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,135 @@ | ||
/// Registers the function this attribute macro is applied on to provide the configuration for the | ||
/// associated driver during initial system configuration. | ||
/// | ||
/// **Important**: for this configuration to be taken into account, a specific Cargo feature may | ||
/// need to be enabled on the `riot-rs` dependency, for each configuration type (see table below). | ||
/// | ||
/// The name of the function does not matter as it will be renamed by the macro. | ||
/// | ||
/// # Parameters | ||
/// | ||
/// - The name of the driver the function provides configuration for. | ||
/// | ||
/// | Driver | Expected return type | Cargo feature to enable | | ||
/// | --------- | ------------------------------ | ------------------------- | | ||
/// | `network` | `embassy_net::Config` | `override-network-config` | | ||
/// | `usb` | `embassy_usb::Config<'static>` | `override-usb-config` | | ||
/// | ||
/// # Note | ||
/// | ||
/// The `riot_rs` crate provides re-exports for the relevant Embassy crates. | ||
/// | ||
/// # Examples | ||
/// | ||
/// The following function provides configuration for the network stack: | ||
/// | ||
/// ```ignore | ||
/// use riot_rs::embassy_net; | ||
/// | ||
/// #[riot_rs::config(network)] | ||
/// fn network_config() -> embassy_net::Config { | ||
/// use embassy_net::Ipv4Address; | ||
/// | ||
/// embassy_net::Config::ipv4_static(embassy_net::StaticConfigV4 { | ||
/// address: embassy_net::Ipv4Cidr::new(Ipv4Address::new(10, 42, 0, 61), 24), | ||
/// dns_servers: heapless::Vec::new(), | ||
/// gateway: Some(Ipv4Address::new(10, 42, 0, 1)), | ||
/// }) | ||
/// } | ||
/// ``` | ||
#[allow(clippy::missing_panics_doc)] | ||
#[proc_macro_attribute] | ||
pub fn config(args: TokenStream, item: TokenStream) -> TokenStream { | ||
#[allow(clippy::wildcard_imports)] | ||
use config_macro::*; | ||
|
||
use quote::{format_ident, quote}; | ||
|
||
let mut attrs = ConfigAttributes::default(); | ||
let thread_parser = syn::meta::parser(|meta| attrs.parse(&meta)); | ||
syn::parse_macro_input!(args with thread_parser); | ||
|
||
let config_function = syn::parse_macro_input!(item as syn::ItemFn); | ||
let config_function_name = &config_function.sig.ident; | ||
|
||
let riot_rs_crate = utils::riot_rs_crate(); | ||
|
||
let (config_fn_name, return_type) = match attrs.kind { | ||
Some(ConfigKind::Network) => ( | ||
format_ident!("riot_rs_network_config"), | ||
quote! {#riot_rs_crate::embassy::embassy_net::Config}, | ||
), | ||
Some(ConfigKind::Usb) => ( | ||
format_ident!("riot_rs_usb_config"), | ||
quote! {#riot_rs_crate::embassy::embassy_usb::Config<'static>}, | ||
), | ||
None => { | ||
panic!("a configuration kind must be specified"); | ||
} | ||
}; | ||
|
||
// Place the provided function into another function whose type signature we enforce. | ||
// This is important as that function will be called unsafely via FFI. | ||
let expanded = quote! { | ||
#[no_mangle] | ||
fn #config_fn_name() -> #return_type { | ||
#[inline(always)] | ||
#config_function | ||
|
||
#config_function_name() | ||
} | ||
}; | ||
|
||
TokenStream::from(expanded) | ||
} | ||
|
||
mod config_macro { | ||
#[derive(Default)] | ||
pub struct ConfigAttributes { | ||
pub kind: Option<ConfigKind>, | ||
} | ||
|
||
impl ConfigAttributes { | ||
pub fn parse(&mut self, meta: &syn::meta::ParseNestedMeta) -> syn::Result<()> { | ||
use enum_iterator::all; | ||
|
||
for (config_name, kind) in all::<ConfigKind>().map(|c| (c.as_name(), c)) { | ||
if meta.path.is_ident(config_name) { | ||
self.check_only_one_kind(config_name); | ||
self.kind = Some(kind); | ||
return Ok(()); | ||
} | ||
} | ||
|
||
let supported_params = all::<ConfigKind>() | ||
.map(|c| format!("`{}`", c.as_name())) | ||
.collect::<Vec<_>>() | ||
.join(", "); | ||
Err(meta.error(format!( | ||
"unsupported parameter ({supported_params} are supported)", | ||
))) | ||
} | ||
|
||
fn check_only_one_kind(&self, param: &str) { | ||
assert!( | ||
self.kind.is_none(), | ||
"a separate function is required for `{param}` configuration", | ||
); | ||
} | ||
} | ||
|
||
#[derive(Debug, enum_iterator::Sequence)] | ||
pub enum ConfigKind { | ||
Network, | ||
Usb, | ||
} | ||
|
||
impl ConfigKind { | ||
pub fn as_name(&self) -> &'static str { | ||
match self { | ||
Self::Network => "network", | ||
Self::Usb => "usb", | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,4 +4,5 @@ mod utils; | |
|
||
use proc_macro::TokenStream; | ||
|
||
include!("config.rs"); | ||
include!("thread.rs"); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
#[test] | ||
fn ui() { | ||
let t = trybuild::TestCases::new(); | ||
t.compile_fail("tests/ui/*.rs"); | ||
} |
19 changes: 19 additions & 0 deletions
19
src/riot-rs-macros/tests/ui/config_conflicting_config_kind.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
// #![no_std] | ||
#![no_main] | ||
|
||
// This will not get used because the attribute macro is expected to fail | ||
#[allow(unused_imports)] | ||
use riot_rs::embassy::embassy_net; | ||
|
||
// FAIL: network and usb cannot be used at the same time | ||
#[riot_rs::config(network, usb)] | ||
fn network_config() -> embassy_net::Config { | ||
use embassy_net::Ipv4Address; | ||
|
||
embassy_net::Config::ipv4_static(embassy_net::StaticConfigV4 { | ||
address: embassy_net::Ipv4Cidr::new(Ipv4Address::new(10, 42, 0, 61), 24), | ||
dns_servers: heapless::Vec::new(), | ||
gateway: Some(Ipv4Address::new(10, 42, 0, 1)), | ||
}) | ||
} | ||
|
7 changes: 7 additions & 0 deletions
7
src/riot-rs-macros/tests/ui/config_conflicting_config_kind.stderr
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
error: custom attribute panicked | ||
--> tests/ui/config_conflicting_config_kind.rs:9:1 | ||
| | ||
9 | #[riot_rs::config(network, usb)] | ||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
| | ||
= help: message: a separate function is required for `usb` configuration |
18 changes: 18 additions & 0 deletions
18
src/riot-rs-macros/tests/ui/config_misspelled_config_kind.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
// #![no_std] | ||
#![no_main] | ||
|
||
// This will not get used because the attribute macro is expected to fail | ||
#[allow(unused_imports)] | ||
use riot_rs::embassy::embassy_net; | ||
|
||
// FAIL: misspelled config kind | ||
#[riot_rs::config(networkk)] | ||
fn network_config() -> embassy_net::Config { | ||
use embassy_net::Ipv4Address; | ||
|
||
embassy_net::Config::ipv4_static(embassy_net::StaticConfigV4 { | ||
address: embassy_net::Ipv4Cidr::new(Ipv4Address::new(10, 42, 0, 61), 24), | ||
dns_servers: heapless::Vec::new(), | ||
gateway: Some(Ipv4Address::new(10, 42, 0, 1)), | ||
}) | ||
} |
5 changes: 5 additions & 0 deletions
5
src/riot-rs-macros/tests/ui/config_misspelled_config_kind.stderr
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
error: unsupported parameter (`network`, `usb` are supported) | ||
--> tests/ui/config_misspelled_config_kind.rs:9:19 | ||
| | ||
9 | #[riot_rs::config(networkk)] | ||
| ^^^^^^^^ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
// #![no_std] | ||
#![no_main] | ||
|
||
// This will not get used because the attribute macro is expected to fail | ||
#[allow(unused_imports)] | ||
use riot_rs::embassy::embassy_net; | ||
|
||
// FAIL: this attribute macro requires parameters | ||
#[riot_rs::config] | ||
fn network_config() -> embassy_net::Config { | ||
use embassy_net::Ipv4Address; | ||
|
||
embassy_net::Config::ipv4_static(embassy_net::StaticConfigV4 { | ||
address: embassy_net::Ipv4Cidr::new(Ipv4Address::new(10, 42, 0, 61), 24), | ||
dns_servers: heapless::Vec::new(), | ||
gateway: Some(Ipv4Address::new(10, 42, 0, 1)), | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
error: custom attribute panicked | ||
--> tests/ui/config_no_parameters.rs:9:1 | ||
| | ||
9 | #[riot_rs::config] | ||
| ^^^^^^^^^^^^^^^^^^ | ||
| | ||
= help: message: a configuration kind must be specified |
Oops, something went wrong.