crux_macros/
lib.rs

1mod capability;
2mod effect;
3mod effect_derive;
4mod export;
5
6use capability::capability_impl;
7use export::export_impl;
8use proc_macro::TokenStream;
9use proc_macro_error::proc_macro_error;
10use syn::{parse_macro_input, Ident, ItemEnum};
11
12/// Procedural macro to derive an Effect enum, with a variant for
13/// each non-skipped capability.
14///
15/// The default name of the Effect enum is "Effect", but this can be
16/// overridden with the `name` attribute.
17///
18/// The default name of the app struct is "App", but this can be
19/// overridden with the `app` attribute.
20///
21/// No Effect variant will be generated for fields annotated with
22/// `#[effect(skip)]`.
23///
24/// e.g.
25/// ```rust
26/// # use crux_core::{Capability, render::Render, compose::Compose};
27/// # use crux_core::macros::Effect;
28/// # #[derive(Default)]
29/// # struct MyApp;
30/// # pub enum MyEvent {None}
31/// # impl crux_core::App for MyApp {
32/// #     type Event = MyEvent;
33/// #     type Model = ();
34/// #     type ViewModel = ();
35/// #     type Capabilities = MyCapabilities;
36/// #     type Effect = MyEffect;
37/// #     fn update(
38/// #         &self,
39/// #         _event: Self::Event,
40/// #         _model: &mut Self::Model,
41/// #         _caps: &Self::Capabilities,
42/// #     ) -> crux_core::Command<MyEffect, MyEvent> {
43/// #         unimplemented!()
44/// #     }
45/// #     fn view(&self, _model: &Self::Model) -> Self::ViewModel {
46/// #         unimplemented!()
47/// #     }
48/// # }
49/// #[derive(Effect)]
50/// #[effect(name = "MyEffect")]
51/// pub struct MyCapabilities {
52///     pub http: crux_http::Http<MyEvent>,
53///     pub render: Render<MyEvent>,
54///     #[effect(skip)]
55///     pub compose: Compose<MyEvent>,
56/// }
57#[proc_macro_derive(Effect, attributes(effect))]
58#[proc_macro_error]
59pub fn effect_derive(input: TokenStream) -> TokenStream {
60    effect_derive::effect_impl(&parse_macro_input!(input)).into()
61}
62
63/// Generates an effect type matching the enum definition provided,
64/// whilst supplying all the necessary decorations and additional trait implementations.
65///
66/// Use `typegen` as an argument if you want to opt in to the built-in foreign type generation.
67///
68/// e.g.
69/// ```rust
70/// # use crux_core::{Capability, render::RenderOperation, compose::Compose};
71/// # use crux_core::macros::effect;
72/// # use crux_http::protocol::HttpRequest;
73/// # #[derive(Default)]
74/// # struct MyApp;
75/// # pub enum MyEvent {None}
76/// # impl crux_core::App for MyApp {
77/// #     type Event = MyEvent;
78/// #     type Model = ();
79/// #     type ViewModel = ();
80/// #     type Capabilities = ();
81/// #     type Effect = MyEffect;
82/// #     fn update(
83/// #         &self,
84/// #         _event: Self::Event,
85/// #         _model: &mut Self::Model,
86/// #         _caps: &Self::Capabilities,
87/// #     ) -> crux_core::Command<MyEffect, MyEvent> {
88/// #         unimplemented!()
89/// #     }
90/// #     fn view(&self, _model: &Self::Model) -> Self::ViewModel {
91/// #         unimplemented!()
92/// #     }
93/// # }
94/// #[effect(typegen)]
95/// pub enum MyEffect {
96///     Render(RenderOperation),
97///     Http(HttpRequest),
98/// }
99#[proc_macro_attribute]
100pub fn effect(args: TokenStream, input: TokenStream) -> TokenStream {
101    let args = parse_macro_input!(args as Option<Ident>);
102    let input = parse_macro_input!(input as ItemEnum);
103    effect::effect_impl(args, input).into()
104}
105
106#[proc_macro_derive(Export)]
107#[proc_macro_error]
108pub fn export(input: TokenStream) -> TokenStream {
109    export_impl(&parse_macro_input!(input)).into()
110}
111
112#[proc_macro_derive(Capability)]
113#[proc_macro_error]
114pub fn capability(input: TokenStream) -> TokenStream {
115    capability_impl(&parse_macro_input!(input)).into()
116}