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