Skip to main content

mkutils_macros/
lib.rs

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