small_derive_deref/lib.rs
1#![crate_name = "small_derive_deref"]
2//! ## Example
3//!
4//! ```rust
5//! use std::ops::DerefMut;
6//! use small_derive_deref::{Deref, DerefMut};
7//!
8//! #[derive(Deref, DerefMut)]
9//! struct WrapperStructDifferentTargetsMultipleGenerics<'a, T> {
10//! #[DerefTarget]
11//! field: &'a str,
12//! #[DerefMutTarget]
13//! field_mut: &'a str,
14//! foo: T
15//! }
16//!
17//! let mut w = WrapperStructDifferentTargetsMultipleGenerics { field: "not rust", field_mut: "rust", foo: "foo"};
18//! assert_eq!(*w, "not rust");
19//! *w = "rUst";
20//! assert_eq!(*w.deref_mut(), "rUst");
21//!
22//! #[derive(Deref, DerefMut)]
23//! struct WrapperTuple(i32, i32);
24//!
25//! let mut w = WrapperTuple(1, 3);
26//! *w *= 2;
27//! assert_eq!(*w, 2);
28//! assert_eq!(*w.deref_mut(), 2);
29//! ```
30
31use proc_macro::TokenStream;
32use quote::quote;
33use syn::{parse_macro_input, Data, DeriveInput, Fields};
34
35/// Defines Deref either on a struct or a tuple.<br>
36/// No attribute needed for structs with one field or tuples.<br>
37/// ## Example
38///
39/// ```rust
40/// use small_derive_deref::Deref;
41///
42/// #[derive(Deref)]
43/// struct WrapperStruct {
44/// field: i32,
45/// }
46///
47/// let w = WrapperStruct { field: 1 };
48/// assert_eq!(*w, 1);
49///
50/// #[derive(Deref)]
51/// struct WrapperMultipleStruct {
52/// #[DerefTarget]
53/// field1: i32,
54/// field2: i32,
55/// }
56///
57/// let w = WrapperMultipleStruct { field1: 1, field2: 2 };
58///
59/// assert_eq!(*w, 1);
60///
61/// #[derive(Deref)]
62/// struct WrapperTuple(i32);
63///
64/// let w = WrapperTuple(1);
65/// assert_eq!(*w, 1);
66/// ```
67#[proc_macro_derive(Deref, attributes(DerefTarget))]
68pub fn derive_deref(input: TokenStream) -> TokenStream {
69 let input = parse_macro_input!(input as DeriveInput);
70 let name = input.ident;
71 let (impl_generics, type_generics, where_clause) = input.generics.split_for_impl();
72
73 let expanded = match input.data {
74 Data::Struct(data_struct) => {
75 match &data_struct.fields {
76 Fields::Named(named) => {
77 let field = match named.named.len() {
78 1 => { named.named.first() }
79 _ => named.named.iter()
80 .find_map(|field| {
81 for attr in &field.attrs {
82 if attr.path().is_ident("DerefTarget") {
83 return Some(field);
84 }
85 }
86 None
87 })
88 };
89
90 if let Some(field) = field {
91 let field_name = &field.ident;
92 let field_type = &field.ty;
93
94 quote! {
95 impl #impl_generics std::ops::Deref for #name #type_generics #where_clause {
96 type Target = #field_type;
97
98 fn deref(&self) -> &Self::Target {
99 &self.#field_name
100 }
101 }
102 }
103 } else {
104 panic!("No field with #[DerefTarget]")
105 }
106 },
107 Fields::Unnamed(unnamed) => {
108 let field_type = &unnamed.unnamed[0].ty;
109
110 quote! {
111 impl #impl_generics std::ops::Deref for #name #type_generics #where_clause {
112 type Target = #field_type;
113
114 fn deref(&self) -> &Self::Target {
115 &self.0
116 }
117 }
118 }
119
120 },
121 Fields::Unit => panic!("Deref not implemented for unit structs")
122 }
123 },
124 _ => panic!("Deref only implemented for structs")
125 };
126
127 expanded.into()
128}
129
130
131/// Defines DerefMut either on a struct or a tuple.<br>
132/// No attribute needed for structs with one field or tuples.<br>
133/// # Examples
134/// ## Struct
135/// ```rust
136/// use std::ops::DerefMut;
137/// use small_derive_deref::{Deref, DerefMut};
138///
139/// #[derive(DerefMut, Deref)]
140/// struct WrapperStruct {
141/// field: i32,
142/// }
143///
144/// let mut w = WrapperStruct { field: 1 };
145/// *w *= 2;
146/// assert_eq!(*w.deref_mut(), 2);
147///
148/// #[derive(DerefMut, Deref)]
149/// struct WrapperMultipleStruct {
150/// #[DerefTarget]
151/// field1: i32,
152/// #[DerefMutTarget]
153/// field2: i32,
154/// }
155///
156/// let mut w = WrapperMultipleStruct { field1: 1, field2: 3 };
157/// *w *= 2;
158/// assert_eq!(*w.deref_mut(), 6);
159/// assert_eq!(*w, 1);
160///
161/// #[derive(DerefMut, Deref)]
162/// struct WrapperTuple(i32);
163///
164/// let mut w = WrapperTuple(1);
165/// *w *= 2;
166/// assert_eq!(*w.deref_mut(), 2);
167/// ```
168#[proc_macro_derive(DerefMut, attributes(DerefMutTarget))]
169pub fn derive_deref_mut(input: TokenStream) -> TokenStream {
170 let input = parse_macro_input!(input as DeriveInput);
171 let struct_name = input.ident;
172 let (impl_generics, type_generics, where_clause) = input.generics.split_for_impl();
173
174 let expanded = match input.data {
175 syn::Data::Struct(data_struct) => {
176 match &data_struct.fields {
177 Fields::Named(named) => {
178 let field = match named.named.len() {
179 1 => { named.named.first() }
180 _ => named.named.iter()
181 .find_map(|field| {
182 for attr in &field.attrs {
183 if attr.path().is_ident("DerefMutTarget") {
184 return Some(field);
185 }
186 }
187 None
188 })
189 };
190
191 if let Some(field) = field {
192 let field_name = &field.ident;
193 quote! {
194 impl #impl_generics std::ops::DerefMut for #struct_name #type_generics #where_clause {
195 fn deref_mut(&mut self) -> &mut Self::Target {
196 &mut self.#field_name
197 }
198 }
199 }
200 } else {
201 panic!("No field marked with #[DerefMutTarget]")
202 }
203 },
204 Fields::Unnamed(_) => {
205 quote! {
206 impl #impl_generics std::ops::DerefMut for #struct_name #type_generics #where_clause {
207 fn deref_mut(&mut self) -> &mut Self::Target {
208 &mut self.0
209 }
210 }
211 }
212 },
213 Fields::Unit => panic!("DerefMut not implemented for unit structs"),
214 }
215 },
216 _ => panic!("DerefMut only implemented for structs"),
217 };
218
219 expanded.into()
220}