1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
//! CPHF is a library to generate efficient lookup tables at compile time using
//! [perfect hash functions](http://en.wikipedia.org/wiki/Perfect_hash_function).
//!
//! It currently uses the
//! [CHD algorithm](http://cmph.sourceforge.net/papers/esa09.pdf) and can generate
//! a 120 entry map in roughly 1 second.
//!
//! MSRV (minimum supported rust version) is Rust 1.85.
//!
//! In contrast to the excellent [`phf`](https://github.com/rust-phf/rust-phf/) crate, this crate
//! uses no code generation outside of normal `macro_rules`. Instead it generates maps using `const` expressions.
//! As such, this crate is several orders of magnitude slower than `phf` (so maps with thousands of entries would probably be
//! better served by `phf`), but doing so allows it to avoid all the major drawbacks. Namely, [nested maps](https://github.com/rust-phf/rust-phf/issues/183) are supported [any type](https://github.com/rust-phf/rust-phf/issues/196) can be used as a key (provided it implements the correct traits and pseudo-traits).
//!
//! ## Usage
//!
//! Simply add `cphf` as a depenency and utilize the included [`phf_ordered_map`] macro to construct an [`OrderedMap`]
//! or the [`phf_ordered_set`] macro to construct an [`OrderedSet`]
//!
//! ```
//! use cphf::{phf_ordered_map, OrderedMap};
//!
//! #[derive(Clone)]
//! pub enum Keyword {
//! Loop,
//! Continue,
//! Break,
//! Fn,
//! Extern,
//! }
//!
//! static KEYWORDS: OrderedMap<&'static str, Keyword> = phf_ordered_map! {&'static str, Keyword;
//! "loop" => Keyword::Loop,
//! "continue" => Keyword::Continue,
//! "break" => Keyword::Break,
//! "fn" => Keyword::Fn,
//! "extern" => Keyword::Extern,
//! };
//!
//! pub fn parse_keyword(keyword: &str) -> Option<Keyword> {
//! KEYWORDS.get(keyword).cloned()
//! }
//! ```
//!
//! Inclusion of duplicate keys will result in a compiler error.
//!
//! ```compile_fail
//! use cphf::{phf_ordered_set, OrderedSet};
//! static DUPLICATE_KEYS: OrderedSet<u32> = phf_ordered_set! {u32;
//! 0,
//! 1,
//! 0,
//! };
//! ```
//!
//! ```compile_fail
//! use cphf::{phf_ordered_map, OrderedMap};
//! static DUPLICATE_KEYS: OrderedMap<u32, ()> = phf_ordered_map! {u32, ();
//! 0 => (),
//! 1 => (),
//! 0 => (),
//! };
//! ```
//!
//! ## Advanced Usage
//!
//! If we wanted to make the above example `Keyword` usable as a key, we would implement traits (and pseudo-traits) like this:
//!
//! ```
//! use core::borrow::Borrow;
//! use cphf::{ConstKey, PhfKey, PhfKeyProxy, Hasher};
//!
//! // We now require `Eq` to be a key
//! #[derive(Clone, PartialEq, Eq)]
//! pub enum Keyword {
//! Loop,
//! Continue,
//! Break,
//! Fn,
//! Extern,
//! }
//!
//! // Define a new type for our pseudo-trait
//! pub struct KeywordMarker;
//!
//! // Glue our marker type to the real type.
//! impl PhfKey for Keyword {
//! type ConstKey = KeywordMarker;
//! }
//! impl ConstKey for KeywordMarker {
//! type PhfKey = Keyword;
//! }
//!
//! // Implement our pseudo-trait. These are `const` inherent methods since there
//! // is current no method of adding `const` methods to a trait
//! impl KeywordMarker {
//! pub const fn pfh_hash(value: &Keyword, state: &mut Hasher) {
//! // We can only use `const` functions here
//! // If Keyword were `Copy` would could use `*value as u32`
//! // But for the sake of this example, we will do this the hard way
//! use Keyword::*;
//! let value = match value {
//! Loop => 0,
//! Continue => 1,
//! Break => 2,
//! Fn => 3,
//! Extern => 4,
//! };
//! <u32 as PhfKey>::ConstKey::pfh_hash(&value, state)
//! }
//! pub const fn pfh_eq(lhs: &Keyword, rhs: &Keyword) -> bool {
//! // We can only use `const` equality functions here
//! // If Keyword were `Copy` would could use `*lhs as u32 == *rhs as u32`
//! // But for the sake of this example, we will do this the hard way
//! use Keyword::*;
//! match (lhs, rhs) {
//! (Loop, Loop) | (Continue, Continue) | (Break, Break) | (Fn, Fn) | (Extern, Extern) => true,
//! _ => false,
//! }
//! }
//! }
//!
//! // Finally we add a trait implementation to allow usage of indexing methods like `get`.
//! // You can make this broad or narrow as you would like, doing so just modifies what types callers can pass to `OrderedMap::get`,
//! // but `?Sized + Borrow<Self>` is a pretty good baseline.
//! impl<PK: ?Sized + Borrow<Keyword>> PhfKeyProxy<PK> for Keyword {
//! fn pfh_hash(pk: &PK, state: &mut Hasher) {
//! // Call the above hash function (or else make an equivalent hash somehow)
//! KeywordMarker::pfh_hash(pk.borrow(), state)
//! }
//! fn pfh_eq(&self, other: &PK) -> bool {
//! // Implement equality
//! self == other.borrow()
//! }
//! }
//!
//! // Now we can make use `Keyword` as a key
//! static KEYWORDS: cphf::OrderedMap<Keyword, &'static str> = cphf::phf_ordered_map! {Keyword, &'static str;
//! Keyword::Loop => "loop",
//! Keyword::Continue => "continue",
//! Keyword::Break => "break",
//! Keyword::Fn => "fn",
//! Keyword::Extern => "extern",
//! };
//! ```
//!
use Hash128;
pub use SipHasher13 as Hasher;
pub use const_shellsort;
pub use *;
pub use Generator;
pub use *;
pub use *;
/// The final computed state during map generation
///
/// Exporting this way hides the actual type so it can only be used by the macros.
pub type BuilderState<const LEN: usize, const BUCKET_LEN: usize> =
BuilderState;
/// A hash result broken down into parts for ease of use in displacement
/// Displace as `d2 + f1*d1 + f2`
const