1use proc_macro::TokenStream;
5use quote::quote;
6use syn::{parse, Data, DataStruct, DeriveInput, Field, Fields, FieldsUnnamed, Ident};
7
8#[proc_macro_derive(New)]
10pub fn derive_new(input: TokenStream) -> TokenStream {
11 for_new_type(&parse(input).unwrap(), "New", |name, field| {
12 let ty = &field.ty;
13 quote! {
14 impl #name {
15 pub fn new(value: #ty) -> Self {
16 Self(value)
17 }
18 }
19 }
20 .into()
21 })
22}
23
24#[proc_macro_derive(Inner)]
26pub fn derive_inner(input: TokenStream) -> TokenStream {
27 for_new_type(&parse(input).unwrap(), "Inner", |name, field| {
28 let ty = &field.ty;
29 quote! {
30 impl #name {
31 pub fn inner(&self) -> &#ty {
32 &self.0
33 }
34 }
35 }
36 .into()
37 })
38}
39
40#[proc_macro_derive(From)]
42pub fn derive_from(input: TokenStream) -> TokenStream {
43 for_new_type(&parse(input).unwrap(), "From", |name, field| {
44 let ty = &field.ty;
45 quote! {
46 impl std::convert::From<#ty> for #name {
47 fn from(value: #ty) -> Self {
48 Self(value)
49 }
50 }
51 }
52 .into()
53 })
54}
55
56#[proc_macro_derive(Add)]
58pub fn derive_add(input: TokenStream) -> TokenStream {
59 for_new_type(&parse(input).unwrap(), "Add", |name, _| {
60 quote! {
61 impl std::ops::Add for #name {
62 type Output = Self;
63 fn add(self, rhs: Self) -> Self::Output {
64 Self(self.0 + rhs.0)
65 }
66 }
67 }
68 .into()
69 })
70}
71
72#[proc_macro_derive(AddAssign)]
74pub fn derive_add_assign(input: TokenStream) -> TokenStream {
75 for_new_type(&parse(input).unwrap(), "AddAssign", |name, _| {
76 quote! {
77 impl std::ops::AddAssign for #name {
78 fn add_assign(&mut self, rhs: Self) {
79 self.0 += rhs.0;
80 }
81 }
82 }
83 .into()
84 })
85}
86
87#[proc_macro_derive(Sub)]
89pub fn derive_sub(input: TokenStream) -> TokenStream {
90 for_new_type(&parse(input).unwrap(), "Sub", |name, _| {
91 quote! {
92 impl std::ops::Sub for #name {
93 type Output = Self;
94 fn sub(self, rhs: Self) -> Self::Output {
95 Self(self.0 - rhs.0)
96 }
97 }
98 }
99 .into()
100 })
101}
102
103#[proc_macro_derive(SubAssign)]
105pub fn derive_sub_assign(input: TokenStream) -> TokenStream {
106 for_new_type(&parse(input).unwrap(), "SubAssign", |name, _| {
107 quote! {
108 impl std::ops::SubAssign for #name {
109 fn sub_assign(&mut self, rhs: Self) {
110 self.0 -= rhs.0;
111 }
112 }
113 }
114 .into()
115 })
116}
117
118#[proc_macro_derive(Mul)]
120pub fn derive_mul(input: TokenStream) -> TokenStream {
121 for_new_type(&parse(input).unwrap(), "Mul", |name, _| {
122 quote! {
123 impl std::ops::Mul for #name {
124 type Output = Self;
125 fn mul(self, rhs: Self) -> Self::Output {
126 Self(self.0 * rhs.0)
127 }
128 }
129 }
130 .into()
131 })
132}
133
134#[proc_macro_derive(MulAssign)]
136pub fn derive_mul_assign(input: TokenStream) -> TokenStream {
137 for_new_type(&parse(input).unwrap(), "MulAssign", |name, _| {
138 quote! {
139 impl std::ops::MulAssign for #name {
140 fn mul_assign(&mut self, rhs: Self) {
141 self.0 *= rhs.0;
142 }
143 }
144 }
145 .into()
146 })
147}
148
149#[proc_macro_derive(MulScalar)]
151pub fn derive_mul_scalar(input: TokenStream) -> TokenStream {
152 for_new_type(&parse(input).unwrap(), "Mul", |name, field| {
153 let ty = &field.ty;
154 quote! {
155 impl std::ops::Mul<#ty> for #name {
156 type Output = Self;
157 fn mul(self, rhs: #ty) -> Self::Output {
158 Self(self.0 * rhs)
159 }
160 }
161 }
162 .into()
163 })
164}
165
166#[proc_macro_derive(MulAssignScalar)]
168pub fn derive_mul_assign_scalar(input: TokenStream) -> TokenStream {
169 for_new_type(&parse(input).unwrap(), "MulAssign", |name, field| {
170 let ty = &field.ty;
171 quote! {
172 impl std::ops::MulAssign<#ty> for #name {
173 fn mul_assign(&mut self, rhs: #ty) {
174 self.0 *= rhs;
175 }
176 }
177 }
178 .into()
179 })
180}
181
182#[proc_macro_derive(Div)]
184pub fn derive_div(input: TokenStream) -> TokenStream {
185 for_new_type(&parse(input).unwrap(), "Div", |name, _| {
186 quote! {
187 impl std::ops::Div for #name {
188 type Output = Self;
189 fn div(self, rhs: Self) -> Self::Output {
190 Self(self.0 / rhs.0)
191 }
192 }
193 }
194 .into()
195 })
196}
197
198#[proc_macro_derive(DivAssign)]
200pub fn derive_div_assign(input: TokenStream) -> TokenStream {
201 for_new_type(&parse(input).unwrap(), "DivAssign", |name, _| {
202 quote! {
203 impl std::ops::DivAssign for #name {
204 fn div_assign(&mut self, rhs: Self) {
205 self.0 /= rhs.0;
206 }
207 }
208 }
209 .into()
210 })
211}
212
213#[proc_macro_derive(DivScalar)]
215pub fn derive_div_scalar(input: TokenStream) -> TokenStream {
216 for_new_type(&parse(input).unwrap(), "Div", |name, field| {
217 let ty = &field.ty;
218 quote! {
219 impl std::ops::Div<#ty> for #name {
220 type Output = Self;
221 fn div(self, rhs: #ty) -> Self::Output {
222 Self(self.0 / rhs)
223 }
224 }
225 }
226 .into()
227 })
228}
229
230#[proc_macro_derive(DivAssignScalar)]
232pub fn derive_div_assign_scalar(input: TokenStream) -> TokenStream {
233 for_new_type(&parse(input).unwrap(), "DivAssign", |name, field| {
234 let ty = &field.ty;
235 quote! {
236 impl std::ops::DivAssign<#ty> for #name {
237 fn div_assign(&mut self, rhs: #ty) {
238 self.0 /= rhs;
239 }
240 }
241 }
242 .into()
243 })
244}
245
246#[proc_macro_derive(Rem)]
248pub fn derive_rem(input: TokenStream) -> TokenStream {
249 for_new_type(&parse(input).unwrap(), "Rem", |name, _| {
250 quote! {
251 impl std::ops::Rem for #name {
252 type Output = Self;
253 fn rem(self, rhs: Self) -> Self::Output {
254 Self(self.0 % rhs.0)
255 }
256 }
257 }
258 .into()
259 })
260}
261
262#[proc_macro_derive(RemAssign)]
264pub fn derive_rem_assign(input: TokenStream) -> TokenStream {
265 for_new_type(&parse(input).unwrap(), "RemAssign", |name, _| {
266 quote! {
267 impl std::ops::RemAssign for #name {
268 fn rem_assign(&mut self, rhs: Self) {
269 self.0 %= rhs.0;
270 }
271 }
272 }
273 .into()
274 })
275}
276
277#[proc_macro_derive(RemScalar)]
279pub fn derive_rem_scalar(input: TokenStream) -> TokenStream {
280 for_new_type(&parse(input).unwrap(), "Rem", |name, field| {
281 let ty = &field.ty;
282 quote! {
283 impl std::ops::Rem<#ty> for #name {
284 type Output = Self;
285 fn rem(self, rhs: #ty) -> Self::Output {
286 Self(self.0 % rhs)
287 }
288 }
289 }
290 .into()
291 })
292}
293
294#[proc_macro_derive(RemAssignScalar)]
296pub fn derive_rem_assign_scalar(input: TokenStream) -> TokenStream {
297 for_new_type(&parse(input).unwrap(), "RemAssign", |name, field| {
298 let ty = &field.ty;
299 quote! {
300 impl std::ops::RemAssign<#ty> for #name {
301 fn rem_assign(&mut self, rhs: #ty) {
302 self.0 %= rhs;
303 }
304 }
305 }
306 .into()
307 })
308}
309
310fn for_new_type<F>(ast: &DeriveInput, t: &str, f: F) -> TokenStream
312where
313 F: Fn(&Ident, &Field) -> TokenStream,
314{
315 match &ast.data {
316 Data::Struct(DataStruct {
317 struct_token: _,
318 fields:
319 Fields::Unnamed(FieldsUnnamed {
320 paren_token: _,
321 unnamed,
322 }),
323 semi_token: _,
324 }) if unnamed.len() == 1 => {
325 let field = unnamed.first().unwrap();
326 f(&ast.ident, field)
327 }
328 _ => panic!("#[derive({t})] is only defined for newtypes (unary tuple structs)"),
329 }
330}