Skip to main content

mkutils_macros/
lib.rs

1mod basic;
2mod const_assoc;
3mod constructor;
4mod context;
5mod default;
6mod error;
7mod from_chain;
8mod set_variant;
9mod toggle;
10mod tokio_main;
11mod type_assoc;
12mod utils;
13
14use crate::{
15    basic::Basic, const_assoc::ConstAssoc, constructor::Constructor, default::Default, from_chain::FromChain,
16    set_variant::SetVariant, toggle::Toggle, type_assoc::TypeAssoc,
17};
18use proc_macro::TokenStream;
19
20// TODO: add documentation
21#[proc_macro_attribute]
22pub fn context(attr_args_token_stream: TokenStream, input_token_stream: TokenStream) -> TokenStream {
23    crate::context::context(attr_args_token_stream, input_token_stream)
24}
25
26/// Implement `::std::convert::From` through a chain of intermediate types.
27///
28///
29/// # Example
30///
31/// ```rust
32/// struct Foo;
33///
34/// struct Bar;
35///
36/// struct Baz;
37///
38/// impl From<Foo> for Bar { fn from(_foo: Foo) -> Self { Self } }
39///
40/// impl From<Bar> for Baz { fn from(_bar: Bar) -> Self { Self } }
41///
42/// impl From<Baz> for MyStruct { fn from(_baz: Baz) -> Self { Self } }
43///
44/// #[derive(mkutils_macros::FromChain)]
45/// #[from_chain(Foo, Bar, Baz)]
46/// struct MyStruct;
47///
48/// // adds
49/// // ```rust
50/// // impl From<Foo> for MyStruct {
51/// //     fn from(foo: Foo) -> Self {
52/// //         Self::from(Baz::from(Bar::from(foo)))
53/// //     }
54/// // }
55/// // ```
56/// // as can be seen in
57///
58/// let _my_struct: MyStruct = Foo.into();
59/// ```
60#[proc_macro_derive(FromChain, attributes(from_chain))]
61pub fn from_chain(input_token_stream: TokenStream) -> TokenStream {
62    FromChain::derive(input_token_stream)
63}
64
65/// Implements traits that only have associated types.
66///
67///
68/// # Example
69///
70/// ```rust
71///
72/// trait Foo {
73///   type Item;
74/// }
75///
76/// #[derive(mkutils_macros::TypeAssoc)]
77/// #[type_assoc(impl_trait = Foo, Item = Vec<u8>)]
78/// struct MyStruct;
79///
80/// // adds
81/// // ```rust
82/// // impl Foo for MyStruct {
83/// //     type Item = Vec<u8>;
84/// // }
85/// // ```
86/// // as can be seen in
87///
88/// fn consume_foo<T: Foo>(value: T) {}
89///
90/// consume_foo(MyStruct);
91/// ```
92#[proc_macro_derive(TypeAssoc, attributes(type_assoc))]
93pub fn type_assoc(input_token_stream: TokenStream) -> TokenStream {
94    TypeAssoc::derive(input_token_stream)
95}
96
97/// Adds associated constants to a type via an inherent impl block.
98///
99///
100/// # Example
101///
102/// ```rust
103/// #[derive(mkutils_macros::ConstAssoc)]
104/// #[const_assoc(pub MAX_SIZE: usize = 1024)]
105/// #[const_assoc(DEFAULT_NAME: &str = "unnamed")]
106/// struct MyStruct;
107///
108/// // adds
109/// // ```rust
110/// // impl MyStruct {
111/// //     pub const MAX_SIZE: usize = 1024;
112/// //     const DEFAULT_NAME: &str = "unnamed";
113/// // }
114/// // ```
115/// // as can be seen in
116///
117/// std::assert_eq!(MyStruct::MAX_SIZE, 1024);
118/// std::assert_eq!(MyStruct::DEFAULT_NAME, "unnamed");
119/// ```
120#[proc_macro_derive(ConstAssoc, attributes(const_assoc))]
121pub fn const_assoc(input_token_stream: TokenStream) -> TokenStream {
122    ConstAssoc::derive(input_token_stream)
123}
124
125/// Implements `Default` for a struct, using `Default::default()` for each field
126/// unless a `#[default(...)]` attribute provides a custom expression.
127///
128///
129/// # Example
130///
131/// ```rust
132/// #[derive(mkutils_macros::Default)]
133/// struct MyStruct {
134///     name: String,
135///     #[default(42)]
136///     count: i32,
137///     #[default(std::vec![1, 2, 3])]
138///     items: Vec<i32>,
139/// }
140///
141/// // adds
142/// // ```rust
143/// // impl Default for MyStruct {
144/// //     fn default() -> Self {
145/// //         Self {
146/// //             name: ::core::default::Default::default(),
147/// //             count: 42,
148/// //             items: std::vec![1, 2, 3],
149/// //         }
150/// //     }
151/// // }
152/// // ```
153/// // as can be seen in
154///
155/// let default = MyStruct::default();
156///
157/// std::assert_eq!(default.name, "");
158/// std::assert_eq!(default.count, 42);
159/// std::assert_eq!(default.items, std::vec![1, 2, 3]);
160/// ```
161#[proc_macro_derive(Default, attributes(default))]
162pub fn default(input_token_stream: TokenStream) -> TokenStream {
163    Default::derive(input_token_stream)
164}
165
166/// Adds `set_*()` methods for each unit variant on the given enum.
167///
168/// # Example
169///
170/// ```rust
171/// #[derive(Debug, mkutils_macros::SetVariant, PartialEq)]
172/// enum MyEnum {
173///   Foo,
174///   Bar,
175///   Baz(String),
176/// }
177///
178/// // adds
179/// // ```rust
180/// // impl MyEnum {
181/// //   pub fn set_foo(&mut self) -> &mut Self {
182/// //     *self = Self::Foo;
183/// //
184/// //     self
185/// //   }
186/// //
187/// //   pub fn set_bar(&mut self) -> &mut Self {
188/// //     *self = Self::Bar;
189/// //
190/// //     self
191/// //   }
192/// // }
193/// // ```
194/// // as can be seen in
195///
196/// let mut my_enum = MyEnum::Foo;
197///
198/// my_enum.set_bar();
199///
200/// std::assert_eq!(my_enum, MyEnum::Bar);
201/// ```
202#[proc_macro_derive(SetVariant)]
203pub fn set_variant(input_token_stream: TokenStream) -> TokenStream {
204    SetVariant::derive(input_token_stream)
205}
206
207/// Adds a `toggled()` method that maps each enum variant to the next unit variant.
208///
209/// # Example
210///
211/// ```rust
212/// #[derive(Debug, mkutils_macros::Toggle, PartialEq)]
213/// enum MyEnum {
214///   Foo,
215///   Bar,
216///   Baz(String),
217/// }
218///
219/// // adds
220/// // ```rust
221/// // impl MyEnum {
222/// //   pub fn toggle(&self) -> Self {
223/// //     match self {
224/// //         Self::Foo => Self::Bar,
225/// //         Self::Bar => Self::Foo,
226/// //         Self::Baz(_string) => Self::Foo,
227/// //     }
228/// //   }
229/// //
230/// //   pub fn toggle(&mut self) -> &mut Self {
231/// //     *self = self.toggled();
232/// //
233/// //     self
234/// //   }
235/// // }
236/// // ```
237/// // as can be seen in
238///
239/// std::assert_eq!(MyEnum::Foo.toggled(), MyEnum::Bar);
240/// std::assert_eq!(MyEnum::Bar.toggled(), MyEnum::Foo);
241/// std::assert_eq!(MyEnum::Baz(String::new()).toggled(), MyEnum::Foo);
242/// ```
243#[proc_macro_derive(Toggle)]
244pub fn toggle(input_token_stream: TokenStream) -> TokenStream {
245    Toggle::derive(input_token_stream)
246}
247
248/// Implements `num::traits::SaturatingAdd` for a struct by delegating to each field.
249/// Supports setting bounds with `#[saturating_add(bound = "T: SomeTrait")]`
250///
251/// # Example
252///
253/// ```rust,ignore
254/// #[derive(Debug, mkutils_macros::SaturatingAdd, PartialEq)]
255/// struct MyStruct(usize, usize);
256/// ```
257///
258/// adds
259///
260/// ```rust,ignore
261/// impl num::traits::SaturatingAdd for MyStruct {
262///     fn saturating_add(&self, v: &Self) -> Self {
263///         Self(self.0.saturating_add(&v.0), self.1.saturating_add(&v.1))
264///     }
265/// }
266/// ```
267///
268/// as can be seen in
269///
270/// ```rust,ignore
271/// std::assert_eq!(MyStruct(1, 1).saturating_add(MyStruct(2, 2)), MyStruct(3, 3));
272/// ```
273#[proc_macro_derive(SaturatingAdd, attributes(saturating_add))]
274pub fn saturating_add(input_token_stream: TokenStream) -> TokenStream {
275    Basic::derive(
276        input_token_stream,
277        "::num::traits::SaturatingAdd",
278        "saturating_add",
279        "Self",
280        "saturating_add",
281    )
282}
283
284/// Implements `num::traits::SaturatingSub` for a struct by delegating to each field.
285/// Supports setting bounds with `#[saturating_sub(bound = "T: SomeTrait")]`
286///
287/// # Example
288///
289/// ```rust,ignore
290/// #[derive(Debug, mkutils_macros::SaturatingSub, PartialEq)]
291/// struct MyStruct(usize, usize);
292/// ```
293///
294/// adds
295///
296/// ```rust,ignore
297/// impl num::traits::SaturatingSub for MyStruct {
298///     fn saturating_sub(&self, v: &Self) -> Self {
299///         Self(self.0.saturating_sub(&v.0), self.1.saturating_sub(&v.1))
300///     }
301/// }
302/// ```
303///
304/// as can be seen in
305///
306/// ```rust,ignore
307/// std::assert_eq!(MyStruct(1, 1).saturating_sub(MyStruct(2, 2)), MyStruct(0, 0));
308/// ```
309#[proc_macro_derive(SaturatingSub, attributes(saturating_sub))]
310pub fn saturating_sub(input_token_stream: TokenStream) -> TokenStream {
311    Basic::derive(
312        input_token_stream,
313        "::num::traits::SaturatingSub",
314        "saturating_sub",
315        "Self",
316        "saturating_sub",
317    )
318}
319
320#[allow(clippy::too_long_first_doc_paragraph)]
321/// Implements `mkutils::SaturatingAddSigned` for a struct by delegating to each field.
322/// Set the `Signed` associated type and bounds with
323/// `#[saturating_add_signed(assoc(type Signed = Point<<T as SaturatingAddSigned>::Signed>)), bound = "T: SomeTrait"]`
324///
325/// # Example
326///
327/// ```rust,ignore
328/// #[derive(Debug, mkutils_macros::SaturatingAddSigned, PartialEq)]
329/// #[saturating_add_signed(assoc(type Signed = MyStruct<<T as SaturatingAddSigned>::Signed>))]
330/// struct MyStruct<T>(T, T);
331/// ```
332///
333/// adds
334///
335/// ```rust,ignore
336/// impl mkutils::SaturatingAddSigned for MyStruct<T> {
337///     fn saturating_add_signed(&self, v: &Other) -> Self {
338///         Self(self.0.saturating_add_signed(&v.0), self.1.saturating_add_signed(&v.1))
339///     }
340/// }
341/// ```
342///
343/// as can be seen in
344///
345/// ```rust,ignore
346/// std::assert_eq!(MyStruct(2, 2).saturating_add_signed(MyStruct(-1, -1)), MyStruct(1, 1));
347/// ```
348#[proc_macro_derive(SaturatingAddSigned, attributes(saturating_add_signed))]
349pub fn saturating_add_signed(input_token_stream: TokenStream) -> TokenStream {
350    Basic::derive(
351        input_token_stream,
352        "::mkutils::SaturatingAddSigned", // NOTE-ee355f
353        "saturating_add_signed",
354        "Self::Signed",
355        "saturating_add_signed",
356    )
357}
358
359/// Adds a `new()` constructor that accepts each field as a parameter.
360/// The method is private by default. Use `#[new("pub")]` or `#[new("pub(crate)")]`
361/// to set a custom visibility.
362///
363/// # Example
364///
365/// ```rust
366/// #[derive(Debug, mkutils_macros::Constructor, PartialEq)]
367/// #[new(pub(crate))]
368/// struct MyStruct {
369///     name: String,
370///     count: i32,
371/// }
372///
373/// // adds
374/// // ```rust
375/// // impl MyStruct {
376/// //     pub(crate) fn new(name: String, count: i32) -> Self {
377/// //         Self { name, count }
378/// //     }
379/// // }
380/// // ```
381/// // as can be seen in
382///
383/// let my_struct_literal = MyStruct { name: "hello".into(), count: 2 };
384/// let my_struct_constructed = MyStruct::new("hello".into(), 2);
385///
386/// std::assert_eq!(my_struct_literal, my_struct_constructed);
387/// ```
388#[proc_macro_derive(Constructor, attributes(new))]
389pub fn constructor(input_token_stream: TokenStream) -> TokenStream {
390    Constructor::derive(input_token_stream)
391}
392
393/// # Example
394///
395/// ```rust,ignore
396/// const THREAD_STACK_SIZE = lits::bytes!("8 MiB");
397///
398/// #[mkutils_macros::tokio_main(thread_stack_size = THREAD_STACK_SIZE)]
399/// fn main() {
400///     // ...
401/// }
402/// ```
403#[proc_macro_attribute]
404pub fn tokio_main(attr_args_token_stream: TokenStream, item_token_stream: TokenStream) -> TokenStream {
405    crate::tokio_main::tokio_main(attr_args_token_stream, item_token_stream)
406}