summaryrefslogtreecommitdiffstats
path: root/third_party/rust/phf_macros
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/phf_macros')
-rw-r--r--third_party/rust/phf_macros/.cargo-checksum.json1
-rw-r--r--third_party/rust/phf_macros/Cargo.toml50
-rw-r--r--third_party/rust/phf_macros/benches/bench.rs130
-rw-r--r--third_party/rust/phf_macros/src/lib.rs242
-rw-r--r--third_party/rust/phf_macros/tests/compile-fail-unicase/equivalent-keys.rs9
-rw-r--r--third_party/rust/phf_macros/tests/compile-fail-unicase/equivalent-keys.stderr5
-rw-r--r--third_party/rust/phf_macros/tests/compile-fail/bad-syntax.rs9
-rw-r--r--third_party/rust/phf_macros/tests/compile-fail/bad-syntax.stderr5
-rw-r--r--third_party/rust/phf_macros/tests/compiletest.rs13
-rw-r--r--third_party/rust/phf_macros/tests/test.rs324
10 files changed, 788 insertions, 0 deletions
diff --git a/third_party/rust/phf_macros/.cargo-checksum.json b/third_party/rust/phf_macros/.cargo-checksum.json
new file mode 100644
index 0000000000..85de24adbd
--- /dev/null
+++ b/third_party/rust/phf_macros/.cargo-checksum.json
@@ -0,0 +1 @@
+{"files":{"Cargo.toml":"220232fa30135dd1d2a76ea65b1eab24323522587fe8bf6064a2af5cebc1aa29","benches/bench.rs":"0daf2e53f820b4280b69cb82f694594417f32be53ead32a407817c2feb0f4874","src/lib.rs":"32bc1404d19d3382d89844fceb1d809484e2626347700eb98ffef74dcadb9829","tests/compile-fail-unicase/equivalent-keys.rs":"7abd4e1fb7c1c0ef92fa5a113ae15066ef09bceee8a03bc78aca8ba8dfe9607a","tests/compile-fail-unicase/equivalent-keys.stderr":"c6dbda76b5e7c5e4c4eeca56f231167259f9bc43eb008fe0356db4ee2dae3978","tests/compile-fail/bad-syntax.rs":"14082c0da8cba00c2b9f985b4ef9dc6827f2641b5b0e7dc379eca2f2629109a6","tests/compile-fail/bad-syntax.stderr":"6aa0c2f2acff3225bd16cd0b0871be1be375e1cd6e1297cb01b2f7ec4cd94f7f","tests/compiletest.rs":"923f745b574953deb6e4c2640c95a8af342883eb6d77f9cdccbfed75bcc6adb7","tests/test.rs":"9ec53f46e525138d14ddeb3392f03f7955ab0c78cf276e2f0d0e1f13f7bc9e3c"},"package":"7f6fde18ff429ffc8fe78e2bf7f8b7a5a5a6e2a8b58bc5a9ac69198bbda9189c"} \ No newline at end of file
diff --git a/third_party/rust/phf_macros/Cargo.toml b/third_party/rust/phf_macros/Cargo.toml
new file mode 100644
index 0000000000..be82a1dc02
--- /dev/null
+++ b/third_party/rust/phf_macros/Cargo.toml
@@ -0,0 +1,50 @@
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# When uploading crates to the registry Cargo will automatically
+# "normalize" Cargo.toml files for maximal compatibility
+# with all versions of Cargo and also rewrite `path` dependencies
+# to registry (e.g., crates.io) dependencies
+#
+# If you believe there's an error in this file please file an
+# issue against the rust-lang/cargo repository. If you're
+# editing this file be aware that the upstream Cargo.toml
+# will likely look very different (and much more reasonable)
+
+[package]
+edition = "2018"
+name = "phf_macros"
+version = "0.8.0"
+authors = ["Steven Fackler <sfackler@gmail.com>"]
+description = "Macros to generate types in the phf crate"
+license = "MIT"
+repository = "https://github.com/sfackler/rust-phf"
+
+[lib]
+proc-macro = true
+[dependencies.phf_generator]
+version = "0.8.0"
+
+[dependencies.phf_shared]
+version = "0.8.0"
+
+[dependencies.proc-macro-hack]
+version = "0.5.4"
+
+[dependencies.proc-macro2]
+version = "1"
+
+[dependencies.quote]
+version = "1"
+
+[dependencies.syn]
+version = "1"
+features = ["full"]
+[dev-dependencies.phf]
+version = "0.8"
+features = ["macros", "unicase"]
+
+[dev-dependencies.trybuild]
+version = "1.0"
+
+[dev-dependencies.unicase]
+version = "2.4.0"
diff --git a/third_party/rust/phf_macros/benches/bench.rs b/third_party/rust/phf_macros/benches/bench.rs
new file mode 100644
index 0000000000..c0d66ef79d
--- /dev/null
+++ b/third_party/rust/phf_macros/benches/bench.rs
@@ -0,0 +1,130 @@
+#![feature(test)]
+
+extern crate test;
+
+mod map {
+ use std::collections::{BTreeMap, HashMap};
+ use test::Bencher;
+ use phf::phf_map;
+
+ macro_rules! map_and_match {
+ ($map:ident, $f:ident, $($key:expr => $value:expr,)+) => {
+ static $map: phf::Map<&'static str, usize> = phf_map! {
+ $($key => $value),+
+ };
+
+ fn $f(key: &str) -> Option<usize> {
+ match key {
+ $($key => Some($value),)+
+ _ => None
+ }
+ }
+ }
+ }
+
+ map_and_match! { MAP, match_get,
+ "apple" => 0,
+ "banana" => 1,
+ "carrot" => 2,
+ "doughnut" => 3,
+ "eggplant" => 4,
+ "frankincene" => 5,
+ "grapes" => 6,
+ "haggis" => 7,
+ "ice cream" => 8,
+ "jelly beans" => 9,
+ "kaffir lime leaves" => 10,
+ "lemonade" => 11,
+ "mashmallows" => 12,
+ "nectarines" => 13,
+ "oranges" => 14,
+ "pineapples" => 15,
+ "quinoa" => 16,
+ "rosemary" => 17,
+ "sourdough" => 18,
+ "tomatoes" => 19,
+ "unleavened bread" => 20,
+ "vanilla" => 21,
+ "watermelon" => 22,
+ "xinomavro grapes" => 23,
+ "yogurt" => 24,
+ "zucchini" => 25,
+ }
+
+ #[bench]
+ fn bench_match_some(b: &mut Bencher) {
+ b.iter(|| {
+ assert_eq!(match_get("zucchini").unwrap(), 25);
+ })
+ }
+
+ #[bench]
+ fn bench_match_none(b: &mut Bencher) {
+ b.iter(|| {
+ assert_eq!(match_get("potato"), None);
+ })
+ }
+
+ #[bench]
+ fn bench_btreemap_some(b: &mut Bencher) {
+ let mut map = BTreeMap::new();
+ for (key, value) in MAP.entries() {
+ map.insert(*key, *value);
+ }
+
+ b.iter(|| {
+ assert_eq!(map.get("zucchini").unwrap(), &25);
+ })
+ }
+
+ #[bench]
+ fn bench_hashmap_some(b: &mut Bencher) {
+ let mut map = HashMap::new();
+ for (key, value) in MAP.entries() {
+ map.insert(*key, *value);
+ }
+
+ b.iter(|| {
+ assert_eq!(map.get("zucchini").unwrap(), &25);
+ })
+ }
+
+ #[bench]
+ fn bench_phf_some(b: &mut Bencher) {
+ b.iter(|| {
+ assert_eq!(MAP.get("zucchini").unwrap(), &25);
+ })
+ }
+
+ #[bench]
+ fn bench_btreemap_none(b: &mut Bencher) {
+ let mut map = BTreeMap::new();
+ for (key, value) in MAP.entries() {
+ map.insert(*key, *value);
+ }
+
+ b.iter(|| {
+ assert_eq!(map.get("potato"), None);
+ })
+ }
+
+
+ #[bench]
+ fn bench_hashmap_none(b: &mut Bencher) {
+ let mut map = HashMap::new();
+ for (key, value) in MAP.entries() {
+ map.insert(*key, *value);
+ }
+
+ b.iter(|| {
+ assert_eq!(map.get("potato"), None);
+ })
+ }
+
+ #[bench]
+ fn bench_phf_none(b: &mut Bencher) {
+ b.iter(|| {
+ assert_eq!(MAP.get("potato"), None);
+ })
+ }
+}
diff --git a/third_party/rust/phf_macros/src/lib.rs b/third_party/rust/phf_macros/src/lib.rs
new file mode 100644
index 0000000000..b1e56ebfcb
--- /dev/null
+++ b/third_party/rust/phf_macros/src/lib.rs
@@ -0,0 +1,242 @@
+extern crate proc_macro;
+
+use phf_generator::HashState;
+use phf_shared::PhfHash;
+use proc_macro::TokenStream;
+use quote::quote;
+use std::collections::HashSet;
+use std::hash::Hasher;
+use syn::parse::{self, Parse, ParseStream};
+use syn::punctuated::Punctuated;
+use syn::{parse_macro_input, Error, Expr, Lit, Token, UnOp};
+
+#[derive(Hash, PartialEq, Eq, Clone)]
+enum ParsedKey {
+ Str(String),
+ Binary(Vec<u8>),
+ Char(char),
+ I8(i8),
+ I16(i16),
+ I32(i32),
+ I64(i64),
+ I128(i128),
+ U8(u8),
+ U16(u16),
+ U32(u32),
+ U64(u64),
+ U128(u128),
+ Bool(bool),
+}
+
+impl PhfHash for ParsedKey {
+ fn phf_hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ match self {
+ ParsedKey::Str(s) => s.phf_hash(state),
+ ParsedKey::Binary(s) => s.phf_hash(state),
+ ParsedKey::Char(s) => s.phf_hash(state),
+ ParsedKey::I8(s) => s.phf_hash(state),
+ ParsedKey::I16(s) => s.phf_hash(state),
+ ParsedKey::I32(s) => s.phf_hash(state),
+ ParsedKey::I64(s) => s.phf_hash(state),
+ ParsedKey::I128(s) => s.phf_hash(state),
+ ParsedKey::U8(s) => s.phf_hash(state),
+ ParsedKey::U16(s) => s.phf_hash(state),
+ ParsedKey::U32(s) => s.phf_hash(state),
+ ParsedKey::U64(s) => s.phf_hash(state),
+ ParsedKey::U128(s) => s.phf_hash(state),
+ ParsedKey::Bool(s) => s.phf_hash(state),
+ }
+ }
+}
+
+impl ParsedKey {
+ fn from_expr(expr: &Expr) -> Option<ParsedKey> {
+ match expr {
+ Expr::Lit(lit) => match &lit.lit {
+ Lit::Str(s) => Some(ParsedKey::Str(s.value())),
+ Lit::ByteStr(s) => Some(ParsedKey::Binary(s.value())),
+ Lit::Byte(s) => Some(ParsedKey::U8(s.value())),
+ Lit::Char(s) => Some(ParsedKey::Char(s.value())),
+ Lit::Int(s) => match s.suffix() {
+ // we've lost the sign at this point, so `-128i8` looks like `128i8`,
+ // which doesn't fit in an `i8`; parse it as a `u8` and cast (to `0i8`),
+ // which is handled below, by `Unary`
+ "i8" => Some(ParsedKey::I8(s.base10_parse::<u8>().unwrap() as i8)),
+ "i16" => Some(ParsedKey::I16(s.base10_parse::<u16>().unwrap() as i16)),
+ "i32" => Some(ParsedKey::I32(s.base10_parse::<u32>().unwrap() as i32)),
+ "i64" => Some(ParsedKey::I64(s.base10_parse::<u64>().unwrap() as i64)),
+ "i128" => Some(ParsedKey::I128(s.base10_parse::<u128>().unwrap() as i128)),
+ "u8" => Some(ParsedKey::U8(s.base10_parse::<u8>().unwrap())),
+ "u16" => Some(ParsedKey::U16(s.base10_parse::<u16>().unwrap())),
+ "u32" => Some(ParsedKey::U32(s.base10_parse::<u32>().unwrap())),
+ "u64" => Some(ParsedKey::U64(s.base10_parse::<u64>().unwrap())),
+ "u128" => Some(ParsedKey::U128(s.base10_parse::<u128>().unwrap())),
+ _ => None,
+ },
+ Lit::Bool(s) => Some(ParsedKey::Bool(s.value)),
+ _ => None,
+ },
+ Expr::Array(array) => {
+ let mut buf = vec![];
+ for expr in &array.elems {
+ match expr {
+ Expr::Lit(lit) => match &lit.lit {
+ Lit::Int(s) => match s.suffix() {
+ "u8" | "" => buf.push(s.base10_parse::<u8>().unwrap()),
+ _ => return None,
+ },
+ _ => return None,
+ },
+ _ => return None,
+ }
+ }
+ Some(ParsedKey::Binary(buf))
+ }
+ Expr::Unary(unary) => {
+ // if we received an integer literal (always unsigned) greater than i__::max_value()
+ // then casting it to a signed integer type of the same width will negate it to
+ // the same absolute value so we don't need to negate it here
+ macro_rules! try_negate (
+ ($val:expr) => {if $val < 0 { $val } else { -$val }}
+ );
+
+ match unary.op {
+ UnOp::Neg(_) => match ParsedKey::from_expr(&unary.expr)? {
+ ParsedKey::I8(v) => Some(ParsedKey::I8(try_negate!(v))),
+ ParsedKey::I16(v) => Some(ParsedKey::I16(try_negate!(v))),
+ ParsedKey::I32(v) => Some(ParsedKey::I32(try_negate!(v))),
+ ParsedKey::I64(v) => Some(ParsedKey::I64(try_negate!(v))),
+ ParsedKey::I128(v) => Some(ParsedKey::I128(try_negate!(v))),
+ _ => None,
+ },
+ _ => None,
+ }
+ }
+ Expr::Group(group) => ParsedKey::from_expr(&group.expr),
+ _ => None,
+ }
+ }
+}
+
+struct Key {
+ parsed: ParsedKey,
+ expr: Expr,
+}
+
+impl PhfHash for Key {
+ fn phf_hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.parsed.phf_hash(state)
+ }
+}
+
+impl Parse for Key {
+ fn parse(input: ParseStream) -> parse::Result<Key> {
+ let expr = input.parse()?;
+ let parsed = ParsedKey::from_expr(&expr)
+ .ok_or_else(|| Error::new_spanned(&expr, "unsupported key expression"))?;
+
+ Ok(Key { parsed, expr })
+ }
+}
+
+struct Entry {
+ key: Key,
+ value: Expr,
+}
+
+impl PhfHash for Entry {
+ fn phf_hash<H>(&self, state: &mut H)
+ where
+ H: Hasher,
+ {
+ self.key.phf_hash(state)
+ }
+}
+
+impl Parse for Entry {
+ fn parse(input: ParseStream) -> parse::Result<Entry> {
+ let key = input.parse()?;
+ input.parse::<Token![=>]>()?;
+ let value = input.parse()?;
+ Ok(Entry { key, value })
+ }
+}
+
+struct Map(Vec<Entry>);
+
+impl Parse for Map {
+ fn parse(input: ParseStream) -> parse::Result<Map> {
+ let parsed = Punctuated::<Entry, Token![,]>::parse_terminated(input)?;
+ let map = parsed.into_iter().collect::<Vec<_>>();
+ check_duplicates(&map)?;
+ Ok(Map(map))
+ }
+}
+
+struct Set(Vec<Entry>);
+
+impl Parse for Set {
+ fn parse(input: ParseStream) -> parse::Result<Set> {
+ let parsed = Punctuated::<Key, Token![,]>::parse_terminated(input)?;
+ let set = parsed
+ .into_iter()
+ .map(|key| Entry {
+ key,
+ value: syn::parse_str("()").unwrap(),
+ })
+ .collect::<Vec<_>>();
+ check_duplicates(&set)?;
+ Ok(Set(set))
+ }
+}
+
+fn check_duplicates(entries: &[Entry]) -> parse::Result<()> {
+ let mut keys = HashSet::new();
+ for entry in entries {
+ if !keys.insert(&entry.key.parsed) {
+ return Err(Error::new_spanned(&entry.key.expr, "duplicate key"));
+ }
+ }
+ Ok(())
+}
+
+fn build_map(entries: &[Entry], state: HashState) -> proc_macro2::TokenStream {
+ let key = state.key;
+ let disps = state.disps.iter().map(|&(d1, d2)| quote!((#d1, #d2)));
+ let entries = state.map.iter().map(|&idx| {
+ let key = &entries[idx].key.expr;
+ let value = &entries[idx].value;
+ quote!((#key, #value))
+ });
+
+ quote! {
+ phf::Map {
+ key: #key,
+ disps: phf::Slice::Static(&[#(#disps),*]),
+ entries: phf::Slice::Static(&[#(#entries),*]),
+ }
+ }
+}
+
+#[::proc_macro_hack::proc_macro_hack]
+pub fn phf_map(input: TokenStream) -> TokenStream {
+ let map = parse_macro_input!(input as Map);
+ let state = phf_generator::generate_hash(&map.0);
+
+ build_map(&map.0, state).into()
+}
+
+#[::proc_macro_hack::proc_macro_hack]
+pub fn phf_set(input: TokenStream) -> TokenStream {
+ let set = parse_macro_input!(input as Set);
+ let state = phf_generator::generate_hash(&set.0);
+
+ let map = build_map(&set.0, state);
+ quote!(phf::Set { map: #map }).into()
+}
diff --git a/third_party/rust/phf_macros/tests/compile-fail-unicase/equivalent-keys.rs b/third_party/rust/phf_macros/tests/compile-fail-unicase/equivalent-keys.rs
new file mode 100644
index 0000000000..45291354cc
--- /dev/null
+++ b/third_party/rust/phf_macros/tests/compile-fail-unicase/equivalent-keys.rs
@@ -0,0 +1,9 @@
+use unicase::UniCase;
+use phf::phf_map;
+
+static MAP: phf::Map<UniCase<&'static str>, isize> = phf_map!( //~ ERROR duplicate key UniCase("FOO")
+ UniCase("FOO") => 42, //~ NOTE one occurrence here
+ UniCase("foo") => 42, //~ NOTE one occurrence here
+);
+
+fn main() {}
diff --git a/third_party/rust/phf_macros/tests/compile-fail-unicase/equivalent-keys.stderr b/third_party/rust/phf_macros/tests/compile-fail-unicase/equivalent-keys.stderr
new file mode 100644
index 0000000000..b0e1d1012f
--- /dev/null
+++ b/third_party/rust/phf_macros/tests/compile-fail-unicase/equivalent-keys.stderr
@@ -0,0 +1,5 @@
+error: unsupported key expression
+ --> $DIR/equivalent-keys.rs:5:5
+ |
+5 | UniCase("FOO") => 42, //~ NOTE one occurrence here
+ | ^^^^^^^^^^^^^^
diff --git a/third_party/rust/phf_macros/tests/compile-fail/bad-syntax.rs b/third_party/rust/phf_macros/tests/compile-fail/bad-syntax.rs
new file mode 100644
index 0000000000..a766be4283
--- /dev/null
+++ b/third_party/rust/phf_macros/tests/compile-fail/bad-syntax.rs
@@ -0,0 +1,9 @@
+use phf::phf_map;
+
+static MAP: phf::Map<u32, u32> = phf_map! {
+ Signature::
+ => //~ ERROR expected identifier
+ ()
+};
+
+fn main() {}
diff --git a/third_party/rust/phf_macros/tests/compile-fail/bad-syntax.stderr b/third_party/rust/phf_macros/tests/compile-fail/bad-syntax.stderr
new file mode 100644
index 0000000000..bd387e6dcc
--- /dev/null
+++ b/third_party/rust/phf_macros/tests/compile-fail/bad-syntax.stderr
@@ -0,0 +1,5 @@
+error: expected identifier
+ --> $DIR/bad-syntax.rs:5:5
+ |
+5 | => //~ ERROR expected identifier
+ | ^^
diff --git a/third_party/rust/phf_macros/tests/compiletest.rs b/third_party/rust/phf_macros/tests/compiletest.rs
new file mode 100644
index 0000000000..c95f3c8073
--- /dev/null
+++ b/third_party/rust/phf_macros/tests/compiletest.rs
@@ -0,0 +1,13 @@
+#[test]
+#[ignore] // compiler error message format is different between 1.32.0 and nightly
+fn compile_test_unicase() {
+ let t = trybuild::TestCases::new();
+ t.compile_fail("tests/compile-fail-unicase/*.rs");
+}
+
+#[test]
+#[ignore]
+fn compile_fail() {
+ let t = trybuild::TestCases::new();
+ t.compile_fail("tests/compile-fail/*.rs");
+}
diff --git a/third_party/rust/phf_macros/tests/test.rs b/third_party/rust/phf_macros/tests/test.rs
new file mode 100644
index 0000000000..05caa41138
--- /dev/null
+++ b/third_party/rust/phf_macros/tests/test.rs
@@ -0,0 +1,324 @@
+mod map {
+ use std::collections::{HashMap, HashSet};
+ use phf::phf_map;
+
+ #[allow(dead_code)]
+ static TRAILING_COMMA: phf::Map<&'static str, isize> = phf_map!(
+ "foo" => 10,
+ );
+
+ #[allow(dead_code)]
+ static NO_TRAILING_COMMA: phf::Map<&'static str, isize> = phf_map!(
+ "foo" => 10
+ );
+
+ #[allow(dead_code)]
+ static BYTE_STRING_KEY: phf::Map<&'static [u8], &'static str> = phf_map!(
+ b"camembert" => "delicious",
+ );
+
+ #[test]
+ fn test_two() {
+ static MAP: phf::Map<&'static str, isize> = phf_map!(
+ "foo" => 10,
+ "bar" => 11,
+ );
+ assert!(Some(&10) == MAP.get(&("foo")));
+ assert!(Some(&11) == MAP.get(&("bar")));
+ assert_eq!(None, MAP.get(&("asdf")));
+ assert_eq!(2, MAP.len());
+ }
+
+ #[test]
+ fn test_entries() {
+ static MAP: phf::Map<&'static str, isize> = phf_map!(
+ "foo" => 10,
+ "bar" => 11,
+ );
+ let hash = MAP.entries().map(|(&k, &v)| (k, v)).collect::<HashMap<_, isize>>();
+ assert!(Some(&10) == hash.get(&("foo")));
+ assert!(Some(&11) == hash.get(&("bar")));
+ assert_eq!(2, hash.len());
+ }
+
+ #[test]
+ fn test_keys() {
+ static MAP: phf::Map<&'static str, isize> = phf_map!(
+ "foo" => 10,
+ "bar" => 11,
+ );
+ let hash = MAP.keys().map(|&e| e).collect::<HashSet<_>>();
+ assert!(hash.contains(&("foo")));
+ assert!(hash.contains(&("bar")));
+ assert_eq!(2, hash.len());
+ }
+
+ #[test]
+ fn test_values() {
+ static MAP: phf::Map<&'static str, isize> = phf_map!(
+ "foo" => 10,
+ "bar" => 11,
+ );
+ let hash = MAP.values().map(|&e| e).collect::<HashSet<isize>>();
+ assert!(hash.contains(&10));
+ assert!(hash.contains(&11));
+ assert_eq!(2, hash.len());
+ }
+
+ #[test]
+ fn test_large() {
+ static MAP: phf::Map<&'static str, isize> = phf_map!(
+ "a" => 0,
+ "b" => 1,
+ "c" => 2,
+ "d" => 3,
+ "e" => 4,
+ "f" => 5,
+ "g" => 6,
+ "h" => 7,
+ "i" => 8,
+ "j" => 9,
+ "k" => 10,
+ "l" => 11,
+ "m" => 12,
+ "n" => 13,
+ "o" => 14,
+ "p" => 15,
+ "q" => 16,
+ "r" => 17,
+ "s" => 18,
+ "t" => 19,
+ "u" => 20,
+ "v" => 21,
+ "w" => 22,
+ "x" => 23,
+ "y" => 24,
+ "z" => 25,
+ );
+ assert!(MAP.get(&("a")) == Some(&0));
+ }
+
+ #[test]
+ fn test_non_static_str_key() {
+ static MAP: phf::Map<&'static str, isize> = phf_map!(
+ "a" => 0,
+ );
+ assert_eq!(Some(&0), MAP.get(&*"a".to_string()));
+ }
+
+ #[test]
+ fn test_index_ok() {
+ static MAP: phf::Map<&'static str, isize> = phf_map!(
+ "a" => 0,
+ );
+ assert_eq!(0, MAP["a"]);
+ }
+
+ #[test]
+ #[should_panic]
+ fn test_index_fail() {
+ static MAP: phf::Map<&'static str, isize> = phf_map!(
+ "a" => 0,
+ );
+ MAP["b"];
+ }
+
+ macro_rules! test_key_type(
+ ($t:ty, $($k:expr => $v:expr),+) => ({
+ static MAP: phf::Map<$t, isize> = phf_map! {
+ $($k => $v),+
+ };
+ $(
+ assert_eq!(Some(&$v), MAP.get(&$k));
+ )+
+ })
+ );
+
+ #[test]
+ fn test_array_vals() {
+ static MAP: phf::Map<&'static str, [u8; 3]> = phf_map!(
+ "a" => [0u8, 1, 2],
+ );
+ assert_eq!(Some(&[0u8, 1, 2]), MAP.get(&("a")));
+ }
+
+ #[test]
+ fn test_array_keys() {
+ static MAP: phf::Map<[u8; 2], isize> = phf_map!(
+ [0u8, 1] => 0,
+ [2, 3u8] => 1,
+ [4, 5] => 2,
+ );
+ assert_eq!(Some(&0), MAP.get(&[0u8, 1u8]));
+ }
+
+ #[test]
+ fn test_byte_keys() {
+ test_key_type!(u8, b'a' => 0, b'b' => 1);
+ }
+
+ #[test]
+ fn test_char_keys() {
+ test_key_type!(char, 'a' => 0, 'b' => 1);
+ }
+
+ #[test]
+ fn test_i8_keys() {
+ test_key_type!(i8, 0i8 => 0, 1i8 => 1, 127i8 => 2, -128i8 => 3);
+ }
+
+ #[test]
+ fn test_i16_keys() {
+ test_key_type!(i16, 0i16 => 0, 1i16 => 1, 32767i16 => 2, -32768i16 => 3);
+ }
+
+ #[test]
+ fn test_i32_keys() {
+ test_key_type!(i32, 0i32 => 0, 1i32 => 1, 2147483647i32 => 2, -2147483648i32 => 3);
+ }
+
+ #[test]
+ fn test_i64_keys() {
+ test_key_type!(i64, 0i64 => 0, 1i64 => 1, -9223372036854775808i64 => 2);
+ }
+
+ #[test]
+ fn test_i128_keys() {
+ test_key_type!(
+ i128, 0i128 => 0, 1i128 => 1,
+ // `syn` handles literals larger than 64-bit differently
+ 170141183460469231731687303715884105727i128 => 2,
+ -170141183460469231731687303715884105727i128 => 3
+ );
+ }
+
+ #[test]
+ fn test_u8_keys() {
+ test_key_type!(u8, 0u8 => 0, 1u8 => 1, 255u8 => 2);
+ }
+
+ #[test]
+ fn test_u16_keys() {
+ test_key_type!(u16, 0u16 => 0, 1u16 => 1, 65535u16 => 2);
+ }
+
+ #[test]
+ fn test_u32_keys() {
+ test_key_type!(u32, 0u32 => 0, 1u32 => 1, 4294967295u32 => 2);
+ }
+
+ #[test]
+ fn test_u64_keys() {
+ test_key_type!(u64, 0u64 => 0, 1u64 => 1, 18446744073709551615u64 => 2);
+ }
+
+ #[test]
+ fn test_u128_keys() {
+ test_key_type!(
+ u128, 0u128 => 0, 1u128 => 1,
+ 340282366920938463463374607431768211455u128 => 2
+ );
+ }
+
+ #[test]
+ fn test_bool_keys() {
+ test_key_type!(bool, false => 0, true => 1);
+ }
+
+ #[test]
+ fn test_into_iterator() {
+ static MAP: phf::Map<&'static str, isize> = phf_map!(
+ "foo" => 10,
+ );
+
+ for (k, v) in &MAP {
+ assert_eq!(&"foo", k);
+ assert_eq!(&10, v)
+ }
+ }
+
+ #[cfg(feature = "unicase_support")]
+ #[test]
+ fn test_unicase() {
+ use unicase::UniCase;
+ static MAP: phf::Map<UniCase<&'static str>, isize> = phf_map!(
+ UniCase("FOO") => 10,
+ UniCase("Bar") => 11,
+ );
+ assert!(Some(&10) == MAP.get(&UniCase("FOo")));
+ assert!(Some(&11) == MAP.get(&UniCase("bar")));
+ assert_eq!(None, MAP.get(&UniCase("asdf")));
+ }
+
+ #[cfg(feature = "unicase_support")]
+ #[test]
+ fn test_unicase_alt() {
+ use unicase;
+ static MAP: phf::Map<unicase::UniCase<&'static str>, isize> = phf_map!(
+ unicase::UniCase("FOO") => 10,
+ unicase::UniCase("Bar") => 11,
+ );
+ assert!(Some(&10) == MAP.get(&unicase::UniCase("FOo")));
+ assert!(Some(&11) == MAP.get(&unicase::UniCase("bar")));
+ assert_eq!(None, MAP.get(&unicase::UniCase("asdf")));
+ }
+}
+
+mod set {
+ use std::collections::HashSet;
+ use phf::phf_set;
+
+ #[allow(dead_code)]
+ static TRAILING_COMMA: phf::Set<&'static str> = phf_set! {
+ "foo",
+ };
+
+ #[allow(dead_code)]
+ static NO_TRAILING_COMMA: phf::Set<&'static str> = phf_set! {
+ "foo"
+ };
+
+ #[test]
+ fn test_two() {
+ static SET: phf::Set<&'static str> = phf_set! {
+ "hello",
+ "world",
+ };
+ assert!(SET.contains(&"hello"));
+ assert!(SET.contains(&"world"));
+ assert!(!SET.contains(&"foo"));
+ assert_eq!(2, SET.len());
+ }
+
+ #[test]
+ fn test_iter() {
+ static SET: phf::Set<&'static str> = phf_set! {
+ "hello",
+ "world",
+ };
+ let set = SET.iter().map(|e| *e).collect::<HashSet<_>>();
+ assert!(set.contains(&"hello"));
+ assert!(set.contains(&"world"));
+ assert_eq!(2, set.len());
+ }
+
+ #[test]
+ fn test_non_static_str_contains() {
+ static SET: phf::Set<&'static str> = phf_set! {
+ "hello",
+ "world",
+ };
+ assert!(SET.contains(&*"hello".to_string()));
+ }
+
+ #[test]
+ fn test_into_iterator() {
+ static SET: phf::Set<&'static str> = phf_set! {
+ "hello",
+ };
+
+ for e in &SET {
+ assert_eq!(&"hello", e);
+ }
+ }
+}