1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
//!
//! Determine kind of a container.
//!
/// Define a private namespace for all its items.
mod private
{
use crate :: *;
// use crate ::type_rightmost;
///
/// Kind of container.
///
#[ derive( Debug, PartialEq, Eq, Copy, Clone ) ]
pub enum ContainerKind
{
/// Not a container.
No,
/// Vector-like.
Vector,
/// Hash map-like.
HashMap,
/// Hash set-like.
HashSet,
}
/// Return kind of container specified by type.
///
/// Good to verify `alloc ::vec ::Vec< i32 >` is vector.
/// Good to verify `std ::collections ::HashMap< i32, i32 >` is hash map.
///
/// ### Basic use-case.
/// ```
/// use macro_tools ::exposed :: *;
///
/// let code = qt!( std ::collections ::HashMap< i32, i32 > );
/// let tree_type = syn ::parse2 :: < syn ::Type >( code ).unwrap();
/// let kind = container_kind ::of_type( &tree_type );
/// assert_eq!( kind, container_kind ::ContainerKind ::HashMap );
/// ```
/// # Panics
/// qqq: doc
#[ must_use ]
pub fn of_type(ty: &syn ::Type) -> ContainerKind
{
if let syn ::Type ::Path(path) = ty
{
let last = &path.path.segments.last();
if last.is_none()
{
return ContainerKind ::No;
}
match last.unwrap().ident.to_string().as_ref()
{
"Vec" => return ContainerKind ::Vector,
"HashMap" => return ContainerKind ::HashMap,
"HashSet" => return ContainerKind ::HashSet,
_ => return ContainerKind ::No,
}
}
ContainerKind ::No
}
/// Return kind of container specified by type. Unlike [`of_type`] it also understand optional types.
///
/// Good to verify `Option< alloc ::vec ::Vec< i32 > >` is optional vector.
///
/// ### Basic use-case.
/// ```
/// use macro_tools ::exposed :: *;
///
/// let code = qt!( Option< std ::collections ::HashMap< i32, i32 > > );
/// let tree_type = syn ::parse2 :: < syn ::Type >( code ).unwrap();
/// let ( kind, optional ) = container_kind ::of_optional( &tree_type );
/// assert_eq!( kind, container_kind ::ContainerKind ::HashMap );
/// assert_eq!( optional, true );
/// ```
/// # Panics
/// qqq: doc
#[ must_use ]
pub fn of_optional(ty: &syn ::Type) -> (ContainerKind, bool)
{
if typ ::type_rightmost(ty) == Some("Option".to_string())
{
let ty2 = typ ::type_parameters(ty, 0..=0).first().copied();
// inspect_type ::inspect_type_of!( ty2 );
if ty2.is_none()
{
return (ContainerKind ::No, false);
}
let ty2 = ty2.unwrap();
return (of_type(ty2), true);
}
(of_type(ty), false)
}
}
#[ doc( inline ) ]
#[ allow( unused_imports ) ]
pub use own :: *;
/// Own namespace of the module.
#[ allow( unused_imports ) ]
pub mod own
{
use super :: *;
#[ doc( inline ) ]
pub use orphan :: *;
#[ doc( inline ) ]
pub use private :: { ContainerKind, of_type, of_optional };
}
/// Orphan namespace of the module.
#[ allow( unused_imports ) ]
pub mod orphan
{
use super :: *;
#[ doc( inline ) ]
pub use exposed :: *;
}
/// Exposed namespace of the module.
#[ allow( unused_imports ) ]
pub mod exposed
{
use super :: *;
pub use super ::super ::container_kind;
// pub use super ::own as container_kind;
#[ doc( inline ) ]
pub use prelude :: *;
}
/// Prelude to use essentials: `use my_module ::prelude :: *`.
#[ allow( unused_imports ) ]
pub mod prelude
{
use super :: *;
}