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
//!
//! Determine kind of a container.
//!
/// Internal namespace.
pub( crate ) 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 );
/// ```
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 );
/// ```
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 protected::*;
/// Protected namespace of the module.
pub mod protected
{
#[ doc( inline ) ]
#[ allow( unused_imports ) ]
pub use super::orphan::*;
#[ doc( inline ) ]
#[ allow( unused_imports ) ]
pub use super::private::
{
ContainerKind,
of_type,
of_optional,
};
}
/// Orphan namespace of the module.
pub mod orphan
{
#[ doc( inline ) ]
#[ allow( unused_imports ) ]
pub use super::exposed::*;
}
/// Exposed namespace of the module.
pub mod exposed
{
pub use super::protected as container_kind;
#[ doc( inline ) ]
#[ allow( unused_imports ) ]
pub use super::prelude::*;
}
/// Prelude to use essentials: `use my_module::prelude::*`.
pub mod prelude
{
}