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}