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