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}