2 releases
0.1.1 | Sep 2, 2024 |
---|---|
0.1.0 | Aug 28, 2024 |
#395 in Procedural macros
17KB
321 lines
Extractor
A procedural macro generate the trait for extactor pattern
.
Example
#[derive(Debug)]
pub struct Widget<'a, V> {
val: &'a V,
}
impl<'a, V> ExtractInnerA<'a, V> for Widget<'a, V> {
fn inner(&self) -> &'a V {
self.val
}
}
impl<'a> Extract<'a, i64, Widget<'a, i64>> for &'a i64 {
type Output<'b> = &'b i64
where
i64: 'b;
type Error = String;
fn extract(_uid: u64, set: &Widget<'a, i64>) -> Result<Self::Output<'a>, Self::Error> {
Ok(set.inner())
}
}
impl<'a> Extract<'a, i64, Widget<'a, i64>> for String {
type Output<'b> = String
where
i64: 'b;
type Error = String;
fn extract(_uid: u64, set: &Widget<'a, i64>) -> Result<Self::Output<'a>, Self::Error> {
Ok(set.inner().to_string())
}
}
fn wrap_handler<'a, V, H, S, Args>(mut handler: H) -> impl FnMut(u64, &S) -> Result<(), String> + 'a
where
V: 'a,
S: ExtractInnerA<'a, V> + 'a,
H: Handler<S, Args, Error = String, Output = ()> + 'a,
Args: Extract<'a, V, S, Output<'a> = Args>,
{
Box::new(move |uid: u64, set: &S| {
let args = Args::extract(uid, set).map_err(|v| v.into())?;
handler.handle(uid, set, args)
})
}
// generate extract and handler trait
extpat::extract!(err: String, Extract { uid: u64, set: &A<V> });
extpat::handler!(err: String, Handler { uid: u64, set: &A<V> });
fn main() {
fn annoy1<'a>(uid: u64, w: &Widget<'a, i64>, val: &'a i64) -> Result<(), String> {
println!("---> in annoy1: uid = {}, widget = {:?}, {}", uid, w, val);
Ok(())
}
fn annoy2(uid: u64, w: &Widget<'_, i64>, val: String) -> Result<(), String> {
println!("---> in annoy2: uid = {}, widget = {:?}, {}", uid, w, val);
Ok(())
}
type HandlerT<'a> = Box<dyn FnMut(u64, &Widget<'a, i64>) -> Result<(), String> + 'a>;
let value = Widget { val: &42i64 };
let handler: Vec<HandlerT<'_>> = vec![
Box::new(wrap_handler(annoy1)),
Box::new(wrap_handler(annoy2)),
];
for mut h in handler {
h(0, &value).unwrap();
}
}
Dependencies
~250–700KB
~17K SLoC