getters3/
lib.rs

1// Copyright (C) 2023-2024 Rowan Hart
2// SPDX-License-Identifier: Apache-2.0
3
4//! Derive Macro for automatically implementing getter and setter patterns
5//! for structs and enums.
6//!
7//! # Examples
8//!
9//! `getters2` supports both structs and enums, unlike other crates that claim to implement this
10//! pattern!
11//!
12//! ## Structs
13//!
14//! `getters2` supports structs with named fields, newtype structs, and tuple structs.
15//!
16//! ### Named Fields
17//!
18//! ```rust
19//! # use getters2::Getters;
20//! #[derive(Getters)]
21//! struct Vector3 {
22//!    x: f32,
23//!    y: f32,
24//!    z: f32,
25//! }
26//!
27//! let mut v = Vector3 { x: 1.0, y: 2.0, z: 3.0 };
28//! assert_eq!(v.x_ref(), &1.0);
29//! assert_eq!(v.y_ref(), &2.0);
30//! assert_eq!(v.z_ref(), &3.0);
31//! ```
32//!
33//! ### Tuple Structs
34//!
35//! Tuple structs are automatically named from first to last (there is technically a
36//! limit of 20 elements, but if you hit it, you may just want to refactor).
37//!
38//! ```rust
39//! # use getters2::Getters;
40//! #[derive(Getters)]
41//! struct Vector3(f32, f32, f32);
42//!
43//! let mut v = Vector3(1.0, 2.0, 3.0);
44//! assert_eq!(v.first_ref(), &1.0);
45//! assert_eq!(v.second_ref(), &2.0);
46//! assert_eq!(v.last_ref(), &3.0);
47//! ```
48//!
49//! ### Newtype Structs
50//!
51//! Newtype structs work like a single-element tuple struct.
52//!
53//! ```rust
54//! # use getters2::Getters;
55//! #[derive(Getters)]
56//! struct Vector1(f32);
57//!
58//! let mut v = Vector1(1.0);
59//! assert_eq!(v.first_ref(), &1.0);
60//! ```
61//!
62//! ### Mutable, Clone, and Deref Getters
63//!
64//! We don't always want to return an immutable reference to a field. Sometimes we want
65//! to return a mutable reference, dereference the field, or clone the field. `getters2`
66//! supports all of these patterns at either a struct level or a field level. Note that
67//! the field-level attributes will override the struct-level attributes, and will only
68//! work on named structs (there is no way to specify attributes on tuple or newtype
69//! struct elements).
70//!
71//! ### Mutable, Clone, and Deref Struct Getters
72//!
73//! ```rust
74//! # use getters2::Getters;
75//! #[derive(Getters)]
76//! #[getters(deref, clone, mutable)]
77//! struct Vector3 {
78//!   x: f32,
79//!   y: f32,
80//!   z: f32,
81//! }
82//!
83//! let mut v = Vector3 { x: 1.0, y: 2.0, z: 3.0 };
84//! assert_eq!(v.x_ref(), &1.0);
85//! assert_eq!(v.y_ref(), &2.0);
86//! assert_eq!(v.z_ref(), &3.0);
87//! assert_eq!(v.x_deref(), 1.0);
88//! assert_eq!(v.y_deref(), 2.0);
89//! assert_eq!(v.z_deref(), 3.0);
90//! assert_eq!(v.x_clone(), 1.0);
91//! assert_eq!(v.y_clone(), 2.0);
92//! assert_eq!(v.z_clone(), 3.0);
93//! *v.x_mut() = 4.0;
94//! *v.y_mut() = 5.0;
95//! *v.z_mut() = 6.0;
96//! assert_eq!(v.x_ref(), &4.0);
97//! assert_eq!(v.y_ref(), &5.0);
98//! assert_eq!(v.z_ref(), &6.0);
99//! ```
100//!
101//! ### Mutable, Clone, and Deref Field Getters
102//!
103//! ```rust
104//! # use getters2::Getters;
105//! #[derive(Getters)]
106//! struct Vector3 {
107//!   #[getters(deref)]
108//!   x: f32,
109//!   #[getters(deref)]
110//!   y: f32,
111//!   z: f32,
112//! }
113//!
114//! let mut v = Vector3 { x: 1.0, y: 2.0, z: 3.0 };
115//! assert_eq!(v.x_ref(), &1.0);
116//! assert_eq!(v.y_ref(), &2.0);
117//! assert_eq!(v.z_ref(), &3.0);
118//! assert_eq!(v.x_deref(), 1.0);
119//! assert_eq!(v.y_deref(), 2.0);
120//! // No z_deref method!
121//! // assert_eq!(v.z_deref(), 3.0);
122//! ```
123//!
124//! ### Skipping all Getters for a Field
125//!
126//! Sometimes we want to skip generating all getters for certain fields. We can do this
127//! by adding the skip attributes for all the getters we have enabled for the struct:
128//!
129//! * `skip` - Skips the immutable reference getter
130//! * `skip_mutable` - Skips the mutable reference getter
131//! * `skip_deref` - Skips the dereference getter
132//! * `skip_clone` - Skips the clone getter
133//!
134//! ```rust
135//! # use getters2::Getters;
136//! #[derive(Getters)]
137//! #[getters(deref, clone, mutable)]
138//! struct Vector3 {
139//!   #[getters(skip, skip_mutable, skip_deref, skip_clone)]
140//!   x: f32,
141//!   y: f32,
142//!   z: f32,
143//! }
144//!
145//! let mut v = Vector3 { x: 1.0, y: 2.0, z: 3.0 };
146//! // No x_ref method!
147//! // assert_eq!(v.x_ref(), &1.0);
148//! assert_eq!(v.y_ref(), &2.0);
149//! assert_eq!(v.z_ref(), &3.0);
150//! // No x_deref method!
151//! // assert_eq!(v.x_deref(), 1.0);
152//! assert_eq!(v.y_deref(), 2.0);
153//! assert_eq!(v.z_deref(), 3.0);
154//! // No x_clone method!
155//! // assert_eq!(v.x_clone(), 1.0);
156//! assert_eq!(v.y_clone(), 2.0);
157//! assert_eq!(v.z_clone(), 3.0);
158//! // No x_mut method!
159//! // *v.x_mut() = 4.0;
160//! *v.y_mut() = 4.0;
161//! *v.z_mut() = 5.0;
162//! // No x_ref method!
163//! // assert_eq!(v.x_ref(), &4.0);
164//! assert_eq!(v.y_ref(), &4.0);
165//! assert_eq!(v.z_ref(), &5.0);
166//! ```
167//!
168//! ## Enums
169//!
170//! Of course, everything we just saw for structs also works for enums. Because we don't know
171//! which variant of an enum we have, we have to return an `Option` for each getter.
172//!
173//! ### Named Enums
174//!
175//! ```rust
176//! # use getters2::Getters;
177//! #[derive(Getters)]
178//! #[getters(deref, clone, mutable)]
179//! enum Animal {
180//!   Dog {
181//!     #[getters(skip_deref)]
182//!     name: String,
183//!     age: u8
184//!   },
185//!   Cat {
186//!     #[getters(skip_deref)]
187//!     name: String,
188//!     age: u8
189//!   },
190//! }
191//! let mut dog = Animal::Dog { name: "Rover".to_string(), age: 5 };
192//! let mut cat = Animal::Cat { name: "Mittens".to_string(), age: 3 };
193//! assert_eq!(dog.dog_name_ref(), Some(&"Rover".to_string()));
194//! assert_eq!(dog.dog_name_clone(), Some("Rover".to_string()));
195//! assert_eq!(dog.dog_age_ref(), Some(&5));
196//! assert_eq!(dog.dog_age_clone(), Some(5));
197//!
198//! let Some(dog_name) = dog.dog_name_mut() else {
199//!    panic!("Expected Some");
200//! };
201//! *dog_name = "Spot".to_string();
202//!
203//! assert_eq!(dog.dog_name_ref(), Some(&"Spot".to_string()));
204//!
205//! assert_eq!(cat.cat_name_ref(), Some(&"Mittens".to_string()));
206//! assert_eq!(cat.cat_name_clone(), Some("Mittens".to_string()));
207//! assert_eq!(cat.cat_age_ref(), Some(&3));
208//! assert_eq!(cat.cat_age_deref(), Some(3));
209//! assert_eq!(cat.cat_age_clone(), Some(3));
210//!
211//! let Some(cat_name) = cat.cat_name_mut() else {
212//!   panic!("Expected Some");
213//! };
214//! *cat_name = "Whiskers".to_string();
215//!
216//! assert_eq!(cat.cat_name_ref(), Some(&"Whiskers".to_string()));
217//! ```
218//!
219//! ## Tuple and Newtype Enums
220//!
221//! Tuple and newtype enums work just like tuple and newtype structs. Note that we can't
222//! skip individual fields in tuple and newtype enums, but we can skip entire variants.
223//! Unofrtunately, this isn't a crate limitation, just a Rust syntax limitation.Here, we
224//! just turn of deref, because we can't dereference strings.
225//!
226//! ```rust
227//! # use getters2::Getters;
228//! #[derive(Getters)]
229//! #[getters(clone, mutable)]
230//! enum Animal {
231//!   Dog(String, u8),
232//!   Cat(String, u8),
233//! }
234//! let mut dog = Animal::Dog("Rover".to_string(), 5);
235//! let mut cat = Animal::Cat("Mittens".to_string(), 3);
236//! assert_eq!(dog.dog_first_ref(), Some(&"Rover".to_string()));
237//! assert_eq!(dog.dog_first_clone(), Some("Rover".to_string()));
238//! assert_eq!(dog.dog_last_ref(), Some(&5));
239//! assert_eq!(dog.dog_last_clone(), Some(5));
240//! assert_eq!(cat.cat_first_ref(), Some(&"Mittens".to_string()));
241//! assert_eq!(cat.cat_first_clone(), Some("Mittens".to_string()));
242//! assert_eq!(cat.cat_last_ref(), Some(&3));
243//! assert_eq!(cat.cat_last_clone(), Some(3));
244//! ```
245//!
246//! ### Skipping Enum Variants
247//!
248//! In addition to skipping a field in a named enum variant, we can skip entire variants.
249//!
250//! ```rust
251//! # use getters2::Getters;
252//! #[derive(Getters)]
253//! #[getters(deref, clone, mutable)]
254//! enum Animal {
255//!   #[getters(skip, skip_mutable, skip_deref, skip_clone)]
256//!   Dog {
257//!     name: String,
258//!     age: u8
259//!   },
260//!   #[getters(skip, skip_mutable, skip_deref, skip_clone)]
261//!   Cat(i64),
262//!   #[getters(skip, skip_mutable, skip_deref, skip_clone)]
263//!   Person(String, i64, i64),
264//!   
265//! }
266//! ```
267
268#![allow(unused_variables)]
269#![deny(missing_docs)]
270
271use darling::{
272    ast::{Data, Fields},
273    util::Flag,
274    FromDeriveInput, FromField, FromVariant,
275};
276use proc_macro::TokenStream;
277use proc_macro2::{Span, TokenStream as TokenStream2};
278use proc_macro_error2::abort;
279use quote::{format_ident, quote, ToTokens};
280use syn::{
281    parse_macro_input, Attribute, DeriveInput, Expr, Generics, Ident, Index, Member, Type,
282    Visibility,
283};
284
285#[derive(Debug, FromField)]
286#[darling(attributes(getters))]
287struct GettersField {
288    ident: Option<Ident>,
289    #[allow(unused)]
290    vis: Visibility,
291    ty: Type,
292    #[allow(unused)]
293    attrs: Vec<Attribute>,
294    mutable: Flag,
295    deref: Flag,
296    clone: Flag,
297    skip: Flag,
298    skip_mutable: Flag,
299    skip_deref: Flag,
300    skip_clone: Flag,
301}
302
303#[derive(Debug, FromVariant)]
304#[darling(attributes(getters))]
305struct GettersVariant {
306    ident: Ident,
307    discriminant: Option<Expr>,
308    fields: Fields<GettersField>,
309    #[allow(unused)]
310    attrs: Vec<Attribute>,
311    #[allow(unused)]
312    mutable: Flag,
313    #[allow(unused)]
314    deref: Flag,
315    #[allow(unused)]
316    clone: Flag,
317    skip: Flag,
318    skip_mutable: Flag,
319    skip_deref: Flag,
320    skip_clone: Flag,
321}
322
323#[derive(Debug, FromDeriveInput)]
324#[darling(
325    attributes(getters),
326    supports(
327        struct_named,
328        struct_newtype,
329        struct_tuple,
330        enum_named,
331        enum_newtype,
332        enum_tuple,
333        enum_unit
334    ),
335    // NOTE: https://doc.rust-lang.org/reference/attributes.html#built-in-attributes-index
336    forward_attrs(
337        cfg,
338        derive,
339        allow,
340        warn,
341        deny,
342        forbid,
343        deprecated,
344        must_use,
345        doc,
346        non_exhaustive
347    )
348)]
349struct GettersInput {
350    ident: Ident,
351    #[allow(unused)]
352    vis: Visibility,
353    generics: Generics,
354    data: Data<GettersVariant, GettersField>,
355    #[allow(unused)]
356    attrs: Vec<Attribute>,
357    mutable: Flag,
358    clone: Flag,
359    deref: Flag,
360}
361
362impl GettersInput {
363    fn method_field(&self, field: &GettersField, index: usize, max: usize) -> TokenStream2 {
364        let ty = &field.ty;
365        let immutable = !field.skip.is_present();
366        let mutable = (field.mutable.is_present() || self.mutable.is_present())
367            && !field.skip_mutable.is_present();
368        let clone =
369            (field.clone.is_present() || self.clone.is_present()) && !field.skip_clone.is_present();
370        let deref =
371            (field.deref.is_present() || self.deref.is_present()) && !field.skip_deref.is_present();
372
373        let (immutable, maybe_mutable, maybe_clone, maybe_deref) =
374            if let Some(ident) = field.ident.as_ref() {
375                let ident_ref = format_ident!("{}_ref", ident);
376                let ident_mut = format_ident!("{}_mut", ident);
377                let ident_clone = format_ident!("{}_clone", ident);
378                let ident_deref = format_ident!("{}_deref", ident);
379                (
380                    immutable
381                        .then_some(quote! {
382                            #[inline(always)]
383                            /// Return an immutable reference to the field
384                            pub fn #ident_ref(&self) -> &#ty {
385                                &self.#ident
386                            }
387                        })
388                        .unwrap_or_default(),
389                    mutable
390                        .then_some(quote! {
391                            #[inline(always)]
392                            /// Return a mutable reference to the field
393                            pub fn #ident_mut(&mut self) -> &mut #ty {
394                                &mut self.#ident
395                            }
396                        })
397                        .unwrap_or_default(),
398                    clone
399                        .then_some(quote! {
400                            #[inline(always)]
401                            /// Return a clone of the field
402                            pub fn #ident_clone(&self) -> #ty {
403                                self.#ident.clone()
404                            }
405                        })
406                        .unwrap_or_default(),
407                    deref
408                        .then_some(quote! {
409                            #[inline(always)]
410                            /// Return a copy of the field
411                            pub fn #ident_deref(&self) -> #ty {
412                                self.#ident
413                            }
414                        })
415                        .unwrap_or_default(),
416                )
417            } else {
418                // Field with no ident, we generate a named method
419                let name = method_name(index, max);
420                let name_ref = format_ident!("{}_ref", name);
421                let name_mut = format_ident!("{}_mut", name);
422                let name_clone = format_ident!("{}_clone", name);
423                let name_deref = format_ident!("{}_deref", name);
424                let index = Member::Unnamed(Index {
425                    index: index as u32,
426                    span: Span::call_site(),
427                });
428
429                (
430                    immutable
431                        .then_some(quote! {
432                            #[inline(always)]
433                            /// Return an immutable reference to the field
434                            pub fn #name_ref(&self) -> &#ty {
435                                &self.#index
436                            }
437                        })
438                        .unwrap_or_default(),
439                    mutable
440                        .then_some(quote! {
441                            #[inline(always)]
442                            /// Return a mutable reference to the field
443                            pub fn #name_mut(&mut self) -> &mut #ty {
444                                &mut self.#index
445                            }
446                        })
447                        .unwrap_or_default(),
448                    clone
449                        .then_some(quote! {
450                            #[inline(always)]
451                            /// Return a clone of the field
452                            pub fn #name_clone(&self) -> #ty {
453                                self.#index.clone()
454                            }
455                        })
456                        .unwrap_or_default(),
457                    deref
458                        .then_some(quote! {
459                            #[inline(always)]
460                            /// Return a copy of the field
461                            pub fn #name_deref(&self) -> #ty {
462                                self.#index
463                            }
464                        })
465                        .unwrap_or_default(),
466                )
467            };
468
469        quote! {
470            #immutable
471            #maybe_mutable
472            #maybe_clone
473            #maybe_deref
474        }
475    }
476
477    #[allow(clippy::too_many_arguments)]
478    fn method_variant(
479        &self,
480        field: &GettersField,
481        index: usize,
482        max: usize,
483        enum_ident: &Ident,
484        variant_ident: &Ident,
485        skip: bool,
486        skip_mutable: bool,
487        skip_clone: bool,
488        skip_deref: bool,
489    ) -> TokenStream2 {
490        let ty = &field.ty;
491        let immutable = !field.skip.is_present() && !skip;
492        let mutable = (field.mutable.is_present() || self.mutable.is_present())
493            && !field.skip_mutable.is_present()
494            && !skip_mutable;
495        let clone = (field.clone.is_present() || self.clone.is_present())
496            && !field.skip_clone.is_present()
497            && !skip_clone;
498        let deref = (field.deref.is_present() || self.deref.is_present())
499            && !field.skip_deref.is_present()
500            && !skip_deref;
501        let prefix = variant_ident.to_string().to_ascii_lowercase();
502
503        let (immutable, maybe_mutable, maybe_clone, maybe_deref) =
504            if let Some(ident) = field.ident.as_ref() {
505                let ident_ref = format_ident!("{}_{}_ref", prefix, ident);
506                let ident_mut = format_ident!("{}_{}_mut", prefix, ident);
507                let ident_clone = format_ident!("{}_{}_clone", prefix, ident);
508                let ident_deref = format_ident!("{}_{}_deref", prefix, ident);
509                (
510                    immutable
511                        .then_some(quote! {
512                            #[inline(always)]
513                            /// Return an immutable reference to the field
514                            pub fn #ident_ref(&self) -> Option<&#ty> {
515                                if let #enum_ident::#variant_ident { #ident, .. } = self {
516                                    Some(#ident)
517                                } else {
518                                    None
519                                }
520                            }
521                        })
522                        .unwrap_or_default(),
523                    mutable
524                        .then_some(quote! {
525                            #[inline(always)]
526                            /// Return a mutable reference to the field
527                            pub fn #ident_mut(&mut self) -> Option<&mut #ty> {
528                                if let #enum_ident::#variant_ident { ref mut #ident, .. } = self {
529                                    Some(#ident)
530                                } else {
531                                    None
532                                }
533                            }
534                        })
535                        .unwrap_or_default(),
536                    clone
537                        .then_some(quote! {
538                            #[inline(always)]
539                            /// Return a clone of the field
540                            pub fn #ident_clone(&self) -> Option<#ty> {
541                                if let #enum_ident::#variant_ident { #ident, .. } = self {
542                                    Some(#ident.clone())
543                                } else {
544                                    None
545                                }
546                            }
547                        })
548                        .unwrap_or_default(),
549                    deref
550                        .then_some(quote! {
551                            #[inline(always)]
552                            /// Return a copy of the field
553                            pub fn #ident_deref(&self) -> Option<#ty> {
554                                if let #enum_ident::#variant_ident { #ident, .. } = self {
555                                    Some(*#ident)
556                                } else {
557                                    None
558                                }
559                            }
560                        })
561                        .unwrap_or_default(),
562                )
563            } else {
564                // Field with no ident, we generate a named method
565                let name = method_name(index, max);
566                let name_ref = format_ident!("{}_{}_ref", prefix, name);
567                let name_mut = format_ident!("{}_{}_mut", prefix, name);
568                let name_clone = format_ident!("{}_{}_clone", prefix, name);
569                let name_deref = format_ident!("{}_{}_deref", prefix, name);
570                let elements = tuple_elements(index, max);
571                let elements_mut = tuple_elements_mut(index, max);
572                let element = tuple_element_name(index);
573
574                (
575                    immutable
576                        .then_some(quote! {
577                            #[inline(always)]
578                            /// Return an immutable reference to the field
579                            pub fn #name_ref(&self) -> Option<&#ty> {
580                                if let #enum_ident::#variant_ident(#elements) = self {
581                                    Some(#element)
582                                } else {
583                                    None
584                                }
585                            }
586                        })
587                        .unwrap_or_default(),
588                    mutable
589                        .then_some(quote! {
590                            #[inline(always)]
591                            /// Retur a mutable reference to the field
592                            pub fn #name_mut(&mut self) -> Option<&mut #ty> {
593                                if let #enum_ident::#variant_ident(#elements_mut) = self {
594                                    Some(#element)
595                                } else {
596                                    None
597                                }
598                            }
599                        })
600                        .unwrap_or_default(),
601                    clone
602                        .then_some(quote! {
603                            #[inline(always)]
604                            /// Return a clone of the field
605                            pub fn #name_clone(&self) -> Option<#ty> {
606                                if let #enum_ident::#variant_ident(#elements) = self {
607                                    Some(#element.clone())
608                                } else {
609                                    None
610                                }
611                            }
612                        })
613                        .unwrap_or_default(),
614                    deref
615                        .then_some(quote! {
616                            #[inline(always)]
617                            /// Return a copy of the field
618                            pub fn #name_deref(&self) -> Option<#ty> {
619                                if let #enum_ident::#variant_ident(#elements) = self {
620                                    Some(*#element)
621                                } else {
622                                    None
623                                }
624                            }
625                        })
626                        .unwrap_or_default(),
627                )
628            };
629
630        quote! {
631            #immutable
632            #maybe_mutable
633            #maybe_clone
634            #maybe_deref
635        }
636    }
637
638    fn methods_struct(&self, fields: &Fields<&GettersField>) -> TokenStream2 {
639        fields
640            .iter()
641            .enumerate()
642            .map(|(i, f)| self.method_field(f, i, fields.len()))
643            .collect::<TokenStream2>()
644    }
645
646    fn methods_enum(&self, variants: &[&GettersVariant]) -> TokenStream2 {
647        variants
648            .iter()
649            .map(|v| {
650                let variant_ident = &v.ident;
651
652                if let Some(discriminant) = v.discriminant.as_ref() {
653                    abort!(
654                        discriminant,
655                        "Getters cannot be derived for enums with discriminants"
656                    )
657                }
658
659                v.fields
660                    .iter()
661                    .enumerate()
662                    .map(|(i, f)| {
663                        self.method_variant(
664                            f,
665                            i,
666                            v.fields.len(),
667                            &self.ident,
668                            variant_ident,
669                            v.skip.is_present(),
670                            v.skip_mutable.is_present(),
671                            v.skip_clone.is_present(),
672                            v.skip_deref.is_present(),
673                        )
674                    })
675                    .collect::<TokenStream2>()
676            })
677            .collect::<TokenStream2>()
678    }
679}
680
681impl ToTokens for GettersInput {
682    fn to_tokens(&self, tokens: &mut TokenStream2) {
683        let ident = &self.ident;
684        let (impl_generics, ty_generics, where_clause) = self.generics.split_for_impl();
685
686        let methods = if let Some(ref fields) = self.data.as_ref().take_struct() {
687            self.methods_struct(fields)
688        } else if let Some(ref variants) = self.data.as_ref().take_enum() {
689            self.methods_enum(variants)
690        } else {
691            abort!(
692                self.ident,
693                "Getters can only be derived for structs and enums"
694            )
695        };
696
697        tokens.extend(quote! {
698            impl #impl_generics #ident #ty_generics #where_clause {
699                #methods
700            }
701        })
702    }
703}
704
705#[proc_macro_derive(Getters, attributes(getters))]
706#[allow(non_snake_case)]
707/// Derive macro for automatically implementing getter and setter patterns
708///
709/// # Examples
710///
711/// Structs:
712///
713/// ```rust
714/// # use getters2::Getters;
715/// #[derive(Getters)]
716/// #[getters(deref, clone, mutable)]
717/// struct NamedVector3 {
718///    x: f32,
719///    y: f32,
720///    z: f32,
721///    #[getters(skip_deref)]
722///    // NOTE: Skip deref, can't dereference strings.
723///    name: String,
724/// }
725///
726/// let mut v = NamedVector3 { x: 1.0, y: 2.0, z: 3.0, name: "foo".to_string() };
727/// assert_eq!(v.x_ref(), &1.0);
728/// assert_eq!(v.y_deref(), 2.0);
729/// assert_eq!(v.z_clone(), 3.0);
730/// *v.x_mut() = 4.0;
731/// assert_eq!(v.x_ref(), &4.0);
732/// ```
733///
734/// Tuple Structs:
735///
736/// ```rust
737/// # use getters2::Getters;
738///
739/// #[derive(Getters)]
740/// #[getters(deref, clone, mutable)]
741/// struct TupleVector3(f32, f32, f32);
742///
743/// let mut v = TupleVector3(1.0, 2.0, 3.0);
744///
745/// assert_eq!(v.first_ref(), &1.0);
746/// assert_eq!(v.second_deref(), 2.0);
747/// assert_eq!(v.last_clone(), 3.0);
748/// *v.first_mut() = 4.0;
749/// assert_eq!(v.first_ref(), &4.0);
750/// ```
751///
752/// Named Enums:
753///
754/// ```rust
755/// # use getters2::Getters;
756///
757/// #[derive(Getters)]
758/// #[getters(deref, clone, mutable)]
759/// enum Animal {
760///   Dog {
761///     #[getters(skip_deref)]
762///     name: String,
763///     age: u8
764///   },
765///   Cat {
766///     #[getters(skip_deref)]
767///     name: String,
768///     age: u8
769///   },
770/// }
771///
772/// let mut dog = Animal::Dog { name: "Rover".to_string(), age: 5 };
773/// let mut cat = Animal::Cat { name: "Mittens".to_string(), age: 3 };
774///
775/// assert_eq!(dog.dog_name_ref(), Some(&"Rover".to_string()));
776/// assert_eq!(dog.dog_name_clone(), Some("Rover".to_string()));
777/// assert_eq!(dog.dog_age_ref(), Some(&5));
778/// assert_eq!(dog.dog_age_deref(), Some(5));
779/// assert_eq!(cat.cat_name_ref(), Some(&"Mittens".to_string()));
780/// assert_eq!(cat.cat_name_clone(), Some("Mittens".to_string()));
781/// assert_eq!(cat.cat_age_ref(), Some(&3));
782/// assert_eq!(cat.cat_age_deref(), Some(3));
783/// ```
784///
785/// Tuple Enums:
786///
787/// ```rust
788/// # use getters2::Getters;
789///
790/// #[derive(Getters)]
791/// #[getters(clone, mutable)]
792/// enum Animal {
793///   Dog(String, u8),
794///   Cat(String, u8),
795/// }
796///
797/// let mut dog = Animal::Dog("Rover".to_string(), 5);
798/// let mut cat = Animal::Cat("Mittens".to_string(), 3);
799///
800/// assert_eq!(dog.dog_first_ref(), Some(&"Rover".to_string()));
801/// assert_eq!(dog.dog_first_clone(), Some("Rover".to_string()));
802/// assert_eq!(dog.dog_last_ref(), Some(&5));
803/// assert_eq!(dog.dog_last_clone(), Some(5));
804/// assert_eq!(cat.cat_first_ref(), Some(&"Mittens".to_string()));
805/// assert_eq!(cat.cat_first_clone(), Some("Mittens".to_string()));
806/// assert_eq!(cat.cat_last_ref(), Some(&3));
807/// assert_eq!(cat.cat_last_clone(), Some(3));
808/// ```
809///
810pub fn Getters(input: TokenStream) -> TokenStream {
811    let getters = match GettersInput::from_derive_input(&parse_macro_input!(input as DeriveInput)) {
812        Ok(g) => g,
813        Err(e) => {
814            return TokenStream::from(e.write_errors());
815        }
816    };
817
818    let mut tokens = TokenStream2::new();
819
820    getters.to_tokens(&mut tokens);
821
822    tokens.into()
823}
824
825const NUMERAL_TO_ORDINAL: [&str; 20] = [
826    "first",
827    "second",
828    "third",
829    "fourth",
830    "fifth",
831    "sixth",
832    "seventh",
833    "eigth",
834    "ninth",
835    "tenth",
836    "eleventh",
837    "twelfth",
838    "thirteenth",
839    "fourteenth",
840    "fifteenth",
841    "sixteenth",
842    "seventeenth",
843    "eighteenth",
844    "nineteenth",
845    "twentieth",
846];
847const LAST: &str = "last";
848
849/// Given an index (0, 1, 2, ...) return the name of the method
850/// (first, second, third, ..., last)
851fn method_name(i: usize, max: usize) -> Ident {
852    if i == max - 1 && max != 1 {
853        Ident::new(LAST, Span::call_site())
854    } else {
855        Ident::new(NUMERAL_TO_ORDINAL[i], Span::call_site())
856    }
857}
858
859const TUPLE_ELEMENTS: [&str; 20] = [
860    "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s",
861    "t",
862];
863
864fn tuple_element_name(index: usize) -> Ident {
865    Ident::new(TUPLE_ELEMENTS[index], Span::call_site())
866}
867
868fn tuple_elements(index: usize, max: usize) -> TokenStream2 {
869    (0..max)
870        .map(tuple_element_name)
871        .enumerate()
872        .map(|(i, n)| {
873            let ident = if i == index {
874                format_ident!("{}", n)
875            } else {
876                format_ident!("_{}", n)
877            };
878
879            if i == max - 1 {
880                quote!(ref #ident)
881            } else {
882                quote!(ref #ident,)
883            }
884        })
885        .collect::<TokenStream2>()
886}
887
888fn tuple_elements_mut(index: usize, max: usize) -> TokenStream2 {
889    (0..max)
890        .map(tuple_element_name)
891        .enumerate()
892        .map(|(i, n)| {
893            let ident = if i == index {
894                format_ident!("{}", n)
895            } else {
896                format_ident!("_{}", n)
897            };
898
899            let maybe_mut = if i == index { quote!(mut) } else { quote!() };
900
901            if i == max - 1 {
902                quote!(ref #maybe_mut #ident)
903            } else {
904                quote!(ref #maybe_mut #ident,)
905            }
906        })
907        .collect::<TokenStream2>()
908}