/// Internal namespace. pub( crate ) mod private { use crate::exposed::*; use crate::type_rightmost; /// /// Kind of container. /// #[derive( Debug, PartialEq, 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. /// /// ### Sample /// ``` /// use proc_macro_tools::*; /// use quote::quote; /// /// let code = quote!( std::collections::HashMap< i32, i32 > ); /// let tree_type = syn::parse2::< syn::Type >( code ).unwrap(); /// let kind = type_container_kind( &tree_type ); /// assert_eq!( kind, ContainerKind::HashMap ); /// ``` pub fn type_container_kind( 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 [type_container_kind] it also understand optional types. /// /// Good to verify `Option< alloc::vec::Vec< i32 > >` is optional vector. /// /// ### Sample /// ``` /// use proc_macro_tools::*; /// use quote::quote; /// /// let code = quote!( Option< std::collections::HashMap< i32, i32 > > ); /// let tree_type = syn::parse2::< syn::Type >( code ).unwrap(); /// let ( kind, optional ) = type_optional_container_kind( &tree_type ); /// assert_eq!( kind, ContainerKind::HashMap ); /// assert_eq!( optional, true ); /// ``` pub fn type_optional_container_kind( ty : &syn::Type ) -> ( ContainerKind, bool ) { // use inspect_type::*; if type_rightmost( ty ) == Some( "Option".to_string() ) { let ty2 = type_parameters( ty, 0 ..= 0 ).first().map( | e | *e ); // inspect_type::inspect_type_of!( ty2 ); if ty2.is_none() { return ( ContainerKind::No, false ) } let ty2 = ty2.unwrap(); return ( type_container_kind( ty2 ), true ); } return ( type_container_kind( ty ), false ); } } /// Exposed namespace of the module. pub mod exposed { pub use super::prelude::*; // use super::private as i; pub use super::private::ContainerKind; pub use super::private::type_container_kind; pub use super::private::type_optional_container_kind; } pub use exposed::*; /// Prelude to use essentials: `use my_module::prelude::*`. pub mod prelude { // // use super::private as i; }