3 releases
0.1.2 | Oct 28, 2023 |
---|---|
0.1.1 | Oct 28, 2023 |
0.1.0 | Oct 28, 2023 |
#1705 in Procedural macros
17KB
107 lines
Behavior
A macro checks like "behavior" in elixir language.
Example
The "behavior" is defined as a trait whose methods are all static methods. And behavior::behavior
macro checks if all given modules implement behavior trait.
use serde::de::DeserializeOwned;
use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize)]
pub struct User {
name: String,
age: u8,
}
#[behavior::behavior(modules(original, fake))] // check behaviors
#[async_trait::async_trait]
trait MyBehavior {
async fn get<T: DeserializeOwned>(url: String) -> T;
fn post_user<'a>(url: String, user: &'a User) -> u16;
}
mod original {
use super::User;
pub async fn get<T: serde::de::DeserializeOwned>(url: String) -> T {
let res = reqwest::Client::new().get(&url).send().await.unwrap();
res.json().await.unwrap()
}
pub fn post_user(url: String, user: &User) -> u16 {
reqwest::blocking::Client::new()
.post(&url)
.json(user)
.send()
.unwrap()
.status()
.as_u16()
}
}
mod fake {
use super::User;
pub async fn get<T: serde::de::DeserializeOwned>(_url: String) -> T {
serde_json::from_str("{}").unwrap()
}
pub fn post_user(_url: String, _user: &User) -> u16 {
200
}
}
It is useful to guarantee the APIs when using feature flag.
#[cfg(feature = "fake")]
pub use fake::*;
#[cfg(not(feature = "fake"))]
pub use original::*;
Because the macro generates a type which implement behavior trait for each module (in the example, FakeModuleMyBehavior
and OriginalModuleMyBehavior
), you can use behavior as normal trait. But it is not recommended.
Dependencies
~0.6–1MB
~23K SLoC