Skip to content

Commit

Permalink
Support UncasedStr in macros
Browse files Browse the repository at this point in the history
UncasedStr::new was made const in uncased 0.9.7 after const transmute
was stabilized in Rust 1.56.
  • Loading branch information
thaliaarchi committed Jun 27, 2023
1 parent 231f395 commit 0e72fa2
Show file tree
Hide file tree
Showing 14 changed files with 89 additions and 34 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
[workspace]
members = [
"phf",
"phf/examples/uncased-example",
"phf/examples/unicase-example",
"phf_codegen",
"phf_codegen/test",
Expand Down
11 changes: 11 additions & 0 deletions phf/examples/uncased-example/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[package]
name = "uncased-example"
version = "0.1.0"
edition = "2021"
rust-version = "1.60"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
phf = { path = "../..", features = ["macros", "uncased"] }
uncased = "0.9.9"
9 changes: 9 additions & 0 deletions phf/examples/uncased-example/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
use phf::phf_map;
use uncased::UncasedStr;

pub static MAP: phf::Map<&'static UncasedStr, isize> = phf_map!(
UncasedStr::new("Foo") => 0,
UncasedStr::new("Bar") => 1,
);

fn main() {}
1 change: 1 addition & 0 deletions phf/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ extern crate std as core;
/// - arrays of `u8` integers
/// - dereferenced byte string literals
/// - `UniCase::unicode(string)`, `UniCase::ascii(string)`, or `Ascii::new(string)` if the `unicase` feature is enabled
/// - `UncasedStr::new(string)` if the `uncased` feature is enabled
///
/// # Example
///
Expand Down
4 changes: 2 additions & 2 deletions phf_codegen/test/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ edition = "2021"

[dependencies]
phf = { version = "^0.11.2", features = ["uncased", "unicase"] }
uncased = { version = "0.9.6", default-features = false }
uncased = { version = "0.9.9", default-features = false }
unicase = "2.6.0"

[build-dependencies]
phf_codegen = { version = "^0.11.2", path = ".." }
uncased = { version = "0.9.6", default-features = false }
uncased = { version = "0.9.9", default-features = false }
unicase = "2.6.0"
2 changes: 2 additions & 0 deletions phf_macros/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,14 @@ categories = ["data-structures"]
proc-macro = true

[features]
uncased = ["uncased_", "phf_shared/uncased"]
unicase = ["unicase_", "phf_shared/unicase"]

[dependencies]
proc-macro2 = "1"
quote = "1"
syn = { version = "2", features = ["full"] }
uncased_ = { package = "uncased", version = "0.9.9", optional = true }
unicase_ = { package = "unicase", version = "2.6.0", optional = true }

phf_generator = "0.11.1"
Expand Down
48 changes: 24 additions & 24 deletions phf_macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ use std::hash::Hasher;
use syn::parse::{self, Parse, ParseStream};
use syn::punctuated::Punctuated;
use syn::{parse_macro_input, Error, Expr, ExprLit, Lit, Token, UnOp};
#[cfg(feature = "uncased")]
use uncased_::Uncased;
#[cfg(feature = "unicase")]
use unicase_::{Ascii, UniCase};

Expand All @@ -35,6 +37,8 @@ enum ParsedKey {
UniCase(UniCase<String>),
#[cfg(feature = "unicase")]
UniCaseAscii(Ascii<String>),
#[cfg(feature = "uncased")]
Uncased(Uncased<'static>),
}

impl PhfHash for ParsedKey {
Expand All @@ -61,6 +65,8 @@ impl PhfHash for ParsedKey {
ParsedKey::UniCase(s) => s.phf_hash(state),
#[cfg(feature = "unicase")]
ParsedKey::UniCaseAscii(s) => s.phf_hash(state),
#[cfg(feature = "uncased")]
ParsedKey::Uncased(s) => s.phf_hash(state),
}
}
}
Expand Down Expand Up @@ -142,40 +148,34 @@ impl ParsedKey {
}
}
Expr::Group(group) => ParsedKey::from_expr(&group.expr),
#[cfg(feature = "unicase")]
#[cfg(any(feature = "unicase", feature = "uncased"))]
Expr::Call(call) => {
if let Expr::Path(ep) = call.func.as_ref() {
let segments = &mut ep.path.segments.iter().rev();
let last = &segments.next()?.ident;
let last_ahead = &segments.next()?.ident;
let is_unicase_unicode = last_ahead == "UniCase" && last == "unicode";
let is_unicase_ascii = last_ahead == "UniCase" && last == "ascii";
let is_ascii_new = last_ahead == "Ascii" && last == "new";
if call.args.len() == 1
&& (is_unicase_unicode || is_unicase_ascii || is_ascii_new)
{
if call.args.len() == 1 {
if let Some(Expr::Lit(ExprLit {
attrs: _,
lit: Lit::Str(s),
})) = call.args.first()
{
let v = if is_unicase_unicode {
ParsedKey::UniCase(UniCase::unicode(s.value()))
} else if is_unicase_ascii {
ParsedKey::UniCase(UniCase::ascii(s.value()))
} else {
ParsedKey::UniCaseAscii(Ascii::new(s.value()))
};
Some(v)
} else {
None
let segments = &mut ep.path.segments.iter().rev();
let last = &segments.next()?.ident;
let last_ahead = &segments.next()?.ident;
#[cfg(feature = "unicase")]
if last_ahead == "UniCase" && last == "unicode" {
return Some(ParsedKey::UniCase(UniCase::unicode(s.value())));
} else if last_ahead == "UniCase" && last == "ascii" {
return Some(ParsedKey::UniCase(UniCase::ascii(s.value())));
} else if last_ahead == "Ascii" && last == "new" {
return Some(ParsedKey::UniCaseAscii(Ascii::new(s.value())));
}
#[cfg(feature = "uncased")]
if last_ahead == "UncasedStr" && last == "new" {
return Some(ParsedKey::Uncased(Uncased::new(s.value())));
}
}
} else {
None
}
} else {
None
}
None
}
_ => None,
}
Expand Down
5 changes: 3 additions & 2 deletions phf_macros_tests/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ categories = ["data-structures"]
[dependencies]

[dev-dependencies]
phf = { version = "0.11", features = ["macros"] }
phf_macros = { version = "0.11", features = ["unicase"] }
phf = { path = "../phf", features = ["macros"] }
phf_macros = { path = "../phf_macros", features = ["uncased", "unicase"] }
trybuild = "1.0"
uncased = "0.9.9"
unicase = "2.6.0"
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
use phf::phf_map;
use uncased::UncasedStr;

static MAP: phf::Map<&'static UncasedStr, isize> = phf_map!(
UncasedStr::new("FOO") => 42,
UncasedStr::new("foo") => 42, //~ ERROR duplicate key
);

fn main() {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
error: duplicate key
--> tests/compile-fail-uncased/equivalent-keys.rs:6:5
|
6 | UncasedStr::new("foo") => 42, //~ ERROR duplicate key
| ^^^^^^^^^^^^^^^^^^^^^^
12 changes: 12 additions & 0 deletions phf_macros_tests/tests/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,18 @@ mod map {
assert!(Some(&11) == MAP.get(&Ascii::new("bar")));
assert_eq!(None, MAP.get(&Ascii::new("asdf")));
}

#[test]
fn test_uncased() {
use uncased::UncasedStr;
static MAP: phf::Map<&'static UncasedStr, isize> = phf_map!(
UncasedStr::new("FOO") => 10,
UncasedStr::new("Bar") => 11,
);
assert!(Some(&10) == MAP.get(&UncasedStr::new("FOo")));
assert!(Some(&11) == MAP.get(&UncasedStr::new("bar")));
assert_eq!(None, MAP.get(&UncasedStr::new("asdf")));
}
}

mod set {
Expand Down
7 changes: 7 additions & 0 deletions phf_macros_tests/tests/trybuild.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,13 @@ fn compile_test_unicase() {
t.compile_fail("tests/compile-fail-unicase/*.rs");
}

#[test]
#[ignore]
fn compile_test_uncased() {
let t = trybuild::TestCases::new();
t.compile_fail("tests/compile-fail-uncased/*.rs");
}

#[test]
#[ignore]
fn compile_fail() {
Expand Down
2 changes: 1 addition & 1 deletion phf_shared/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,5 @@ std = []

[dependencies]
siphasher = "0.3"
uncased = { version = "0.9.6", optional = true, default-features = false }
uncased = { version = "0.9.9", optional = true, default-features = false }
unicase = { version = "2.6.0", optional = true }
7 changes: 2 additions & 5 deletions phf_shared/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -343,12 +343,9 @@ impl PhfHash for uncased::UncasedStr {
#[cfg(feature = "uncased")]
impl FmtConst for uncased::UncasedStr {
fn fmt_const(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
// transmute is not stable in const fns (rust-lang/rust#53605), so
// `UncasedStr::new` can't be a const fn itself, but we can inline the
// call to transmute here in the meantime.
f.write_str("unsafe { ::core::mem::transmute::<&'static str, &'static UncasedStr>(")?;
f.write_str("UncasedStr::new(")?;
self.as_str().fmt_const(f)?;
f.write_str(") }")
f.write_str(")")
}
}

Expand Down

0 comments on commit 0e72fa2

Please sign in to comment.