• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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