dfdi_macros/
lib.rs

1#![forbid(unsafe_code)]
2
3mod derive_service;
4
5use proc_macro::TokenStream;
6use syn::{parse_macro_input, DeriveInput, Error};
7
8/// Create an implementation of [`Service`] on a `'static` version of the original type.
9///
10/// You can use the `#[service(Argument -> Output)]` attribute to customize the argument and return
11/// types. The default service attribute is `#[service(() -> Self)]`.
12///
13/// To produce the final impl, the derive macro follows these steps:
14/// - Replace all the lifetimes on the type with `'static` and implement `Service` on the new type
15/// - Set `Output<'cx>` to the output type with all non-'static lifetimes replaced by `'cx`
16/// - Set `Argument<'arg>` to the argument type with all non-'static lifetimes replaced by `'arg`
17///
18/// ```
19/// # use dfdi::Service;
20/// #[derive(Service)]
21/// struct Ref<'a, T>(&'a T);
22///
23/// // The above generates:
24/// // impl<T> Service for Ref<'static, T> {
25/// //    type Output<'cx> = Ref<'cx, T>;
26/// //    type Argument<'arg> = ();
27/// // }
28///
29/// #[derive(Service)]
30/// #[service(bool -> Option<Self>)]
31/// struct MaybeRef<'a, T>(&'a T);
32///
33/// // The above generates:
34/// // impl<T> Service for MaybeRef<'static, T> {
35/// //    type Output<'cx> = Option<MaybeRef<'cx, T>>;
36/// //    type Argument<'arg> = bool;
37/// // }
38/// ```
39#[proc_macro_derive(Service, attributes(service))]
40pub fn derive_service(input: TokenStream) -> TokenStream {
41    let input = parse_macro_input!(input as DeriveInput);
42    derive_service::derive_service(input)
43        .unwrap_or_else(Error::into_compile_error)
44        .into()
45}