boring_derive/
lib.rs

1//! Derive macros for some common patterns
2//!
3//! The currently implemented patterns are:
4//!  - Builder
5//!  - From
6//!
7//! # Builder
8//! for the `Builder` macro it generates an impl with methods of the form:
9//! ```text
10//! fn field(mut self, value: impl Into<Type>) -> Self {
11//!     self.field = value.into()
12//!     self
13//! }
14//! ```
15//!
16//! An example of the generated code for a struct is:
17//! ```text
18//! #[derive(Default, Builder)]
19//! struct Example {
20//!     item: String,
21//!     value: usize,
22//! }
23//!
24//! // generated impl
25//! impl Example {
26//!     fn item(mut self, value: impl Into<String>) -> Self {
27//!         self.item = value.into();
28//!         self
29//!     }
30//!
31//!     fn value(mut self, value: impl Into<usize>) -> Self {
32//!         self.value = value.into();
33//!         self
34//!     }
35//! }
36//!
37//! // using the values
38//! fn func() {
39//!     let ex = Example::default()
40//!         .item("something")
41//!         .value(1);
42//!     ...
43//! }
44//! ```
45//!
46//! if you want to not include a field in the builder pattern use the `skip` attribute:
47//! ```text
48//! #[derive(Builder)]
49//! struct Example {
50//!     #[builder(skip)]
51//!     item: String,
52//!     value: usize,
53//! }
54//! ```
55//!
56//! if you do not want to have the `Into` use the `no_into` attribute:
57//! ```text
58//! #[derive(Builder)]
59//! struct Example {
60//!     #[builder(no_into)]
61//!     item: String,
62//!     value: usize,
63//! }
64//! ```
65//!
66//! if you need to alter the names of the associated methods use `prefix` and/or `rename`
67//! attributes.
68//! ```text
69//! #[derive(Builder)]
70//! #[builder(prefix = "set_")]
71//! struct Example {
72//!     item: String,
73//!     #[builder(rename = "num")]
74//!     value: usize,
75//! }
76//!
77//! // will generate
78//! impl Example {
79//!     fn set_item(mut self, ..) -> Self {..}
80//!     fn num(mut self, ..) -> Self {..}
81//! }
82//! ```
83//!
84//! The Builder pattern is not defined for enums, unit-like struct, newtypes, and tuple structs
85//!
86//! # From
87//! For the `From` derive it implements the trivial `From<Type>` implementations:
88//! ```text
89//! #[derive(From)]
90//! enum Example {
91//!     Empty,
92//!     Number(f32),
93//!     Pair(String, String),
94//! }
95//!
96//! // will generate
97//! impl From<()> for Example {
98//!     fn from(value: ()) -> Self {
99//!         Example::Empty
100//!     }
101//! }
102//! impl From<f32> for Example {
103//!     fn from(value: f32) -> Self {
104//!         Example::Number(f32)
105//!     }
106//! }
107//! impl From<(String, String)> for Example {
108//!     fn from(value: (String, String)) -> Self {
109//!         Example::Pair(value.0, value.1)
110//!     }
111//! }
112//! ```
113//!
114//! For struct datatypes it uses tuples as the type to convert from:
115//! ```text
116//! #[derive(From)]
117//! struct Example {
118//!     item: usize
119//!     value: String
120//! }
121//!
122//! // generates
123//! impl From<(usize, String)> for Example {
124//!     fn from(value: (usize, String)) -> Self {
125//!         Example {
126//!             item: value.0,
127//!             value: value.1,
128//!         }
129//!     }
130//! }
131//! ```
132//!
133//! If you need to not generate a `From` implementation use the `skip` attribute
134//! ```text
135//! #[derive(From)]
136//! enum Example {
137//!     #[from(skip)]
138//!     Empty,
139//!     Number(f32),
140//!     Pair(String, String),
141//! }
142//! ```
143mod builder_derive;
144mod core;
145mod from_derive;
146
147use proc_macro::TokenStream;
148use syn::parse_macro_input;
149use syn::DeriveInput;
150
151use builder_derive::impl_builder;
152use from_derive::impl_from;
153
154#[proc_macro_derive(From, attributes(from))]
155pub fn from_derive(input: TokenStream) -> TokenStream {
156    let ast = parse_macro_input!(input as DeriveInput);
157
158    impl_from(&ast)
159        .unwrap_or_else(syn::Error::into_compile_error)
160        .into()
161}
162
163#[proc_macro_derive(Builder, attributes(builder))]
164pub fn builder_derive(input: TokenStream) -> TokenStream {
165    let ast = parse_macro_input!(input as DeriveInput);
166
167    impl_builder(&ast)
168        .unwrap_or_else(syn::Error::into_compile_error)
169        .into()
170}