Skip to main content

phf/
lib.rs

1//! Rust-PHF is a library to generate efficient lookup tables at compile time using
2//! [perfect hash functions](http://en.wikipedia.org/wiki/Perfect_hash_function).
3//!
4//! It currently uses the
5//! [CHD algorithm](http://cmph.sourceforge.net/papers/esa09.pdf) by default and
6//! also ships an experimental `ptrhash` feature for an alternative MPHF layout.
7//!
8//! MSRV (minimum supported rust version) is Rust 1.85.
9//!
10//! ## Usage
11//!
12//! PHF data structures can be constructed via either the procedural
13//! macros in the `phf_macros` crate or code generation supported by the
14//! `phf_codegen` crate. If you prefer macros, you can easily use them by
15//! enabling the `macros` feature of the `phf` crate, like:
16//!
17//!```toml
18//! [dependencies]
19//! phf = { version = "0.14.0", features = ["macros"] }
20//! ```
21//!
22//! To try the experimental MPHF alternative instead of the default CHD layout,
23//! enable the `ptrhash` feature on every `phf` crate involved in generation and
24//! runtime lookup:
25//!
26//! ```toml
27//! [dependencies]
28//! phf = { version = "0.14.0", features = ["macros", "ptrhash"] }
29//! ```
30//!
31//! To compile the `phf` crate with a dependency on
32//! libcore instead of libstd, enabling use in environments where libstd
33//! will not work, set `default-features = false` for the dependency:
34//!
35//! ```toml
36//! [dependencies]
37//! # to use `phf` in `no_std` environments
38//! phf = { version = "0.14.0", default-features = false }
39//! ```
40//!
41//! ## Example (with the `macros` feature enabled)
42//!
43//! ```rust
44//! use phf::phf_map;
45//!
46//! #[derive(Clone)]
47//! pub enum Keyword {
48//!     Loop,
49//!     Continue,
50//!     Break,
51//!     Fn,
52//!     Extern,
53//! }
54//!
55//! static KEYWORDS: phf::Map<&'static str, Keyword> = phf_map! {
56//!     "loop" => Keyword::Loop,
57//!     "continue" => Keyword::Continue,
58//!     "break" => Keyword::Break,
59//!     "fn" => Keyword::Fn,
60//!     "extern" => Keyword::Extern,
61//! };
62//!
63//! pub fn parse_keyword(keyword: &str) -> Option<Keyword> {
64//!     KEYWORDS.get(keyword).cloned()
65//! }
66//! ```
67//!
68//! Alternatively, you can use the [`phf_codegen`] crate to generate PHF datatypes
69//! in a build script.
70//!
71//! [`phf_codegen`]: https://docs.rs/phf_codegen
72//!
73//! ## Note
74//!
75//! Currently, the macro syntax has some limitations and may not
76//! work as you want. See [#196] for example.
77//!
78//! [#196]: https://github.com/rust-phf/rust-phf/issues/196
79
80#![doc(html_root_url = "https://docs.rs/phf/0.14.0")]
81#![warn(missing_docs)]
82#![cfg_attr(not(feature = "std"), no_std)]
83
84#[cfg(feature = "std")]
85extern crate std as core;
86
87#[cfg(feature = "macros")]
88/// Macro to create a `static` (compile-time) [`Map`].
89///
90/// Requires the `macros` feature.
91///
92/// Supported key expressions are:
93/// - literals: bools, (byte) strings, bytes, chars, and integers (integer
94///   literals in the first key's type shape must have suffixes; later
95///   unsuffixed integers infer from the same position in that first key)
96/// - arrays of `u8` integer literals
97/// - tuples of any supported key expressions, up to 12 elements
98/// - dereferenced byte string literals
99/// - OR patterns using `|` to map multiple keys to the same value
100/// - `UniCase::unicode(string)`, `UniCase::ascii(string)`, or `Ascii::new(string)` if the `unicase` feature is enabled
101/// - `UncasedStr::new(string)` if the `uncased` feature is enabled
102///
103/// All keys must use the same supported key expression type as the first key.
104///
105/// # Example
106///
107/// ```
108/// use phf::{phf_map, Map};
109///
110/// static MY_MAP: Map<&'static str, u32> = phf_map! {
111///     "hello" => 1,
112///     "world" => 2,
113/// };
114///
115/// fn main () {
116///     assert_eq!(MY_MAP["hello"], 1);
117/// }
118/// ```
119///
120/// # OR Patterns
121///
122/// You can use OR patterns to map multiple keys to the same value:
123///
124/// ```
125/// use phf::{phf_map, Map};
126///
127/// static OPERATORS: Map<&'static str, &'static str> = phf_map! {
128///     "+" | "add" | "plus" => "addition",
129///     "-" | "sub" | "minus" => "subtraction",
130///     "*" | "mul" | "times" => "multiplication",
131/// };
132///
133/// fn main() {
134///     assert_eq!(OPERATORS["+"], "addition");
135///     assert_eq!(OPERATORS["add"], "addition");
136///     assert_eq!(OPERATORS["plus"], "addition");
137/// }
138/// ```
139pub use phf_macros::phf_map;
140
141#[cfg(feature = "macros")]
142/// Macro to create a `static` (compile-time) [`OrderedMap`].
143///
144/// Requires the `macros` feature. Same usage as [`phf_map`].
145pub use phf_macros::phf_ordered_map;
146
147#[cfg(feature = "macros")]
148/// Macro to create a `static` (compile-time) [`Set`].
149///
150/// Requires the `macros` feature.
151///
152/// # Example
153///
154/// ```
155/// use phf::{phf_set, Set};
156///
157/// static MY_SET: Set<&'static str> = phf_set! {
158///     "hello world",
159///     "hola mundo",
160/// };
161///
162/// fn main () {
163///     assert!(MY_SET.contains("hello world"));
164/// }
165/// ```
166///
167/// # OR Patterns
168///
169/// You can use OR patterns to include multiple keys in a single entry:
170///
171/// ```
172/// use phf::{phf_set, Set};
173///
174/// static KEYWORDS: Set<&'static str> = phf_set! {
175///     "if" | "elif" | "else",
176///     "for" | "while" | "loop",
177///     "fn" | "function" | "def",
178/// };
179///
180/// fn main() {
181///     assert!(KEYWORDS.contains("if"));
182///     assert!(KEYWORDS.contains("elif"));
183///     assert!(KEYWORDS.contains("else"));
184///     assert!(KEYWORDS.contains("for"));
185/// }
186/// ```
187pub use phf_macros::phf_set;
188
189#[cfg(feature = "macros")]
190/// Macro to create a `static` (compile-time) [`OrderedSet`].
191///
192/// Requires the `macros` feature. Same usage as [`phf_set`].
193pub use phf_macros::phf_ordered_set;
194
195// `__resolve_cfg` re-enters the proc macro after filtering `#[cfg]`
196// attributes. This supports both `phf::phf_map!` re-exports and direct
197// `phf_macros::phf_map!` users where `phf/macros` is not enabled.
198#[cfg(feature = "macros")]
199#[doc(hidden)]
200#[macro_export]
201macro_rules! __call_macro {
202    ($callback:ident { $($tokens:tt)* }) => {
203        $crate::$callback! { $($tokens)* }
204    };
205}
206
207#[cfg(not(feature = "macros"))]
208#[doc(hidden)]
209#[macro_export]
210macro_rules! __call_macro {
211    ($callback:ident { $($tokens:tt)* }) => {
212        phf_macros::$callback! { $($tokens)* }
213    };
214}
215
216#[doc(hidden)]
217// Invoked by proc macros to resolve `#[cfg]`s in the caller context.
218#[macro_export]
219macro_rules! __resolve_cfg {
220    // No `#[cfg]`s left to evaluate.
221    ($callback:ident [ $($acc:tt)* ] { $($in:tt)* }) => {
222        $crate::__call_macro! {
223            $callback { $($acc)* $($in)* }
224        }
225    };
226
227    // Evaluate a `#[cfg]`.
228    (
229        $callback:ident
230        [ $($acc:tt)* ]
231        { $($in1:tt)* }
232        { $(#[$meta:meta])+ $($in2:tt)* }
233        $($rest:tt)*
234    ) => {{
235        // Macro shadowing is allowed if the shadowed macro is unused.
236        #[allow(unused)]
237        macro_rules! resolver {
238            () => {
239                $crate::__resolve_cfg! {
240                    $callback
241                    [ $($acc)* $($in1)* ]
242                    $($rest)*
243                }
244            };
245        }
246
247        $(#[$meta])+
248        macro_rules! resolver {
249            () => {
250                $crate::__resolve_cfg! {
251                    $callback
252                    [ $($acc)* $($in1)* $($in2)* ]
253                    $($rest)*
254                }
255            };
256        }
257
258        resolver! {}
259    }};
260}
261
262#[doc(inline)]
263pub use self::map::Map;
264#[doc(inline)]
265pub use self::ordered_map::OrderedMap;
266#[doc(inline)]
267pub use self::ordered_set::OrderedSet;
268#[doc(inline)]
269pub use self::set::Set;
270pub use phf_shared::{PhfEq, PhfHash};
271
272pub mod map;
273pub mod ordered_map;
274pub mod ordered_set;
275pub mod set;