oxide_generator_rs/
lib.rs1#![doc = include_str!("../README.md")]
2
3use proc_macro::TokenStream;
8use syn::Item;
9use syn::parse_macro_input;
10#[cfg(test)]
11use std::sync::{Mutex, OnceLock};
12
13mod derive;
14mod meta;
15mod reducer;
16mod routes;
17#[cfg(feature = "isolated-channels")]
18mod isolated_channels;
19#[cfg(test)]
20pub(crate) static TEST_ENV_LOCK: OnceLock<Mutex<()>> = OnceLock::new();
21
22#[proc_macro_attribute]
23pub fn state(attr: TokenStream, item: TokenStream) -> TokenStream {
40 let args = parse_macro_input!(attr as derive::StateArgs);
41 let input = parse_macro_input!(item as Item);
42 match input {
43 Item::Struct(item_struct) => derive::expand_state_struct(args, item_struct).into(),
44 Item::Enum(item_enum) => derive::expand_state_enum(args, item_enum).into(),
45 other => syn::Error::new_spanned(other, "#[state] can only be applied to a struct or enum")
46 .to_compile_error()
47 .into(),
48 }
49}
50
51#[proc_macro_attribute]
52pub fn actions(attr: TokenStream, item: TokenStream) -> TokenStream {
62 let _ = parse_macro_input!(attr as syn::parse::Nothing);
63 let input = parse_macro_input!(item as Item);
64 match input {
65 Item::Enum(item_enum) => derive::expand_actions_enum(item_enum).into(),
66 other => syn::Error::new_spanned(other, "#[actions] can only be applied to an enum")
67 .to_compile_error()
68 .into(),
69 }
70}
71
72#[proc_macro_attribute]
73pub fn reducer(attr: TokenStream, item: TokenStream) -> TokenStream {
83 let args = parse_macro_input!(attr as reducer::ReducerArgs);
84 let input = parse_macro_input!(item as Item);
85 match input {
86 Item::Impl(item_impl) => reducer::expand_reducer_impl(args, item_impl).into(),
87 other => syn::Error::new_spanned(
88 other,
89 "#[reducer(...)] can only be applied to an `impl oxide_core::Reducer for <Type>` block",
90 )
91 .to_compile_error()
92 .into(),
93 }
94}
95
96#[proc_macro_attribute]
97pub fn routes(attr: TokenStream, item: TokenStream) -> TokenStream {
105 let _ = parse_macro_input!(attr as syn::parse::Nothing);
106 let input = parse_macro_input!(item as Item);
107 match input {
108 Item::Mod(item_mod) => match routes::expand_routes_module(item_mod) {
109 Ok(ts) => ts.into(),
110 Err(e) => e.to_compile_error().into(),
111 },
112 other => syn::Error::new_spanned(other, "#[routes] can only be applied to a module")
113 .to_compile_error()
114 .into(),
115 }
116}
117
118#[proc_macro_attribute]
119pub fn oxide_route(attr: TokenStream, item: TokenStream) -> TokenStream {
120 let args = parse_macro_input!(attr as routes::OxideRouteArgs);
121 let input = parse_macro_input!(item as Item);
122 match input {
123 Item::Struct(item_struct) => match routes::expand_oxide_route_struct(args, item_struct) {
124 Ok(ts) => ts.into(),
125 Err(e) => e.to_compile_error().into(),
126 },
127 other => syn::Error::new_spanned(other, "#[oxide_route] can only be applied to a struct")
128 .to_compile_error()
129 .into(),
130 }
131}
132
133#[cfg(feature = "isolated-channels")]
134#[proc_macro_attribute]
135pub fn oxide_event_channel(attr: TokenStream, item: TokenStream) -> TokenStream {
144 let args = parse_macro_input!(attr as isolated_channels::OxideEventChannelArgs);
145 let input = parse_macro_input!(item as Item);
146 match input {
147 Item::Impl(item_impl) => match isolated_channels::expand_oxide_event_channel(args, item_impl) {
148 Ok(ts) => ts.into(),
149 Err(e) => e.to_compile_error().into(),
150 },
151 other => syn::Error::new_spanned(
152 other,
153 "#[oxide_event_channel] can only be applied to an impl block",
154 )
155 .to_compile_error()
156 .into(),
157 }
158}
159
160#[cfg(feature = "isolated-channels")]
161#[proc_macro_attribute]
162pub fn oxide_callback(attr: TokenStream, item: TokenStream) -> TokenStream {
167 let args = parse_macro_input!(attr as isolated_channels::OxideCallbackArgs);
168 let input = parse_macro_input!(item as Item);
169 match input {
170 Item::Impl(item_impl) => match isolated_channels::expand_oxide_callback(args, item_impl) {
171 Ok(ts) => ts.into(),
172 Err(e) => e.to_compile_error().into(),
173 },
174 other => syn::Error::new_spanned(
175 other,
176 "#[oxide_callback] can only be applied to an impl block",
177 )
178 .to_compile_error()
179 .into(),
180 }
181}