macro_tools/
item_struct.rs

1//!
2//! Parse structures, like `struct { a : i32 }`.
3//!
4
5/// Define a private namespace for all its items.
6mod private
7{
8  #[ allow( clippy::wildcard_imports ) ]
9  use crate::*;
10  // use iter_tools::{ IterTrait, BoxedIter };
11
12  /// Extracts the types of each field into a vector.
13  #[ must_use ]
14  pub fn field_types( t : &syn::ItemStruct )
15  ->
16  impl IterTrait< '_, &syn::Type >
17  // -> std::iter::Map
18  // <
19  //   syn::punctuated::Iter< 'a, syn::Field >,
20  //   impl FnMut( &'a syn::Field ) -> &'a syn::Type + 'a,
21  // >
22  {
23    t.fields.iter().map( | field | &field.ty )
24  }
25
26  /// Retrieves the names of each field, if they exist.
27  /// # Errors
28  /// qqq: doc
29  /// # Panics
30  /// qqq: error
31  #[ allow( clippy::match_wildcard_for_single_variants ) ]
32  #[ must_use ]
33  pub fn field_names( t : &syn::ItemStruct ) -> Option< BoxedIter< '_, &syn::Ident > >
34  {
35    match &t.fields
36    {
37      syn::Fields::Named( fields ) => Some( Box::new( fields.named.iter().map( | field | field.ident.as_ref().unwrap() ) ) ),
38      syn::Fields::Unit => Some( Box::new( core::iter::empty() ) ),
39      _ => None,
40    }
41  }
42
43  /// Retrieves the type of the first field of the struct.
44  ///
45  /// Returns the type if the struct has at least one field, otherwise returns an error.
46  /// # Errors
47  /// qqq
48  #[ allow( clippy::match_wildcard_for_single_variants ) ]
49  pub fn first_field_type( t : &syn::ItemStruct ) -> Result< syn::Type >
50  {
51    let maybe_field = match t.fields
52    {
53      syn::Fields::Named( ref fields ) => fields.named.first(),
54      syn::Fields::Unnamed( ref fields ) => fields.unnamed.first(),
55      _ => return Err( syn_err!( t.fields.span(), "Expects either named or unnamed field" ) ),
56    };
57
58    if let Some( field ) = maybe_field
59    {
60      return Ok( field.ty.clone() )
61    }
62
63    Err( syn_err!( t.span(), "Expects at least one field" ) )
64  }
65
66  /// Retrieves the name of the first field of the struct, if available.
67  ///
68  /// Returns `Some` with the field identifier for named fields, or `None` for unnamed fields.
69  /// Returns an error if the struct has no fields
70  /// # Errors
71  /// qqq: doc
72  #[ allow( clippy::match_wildcard_for_single_variants ) ]
73  pub fn first_field_name( t : &syn::ItemStruct ) -> Result< Option< syn::Ident > >
74  {
75    let maybe_field = match t.fields
76    {
77      syn::Fields::Named( ref fields ) => fields.named.first(),
78      syn::Fields::Unnamed( ref fields ) => fields.unnamed.first(),
79      _ => return Err( syn_err!( t.fields.span(), "Expects fields" ) ),
80    };
81
82    if let Some( field ) = maybe_field
83    {
84      return Ok( field.ident.clone() )
85    }
86
87    Err( syn_err!( t.span(), "Expects type for fields" ) )
88  }
89
90
91}
92
93#[ doc( inline ) ]
94#[ allow( unused_imports ) ]
95pub use own::*;
96
97/// Own namespace of the module.
98#[ allow( unused_imports ) ]
99pub mod own
100{
101  #[ allow( clippy::wildcard_imports ) ]
102  use super::*;
103  #[ doc( inline ) ]
104  pub use orphan::*;
105  #[ doc( inline ) ]
106  pub use private::
107  {
108    field_types,
109    field_names,
110    first_field_type,
111    first_field_name,
112  };
113}
114
115/// Orphan namespace of the module.
116#[ allow( unused_imports ) ]
117pub mod orphan
118{
119  #[ allow( clippy::wildcard_imports ) ]
120  use super::*;
121  #[ doc( inline ) ]
122  pub use exposed::*;
123}
124
125/// Exposed namespace of the module.
126#[ allow( unused_imports ) ]
127pub mod exposed
128{
129  #[ allow( clippy::wildcard_imports ) ]
130  use super::*;
131  pub use super::super::item_struct;
132
133  #[ doc( inline ) ]
134  pub use prelude::*;
135}
136
137/// Prelude to use essentials: `use my_module::prelude::*`.
138#[ allow( unused_imports ) ]
139pub mod prelude
140{
141  use super::*;
142}