1 //! This library provides two derive macros. One, `Getters` for autogenerating getters and
2 //! `Dissolve` for consuming a struct returning a tuple of all fields. They can only be
3 //! used on named structs.
4 //!
5 //! # Derives
6 //!
7 //! Only named structs can derive `Getters` or `Dissolve`.
8 //!
9 //! # `Getter` methods generated
10 //!
11 //! The getter methods generated shall bear the same name as the struct fields and be
12 //! publicly visible. The methods return an immutable reference to the struct field of the
13 //! same name. If there is already a method defined with that name there'll be a collision.
14 //! In these cases one of two attributes can be set to either `skip` or `rename` the getter.
15 //!
16 //!
17 //! # `Getters` Usage
18 //!
19 //! In lib.rs or main.rs;
20 //!
21 //! ```edition2018
22 //! use derive_getters::Getters;
23 //!
24 //! #[derive(Getters)]
25 //! struct Number {
26 //! num: u64,
27 //! }
28 //!
29 //! fn main() {
30 //! let number = Number { num: 655 };
31 //! assert!(number.num() == &655);
32 //! }
33 //! ```
34 //!
35 //! Here, a method called `num()` has been created for the `Number` struct which gives a
36 //! reference to the `num` field.
37 //!
38 //! This macro can also derive on structs that have simple generic types. For example;
39 //!
40 //! ```edition2018
41 //! # use derive_getters::Getters;
42 //! #[derive(Getters)]
43 //! struct Generic<T, U> {
44 //! gen_t: T,
45 //! gen_u: U,
46 //! }
47 //! #
48 //! # fn main() { }
49 //! ```
50 //!
51 //! The macro can also handle generic types with trait bounds. For example;
52 //! ```edition2018
53 //! # use derive_getters::Getters;
54 //! #[derive(Getters)]
55 //! struct Generic<T: Clone, U: Copy> {
56 //! gen_t: T,
57 //! gen_u: U,
58 //! }
59 //! #
60 //! # fn main() { }
61 //! ```
62 //! The trait bounds can also be declared in a `where` clause.
63 //!
64 //! Additionaly, simple lifetimes are OK too;
65 //! ```edition2018
66 //! # use derive_getters::Getters;
67 //! #[derive(Getters)]
68 //! struct Annotated<'a, 'b, T> {
69 //! stuff: &'a T,
70 //! comp: &'b str,
71 //! num: u64,
72 //! }
73 //! #
74 //! # fn main() { }
75 //! ```
76 //!
77 //! # `Getter` Attributes
78 //! Getters can be further configured to either skip or rename a getter.
79 //!
80 //! * #[getter(skip)]
81 //! Will skip generating a getter for the field being decorated.
82 //!
83 //! * #[getter(rename = "name")]
84 //! Changes the name of the getter (default is the field name) to "name".
85 //!
86 //!```edition2018
87 //! # use derive_getters::Getters;
88 //! #[derive(Getters)]
89 //! struct Attributed {
90 //! keep_me: u64,
91 //!
92 //! #[getter(skip)]
93 //! skip_me: u64,
94 //!
95 //! #[getter(rename = "number")]
96 //! rename_me: u64,
97 //! }
98 //! #
99 //! # fn main() { }
100 //! ```
101 //!
102 //! # `Dissolve` method generated
103 //!
104 //! Deriving `Dissolve` on a named struct will generate a method `dissolve(self)` which
105 //! shall return a tuple of all struct fields in the order they were defined. Calling this
106 //! method consumes the struct. The name of this method can be changed with an attribute.
107 //!
108 //! # `Dissolve` usage
109 //!
110 //! ```edition2018
111 //! # use derive_getters::Dissolve;
112 //! #[derive(Dissolve)]
113 //! struct Stuff {
114 //! name: String,
115 //! price: f64,
116 //! count: usize,
117 //! }
118 //!
119 //! fn main() {
120 //! let stuff = Stuff {
121 //! name: "Hogie".to_owned(),
122 //! price: 123.4f64,
123 //! count: 100,
124 //! };
125 //!
126 //! let (n, p, c) = stuff.dissolve();
127 //! assert!(n == "Hogie");
128 //! assert!(p == 123.4f64);
129 //! assert!(c == 100);
130 //! }
131 //! ```
132 //!
133 //! # `Dissolve` Attributes
134 //! You can rename the `dissolve` function by using a struct attribute.
135 //!
136 //! * #[dissolve(rename = "name")]
137 //!
138 //! ```edition2018
139 //! # use derive_getters::Dissolve;
140 //! #[derive(Dissolve)]
141 //! #[dissolve(rename = "shatter")]
142 //! struct Numbers {
143 //! a: u64,
144 //! b: i64,
145 //! c: f64,
146 //! }
147 //! #
148 //! # fn main() { }
149 //! ```
150 //!
151 //! # Panics
152 //!
153 //! If `Getters` or `Dissolve` are derived on unit or unnamed structs, enums or unions.
154 //!
155 //! # Cannot Do
156 //! Const generics aren't handled by this macro nor are they tested.
157 use std::convert::TryFrom;
158
159 extern crate proc_macro;
160 use syn::{DeriveInput, parse_macro_input};
161
162 mod faultmsg;
163 mod dissolve;
164 mod getters;
165 mod extract;
166
167 /// Generate getter methods for all named struct fields in a seperate struct `impl` block.
168 /// Getter methods share the name of the field they're 'getting'. Methods return an
169 /// immutable reference to the field.
170 #[proc_macro_derive(Getters, attributes(getter))]
getters(input: proc_macro::TokenStream) -> proc_macro::TokenStream171 pub fn getters(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
172 let ast = parse_macro_input!(input as DeriveInput);
173
174 getters::NamedStruct::try_from(&ast)
175 .map(|ns| ns.emit())
176 .unwrap_or_else(|err| err.to_compile_error())
177 .into()
178 }
179
180 /// Produce a `dissolve` method that consumes the named struct returning a tuple of all the
181 /// the struct fields.
182 #[proc_macro_derive(Dissolve, attributes(dissolve))]
dissolve(input: proc_macro::TokenStream) -> proc_macro::TokenStream183 pub fn dissolve(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
184 let ast = parse_macro_input!(input as DeriveInput);
185
186 dissolve::NamedStruct::try_from(&ast)
187 .map(|ns| ns.emit())
188 .unwrap_or_else(|err| err.to_compile_error())
189 .into()
190 }
191