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}