Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ jobs:

- name: trybuild test
if: matrix.version == 'stable'
run: cargo test -p phf_macros_tests -- --ignored
run: cargo test -p phf_macros_test -- --ignored

- name: no_std build check
working-directory: phf
Expand Down
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ members = [
"phf_codegen/test",
"phf_generator",
"phf_macros",
"phf_macros_tests",
"phf_macros_test",
"phf_shared"
]

Expand Down
44 changes: 44 additions & 0 deletions phf_codegen/test/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,5 +130,49 @@ fn main() -> io::Result<()> {
.into_iter()
.collect::<phf_codegen::Map<_>>()
.build()
)?;

// Test tuple keys for Map
writeln!(
&mut file,
"static TUPLE_MAP: ::phf::Map<(u32, &'static str), &'static str> = \n{};",
phf_codegen::Map::new()
.entry((1u32, "a"), "\"first\"")
.entry((2u32, "b"), "\"second\"")
.entry((3u32, "c"), "\"third\"")
.build()
)?;

// Test tuple keys for Set
writeln!(
&mut file,
"static TUPLE_SET: ::phf::Set<(u32, &'static str)> = \n{};",
phf_codegen::Set::new()
.entry((1u32, "x"))
.entry((2u32, "y"))
.entry((3u32, "z"))
.build()
)?;

// Test nested tuple keys for Map
writeln!(
&mut file,
"static NESTED_TUPLE_MAP: ::phf::Map<((u32, u32), &'static str), u32> = \n{};",
phf_codegen::Map::new()
.entry(((1u32, 2u32), "nested"), "10")
.entry(((3u32, 4u32), "tuple"), "20")
.entry(((5u32, 6u32), "keys"), "30")
.build()
)?;

// Test mixed type tuple keys
writeln!(
&mut file,
"static MIXED_TUPLE_MAP: ::phf::Map<(bool, u8, &'static str), &'static str> = \n{};",
phf_codegen::Map::new()
.entry((true, 1u8, "test"), "\"value1\"")
.entry((false, 2u8, "demo"), "\"value2\"")
.entry((true, 3u8, "example"), "\"value3\"")
.build()
)
}
36 changes: 36 additions & 0 deletions phf_codegen/test/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -125,4 +125,40 @@ mod test {
assert_eq!(3, FROM_ITER_MAP["three"]);
assert!(!FROM_ITER_MAP.contains_key("four"));
}

#[test]
fn tuple_map() {
assert_eq!("first", TUPLE_MAP[&(1u32, "a")]);
assert_eq!("second", TUPLE_MAP[&(2u32, "b")]);
assert_eq!("third", TUPLE_MAP[&(3u32, "c")]);
assert!(!TUPLE_MAP.contains_key(&(4u32, "d")));
assert!(!TUPLE_MAP.contains_key(&(1u32, "b")));
}

#[test]
fn tuple_set() {
assert!(TUPLE_SET.contains(&(1u32, "x")));
assert!(TUPLE_SET.contains(&(2u32, "y")));
assert!(TUPLE_SET.contains(&(3u32, "z")));
assert!(!TUPLE_SET.contains(&(4u32, "w")));
assert!(!TUPLE_SET.contains(&(1u32, "y")));
}

#[test]
fn nested_tuple_map() {
assert_eq!(10, NESTED_TUPLE_MAP[&((1u32, 2u32), "nested")]);
assert_eq!(20, NESTED_TUPLE_MAP[&((3u32, 4u32), "tuple")]);
assert_eq!(30, NESTED_TUPLE_MAP[&((5u32, 6u32), "keys")]);
assert!(!NESTED_TUPLE_MAP.contains_key(&((7u32, 8u32), "missing")));
assert!(!NESTED_TUPLE_MAP.contains_key(&((1u32, 2u32), "wrong")));
}

#[test]
fn mixed_tuple_map() {
assert_eq!("value1", MIXED_TUPLE_MAP[&(true, 1u8, "test")]);
assert_eq!("value2", MIXED_TUPLE_MAP[&(false, 2u8, "demo")]);
assert_eq!("value3", MIXED_TUPLE_MAP[&(true, 3u8, "example")]);
assert!(!MIXED_TUPLE_MAP.contains_key(&(false, 1u8, "test")));
assert!(!MIXED_TUPLE_MAP.contains_key(&(true, 4u8, "missing")));
}
}
25 changes: 25 additions & 0 deletions phf_macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ enum ParsedKey {
U128(u128),
Usize(usize),
Bool(bool),
Tuple(Vec<ParsedKey>),
#[cfg(feature = "unicase")]
UniCase(UniCase<String>),
#[cfg(feature = "unicase")]
Expand Down Expand Up @@ -65,6 +66,11 @@ impl PhfHash for ParsedKey {
ParsedKey::U128(s) => s.phf_hash(state),
ParsedKey::Usize(s) => s.phf_hash(state),
ParsedKey::Bool(s) => s.phf_hash(state),
ParsedKey::Tuple(elements) => {
for element in elements {
element.phf_hash(state);
}
}
#[cfg(feature = "unicase")]
ParsedKey::UniCase(s) => s.phf_hash(state),
#[cfg(feature = "unicase")]
Expand Down Expand Up @@ -99,6 +105,14 @@ impl ParsedKey {
"u64" => Some(ParsedKey::U64(s.base10_parse::<u64>().unwrap())),
"u128" => Some(ParsedKey::U128(s.base10_parse::<u128>().unwrap())),
"usize" => Some(ParsedKey::Usize(s.base10_parse::<usize>().unwrap())),
// Handle unsuffixed integer literals, default to i32
"" => {
if let Ok(val) = s.base10_parse::<i32>() {
Some(ParsedKey::I32(val))
} else {
None
}
}
_ => None,
},
Lit::Bool(s) => Some(ParsedKey::Bool(s.value)),
Expand Down Expand Up @@ -161,6 +175,17 @@ impl ParsedKey {
_ => None,
}
}
Expr::Tuple(tuple) => {
let mut elements = Vec::new();
for elem in &tuple.elems {
if let Some(parsed_elem) = ParsedKey::from_expr(elem) {
elements.push(parsed_elem);
} else {
return None;
}
}
Some(ParsedKey::Tuple(elements))
}
Expr::Group(group) => ParsedKey::from_expr(&group.expr),
Expr::Call(call) if call.args.len() == 1 => {
let last;
Expand Down
2 changes: 1 addition & 1 deletion phf_macros_tests/Cargo.toml → phf_macros_test/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[package]
name = "phf_macros_tests"
name = "phf_macros_test"
version = "0.1.0"
authors = ["Yuki Okushi"]
edition = "2021"
Expand Down
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,11 @@ error[E0277]: the trait bound `UniCase<&str>: phf_shared::PhfBorrow<_>` is not s
`&[u8; N]` implements `phf_shared::PhfBorrow<[u8; N]>`
`&[u8]` implements `phf_shared::PhfBorrow<[u8]>`
`&str` implements `phf_shared::PhfBorrow<str>`
`String` implements `phf_shared::PhfBorrow<str>`
`Vec<u8>` implements `phf_shared::PhfBorrow<[u8]>`
`[bool; N]` implements `phf_shared::PhfBorrow<[bool]>`
`[char; N]` implements `phf_shared::PhfBorrow<[char]>`
`[i128; N]` implements `phf_shared::PhfBorrow<[i128]>`
`(A, B)` implements `phf_shared::PhfBorrow<(A, B)>`
`(A, B, C)` implements `phf_shared::PhfBorrow<(A, B, C)>`
`(A, B, C, D)` implements `phf_shared::PhfBorrow<(A, B, C, D)>`
`(A, B, C, D, E)` implements `phf_shared::PhfBorrow<(A, B, C, D, E)>`
`(A, B, C, D, E, F)` implements `phf_shared::PhfBorrow<(A, B, C, D, E, F)>`
and $N others
note: required by a bound in `phf::Map::<K, V>::get`
--> $WORKSPACE/phf/src/map.rs
Expand Down
52 changes: 52 additions & 0 deletions phf_macros_tests/tests/test.rs → phf_macros_test/tests/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,19 @@ mod map {
#[cfg(not(feature = "enabled_feature"))]
assert_eq!(None, MY_MAP.get("baz"));
}

#[test]
fn test_tuples() {
static MAP: phf::Map<(u32, &str), u32> = phf_map! {
(0, "a") => 1,
(1, "b") => 2,
(2, "c") => 3,
};
assert_eq!(Some(&1), MAP.get(&(0, "a")));
assert_eq!(Some(&2), MAP.get(&(1, "b")));
assert_eq!(Some(&3), MAP.get(&(2, "c")));
assert_eq!(None, MAP.get(&(3, "d")));
}
}

mod set {
Expand Down Expand Up @@ -408,6 +421,19 @@ mod set {
#[cfg(not(feature = "enabled_feature"))]
assert!(!SET.contains("baz"));
}

#[test]
fn test_tuples() {
static SET: phf::Set<(u32, &str)> = phf_set! {
(0, "a"),
(1, "b"),
(2, "c"),
};
assert!(SET.contains(&(0, "a")));
assert!(SET.contains(&(1, "b")));
assert!(SET.contains(&(2, "c")));
assert!(!SET.contains(&(3, "d")));
}
}

mod ordered_map {
Expand Down Expand Up @@ -551,6 +577,19 @@ mod ordered_map {
#[cfg(not(feature = "enabled_feature"))]
assert_eq!(None, MY_MAP.get("baz"));
}

#[test]
fn test_tuples() {
static MAP: phf::OrderedMap<(u32, &str), u32> = phf_ordered_map! {
(0, "a") => 1,
(1, "b") => 2,
(2, "c") => 3,
};
assert_eq!(Some(&1), MAP.get(&(0, "a")));
assert_eq!(Some(&2), MAP.get(&(1, "b")));
assert_eq!(Some(&3), MAP.get(&(2, "c")));
assert_eq!(None, MAP.get(&(3, "d")));
}
}

mod ordered_set {
Expand Down Expand Up @@ -652,4 +691,17 @@ mod ordered_set {
#[cfg(not(feature = "enabled_feature"))]
assert!(!SET.contains("baz"));
}

#[test]
fn test_tuples() {
static SET: phf::OrderedSet<(u32, &str)> = phf_ordered_set! {
(0, "a"),
(1, "b"),
(2, "c"),
};
assert!(SET.contains(&(0, "a")));
assert!(SET.contains(&(1, "b")));
assert!(SET.contains(&(2, "c")));
assert!(!SET.contains(&(3, "d")));
}
}
File renamed without changes.
49 changes: 49 additions & 0 deletions phf_shared/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -473,3 +473,52 @@ slice_impl!(u128);
slice_impl!(i128);
slice_impl!(bool);
slice_impl!(char);

macro_rules! tuple_impl {
($($t:ident),+) => {
impl<$($t: PhfHash),+> PhfHash for ($($t,)+) {
fn phf_hash<HS: Hasher>(&self, state: &mut HS) {
#[allow(non_snake_case)]
let ($($t,)+) = self;
$(
$t.phf_hash(state);
)+
}
}

impl<$($t: PhfHash),+> PhfBorrow<($($t,)+)> for ($($t,)+) {
fn borrow(&self) -> &($($t,)+) {
self
}
}

impl<$($t: FmtConst),+> FmtConst for ($($t,)+) {
fn fmt_const(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
#[allow(non_snake_case)]
let ($($t,)+) = self;
write!(f, "(")?;
let mut first = true;
$(
if !core::mem::replace(&mut first, false) {
write!(f, ", ")?;
}
$t.fmt_const(f)?;
)+
write!(f, ")")
}
}
};
}

tuple_impl!(A);
tuple_impl!(A, B);
tuple_impl!(A, B, C);
tuple_impl!(A, B, C, D);
tuple_impl!(A, B, C, D, E);
tuple_impl!(A, B, C, D, E, F);
tuple_impl!(A, B, C, D, E, F, G);
tuple_impl!(A, B, C, D, E, F, G, HT);
tuple_impl!(A, B, C, D, E, F, G, HT, I);
tuple_impl!(A, B, C, D, E, F, G, HT, I, J);
tuple_impl!(A, B, C, D, E, F, G, HT, I, J, K);
tuple_impl!(A, B, C, D, E, F, G, HT, I, J, K, L);
Loading