|  | #![warn(missing_docs)] | 
|  | #![warn(unused_results)] | 
|  | #![doc(html_root_url="https://docs.rs/maplit/1/")] | 
|  |  | 
|  | //! Macros for container literals with specific type. | 
|  | //! | 
|  | //! ``` | 
|  | //! #[macro_use] extern crate maplit; | 
|  | //! | 
|  | //! # fn main() { | 
|  | //! let map = hashmap!{ | 
|  | //!     "a" => 1, | 
|  | //!     "b" => 2, | 
|  | //! }; | 
|  | //! # } | 
|  | //! ``` | 
|  | //! | 
|  | //! The **maplit** crate uses `=>` syntax to separate the key and value for the | 
|  | //! mapping macros. (It was not possible to use `:` as separator due to syntactic | 
|  | //! restrictions in regular `macro_rules!` macros.) | 
|  | //! | 
|  | //! Note that rust macros are flexible in which brackets you use for the invocation. | 
|  | //! You can use them as `hashmap!{}` or `hashmap![]` or `hashmap!()`. | 
|  | //! | 
|  | //! Generic container macros already exist elsewhere, so those are not provided | 
|  | //! here at the moment. | 
|  |  | 
|  | #[macro_export(local_inner_macros)] | 
|  | /// Create a **HashMap** from a list of key-value pairs | 
|  | /// | 
|  | /// ## Example | 
|  | /// | 
|  | /// ``` | 
|  | /// #[macro_use] extern crate maplit; | 
|  | /// # fn main() { | 
|  | /// | 
|  | /// let map = hashmap!{ | 
|  | ///     "a" => 1, | 
|  | ///     "b" => 2, | 
|  | /// }; | 
|  | /// assert_eq!(map["a"], 1); | 
|  | /// assert_eq!(map["b"], 2); | 
|  | /// assert_eq!(map.get("c"), None); | 
|  | /// # } | 
|  | /// ``` | 
|  | macro_rules! hashmap { | 
|  | (@single $($x:tt)*) => (()); | 
|  | (@count $($rest:expr),*) => (<[()]>::len(&[$(hashmap!(@single $rest)),*])); | 
|  |  | 
|  | ($($key:expr => $value:expr,)+) => { hashmap!($($key => $value),+) }; | 
|  | ($($key:expr => $value:expr),*) => { | 
|  | { | 
|  | let _cap = hashmap!(@count $($key),*); | 
|  | let mut _map = ::std::collections::HashMap::with_capacity(_cap); | 
|  | $( | 
|  | let _ = _map.insert($key, $value); | 
|  | )* | 
|  | _map | 
|  | } | 
|  | }; | 
|  | } | 
|  |  | 
|  | /// Create a **HashSet** from a list of elements. | 
|  | /// | 
|  | /// ## Example | 
|  | /// | 
|  | /// ``` | 
|  | /// #[macro_use] extern crate maplit; | 
|  | /// # fn main() { | 
|  | /// | 
|  | /// let set = hashset!{"a", "b"}; | 
|  | /// assert!(set.contains("a")); | 
|  | /// assert!(set.contains("b")); | 
|  | /// assert!(!set.contains("c")); | 
|  | /// # } | 
|  | /// ``` | 
|  | #[macro_export(local_inner_macros)] | 
|  | macro_rules! hashset { | 
|  | (@single $($x:tt)*) => (()); | 
|  | (@count $($rest:expr),*) => (<[()]>::len(&[$(hashset!(@single $rest)),*])); | 
|  |  | 
|  | ($($key:expr,)+) => { hashset!($($key),+) }; | 
|  | ($($key:expr),*) => { | 
|  | { | 
|  | let _cap = hashset!(@count $($key),*); | 
|  | let mut _set = ::std::collections::HashSet::with_capacity(_cap); | 
|  | $( | 
|  | let _ = _set.insert($key); | 
|  | )* | 
|  | _set | 
|  | } | 
|  | }; | 
|  | } | 
|  |  | 
|  | #[macro_export(local_inner_macros)] | 
|  | /// Create a **BTreeMap** from a list of key-value pairs | 
|  | /// | 
|  | /// ## Example | 
|  | /// | 
|  | /// ``` | 
|  | /// #[macro_use] extern crate maplit; | 
|  | /// # fn main() { | 
|  | /// | 
|  | /// let map = btreemap!{ | 
|  | ///     "a" => 1, | 
|  | ///     "b" => 2, | 
|  | /// }; | 
|  | /// assert_eq!(map["a"], 1); | 
|  | /// assert_eq!(map["b"], 2); | 
|  | /// assert_eq!(map.get("c"), None); | 
|  | /// # } | 
|  | /// ``` | 
|  | macro_rules! btreemap { | 
|  | // trailing comma case | 
|  | ($($key:expr => $value:expr,)+) => (btreemap!($($key => $value),+)); | 
|  |  | 
|  | ( $($key:expr => $value:expr),* ) => { | 
|  | { | 
|  | let mut _map = ::std::collections::BTreeMap::new(); | 
|  | $( | 
|  | let _ = _map.insert($key, $value); | 
|  | )* | 
|  | _map | 
|  | } | 
|  | }; | 
|  | } | 
|  |  | 
|  | #[macro_export(local_inner_macros)] | 
|  | /// Create a **BTreeSet** from a list of elements. | 
|  | /// | 
|  | /// ## Example | 
|  | /// | 
|  | /// ``` | 
|  | /// #[macro_use] extern crate maplit; | 
|  | /// # fn main() { | 
|  | /// | 
|  | /// let set = btreeset!{"a", "b"}; | 
|  | /// assert!(set.contains("a")); | 
|  | /// assert!(set.contains("b")); | 
|  | /// assert!(!set.contains("c")); | 
|  | /// # } | 
|  | /// ``` | 
|  | macro_rules! btreeset { | 
|  | ($($key:expr,)+) => (btreeset!($($key),+)); | 
|  |  | 
|  | ( $($key:expr),* ) => { | 
|  | { | 
|  | let mut _set = ::std::collections::BTreeSet::new(); | 
|  | $( | 
|  | _set.insert($key); | 
|  | )* | 
|  | _set | 
|  | } | 
|  | }; | 
|  | } | 
|  |  | 
|  | /// Identity function. Used as the fallback for conversion. | 
|  | #[doc(hidden)] | 
|  | pub fn __id<T>(t: T) -> T { t } | 
|  |  | 
|  | /// Macro that converts the keys or key-value pairs passed to another maplit | 
|  | /// macro. The default conversion is to use the [`Into`] trait, if no | 
|  | /// custom conversion is passed. | 
|  | /// | 
|  | /// The syntax is: | 
|  | /// | 
|  | /// `convert_args!(` `keys=` *function* `,` `values=` *function* `,` | 
|  | ///     *macro_name* `!(` [ *key* => *value* [, *key* => *value* ... ] ] `))` | 
|  | /// | 
|  | /// Here *macro_name* is any other maplit macro and either or both of the | 
|  | /// explicit `keys=` and `values=` parameters can be omitted. | 
|  | /// | 
|  | /// [`Into`]: https://doc.rust-lang.org/std/convert/trait.Into.html | 
|  | /// | 
|  | /// **Note** To use `convert_args`, the macro that is being wrapped | 
|  | /// must itself be brought into the current scope with `#[macro_use]` or `use`. | 
|  | /// | 
|  | /// # Examples | 
|  | /// | 
|  | /// ``` | 
|  | /// #[macro_use] extern crate maplit; | 
|  | /// # fn main() { | 
|  | /// | 
|  | /// use std::collections::HashMap; | 
|  | /// use std::collections::BTreeSet; | 
|  | /// | 
|  | /// // a. Use the default conversion with the Into trait. | 
|  | /// // Here this converts both the key and value string literals to `String`, | 
|  | /// // but we need to specify the map type exactly! | 
|  | /// | 
|  | /// let map1: HashMap<String, String> = convert_args!(hashmap!( | 
|  | ///     "a" => "b", | 
|  | ///     "c" => "d", | 
|  | /// )); | 
|  | /// | 
|  | /// // b. Specify an explicit custom conversion for the keys. If we don't specify | 
|  | /// // a conversion for the values, they are not converted at all. | 
|  | /// | 
|  | /// let map2 = convert_args!(keys=String::from, hashmap!( | 
|  | ///     "a" => 1, | 
|  | ///     "c" => 2, | 
|  | /// )); | 
|  | /// | 
|  | /// // Note: map2 is a HashMap<String, i32>, but we didn't need to specify the type | 
|  | /// let _: HashMap<String, i32> = map2; | 
|  | /// | 
|  | /// // c. convert_args! works with all the maplit macros -- and macros from other | 
|  | /// // crates that have the same "signature". | 
|  | /// // For example, btreeset and conversion from &str to Vec<u8>. | 
|  | /// | 
|  | /// let set: BTreeSet<Vec<u8>> = convert_args!(btreeset!( | 
|  | ///     "a", "b", "c", "d", "a", "e", "f", | 
|  | /// )); | 
|  | /// assert_eq!(set.len(), 6); | 
|  | /// | 
|  | /// | 
|  | /// # } | 
|  | /// ``` | 
|  | #[macro_export(local_inner_macros)] | 
|  | macro_rules! convert_args { | 
|  | (keys=$kf:expr, $macro_name:ident !($($k:expr),* $(,)*)) => { | 
|  | $macro_name! { $(($kf)($k)),* } | 
|  | }; | 
|  | (keys=$kf:expr, values=$vf:expr, $macro_name:ident !($($k:expr),* $(,)*)) => { | 
|  | $macro_name! { $(($kf)($k)),* } | 
|  | }; | 
|  | (keys=$kf:expr, values=$vf:expr, $macro_name:ident !( $($k:expr => $v:expr),* $(,)*)) => { | 
|  | $macro_name! { $(($kf)($k) => ($vf)($v)),* } | 
|  | }; | 
|  | (keys=$kf:expr, $macro_name:ident !($($rest:tt)*)) => { | 
|  | convert_args! { | 
|  | keys=$kf, values=$crate::__id, | 
|  | $macro_name !( | 
|  | $($rest)* | 
|  | ) | 
|  | } | 
|  | }; | 
|  | (values=$vf:expr, $macro_name:ident !($($rest:tt)*)) => { | 
|  | convert_args! { | 
|  | keys=$crate::__id, values=$vf, | 
|  | $macro_name !( | 
|  | $($rest)* | 
|  | ) | 
|  | } | 
|  | }; | 
|  | ($macro_name:ident ! $($rest:tt)*) => { | 
|  | convert_args! { | 
|  | keys=::std::convert::Into::into, values=::std::convert::Into::into, | 
|  | $macro_name ! | 
|  | $($rest)* | 
|  | } | 
|  | }; | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn test_hashmap() { | 
|  | use std::collections::HashMap; | 
|  | use std::collections::HashSet; | 
|  | let names = hashmap!{ | 
|  | 1 => "one", | 
|  | 2 => "two", | 
|  | }; | 
|  | assert_eq!(names.len(), 2); | 
|  | assert_eq!(names[&1], "one"); | 
|  | assert_eq!(names[&2], "two"); | 
|  | assert_eq!(names.get(&3), None); | 
|  |  | 
|  | let empty: HashMap<i32, i32> = hashmap!{}; | 
|  | assert_eq!(empty.len(), 0); | 
|  |  | 
|  | let _nested_compiles = hashmap!{ | 
|  | 1 => hashmap!{0 => 1 + 2,}, | 
|  | 2 => hashmap!{1 => 1,}, | 
|  | }; | 
|  |  | 
|  | let _: HashMap<String, i32> = convert_args!(keys=String::from, hashmap!( | 
|  | "one" => 1, | 
|  | "two" => 2, | 
|  | )); | 
|  |  | 
|  | let _: HashMap<String, i32> = convert_args!(keys=String::from, values=__id, hashmap!( | 
|  | "one" => 1, | 
|  | "two" => 2, | 
|  | )); | 
|  |  | 
|  | let names: HashSet<String> = convert_args!(hashset!( | 
|  | "one", | 
|  | "two", | 
|  | )); | 
|  | assert!(names.contains("one")); | 
|  | assert!(names.contains("two")); | 
|  |  | 
|  | let lengths: HashSet<usize> = convert_args!(keys=str::len, hashset!( | 
|  | "one", | 
|  | "two", | 
|  | )); | 
|  | assert_eq!(lengths.len(), 1); | 
|  |  | 
|  | let _no_trailing: HashSet<usize> = convert_args!(keys=str::len, hashset!( | 
|  | "one", | 
|  | "two" | 
|  | )); | 
|  | } | 
|  |  | 
|  | #[test] | 
|  | fn test_btreemap() { | 
|  | use std::collections::BTreeMap; | 
|  | let names = btreemap!{ | 
|  | 1 => "one", | 
|  | 2 => "two", | 
|  | }; | 
|  | assert_eq!(names.len(), 2); | 
|  | assert_eq!(names[&1], "one"); | 
|  | assert_eq!(names[&2], "two"); | 
|  | assert_eq!(names.get(&3), None); | 
|  |  | 
|  | let empty: BTreeMap<i32, i32> = btreemap!{}; | 
|  | assert_eq!(empty.len(), 0); | 
|  |  | 
|  | let _nested_compiles = btreemap!{ | 
|  | 1 => btreemap!{0 => 1 + 2,}, | 
|  | 2 => btreemap!{1 => 1,}, | 
|  | }; | 
|  | } |