]> git.proxmox.com Git - rustc.git/blob - src/vendor/phf_codegen/src/lib.rs
New upstream version 1.27.1+dfsg1
[rustc.git] / src / vendor / phf_codegen / src / lib.rs
1 //! A set of builders to generate Rust source for PHF data structures at
2 //! compile time.
3 //!
4 //! The provided builders are intended to be used in a Cargo build script to
5 //! generate a Rust source file that will be included in a library at build
6 //! time.
7 //!
8 //! # Examples
9 //!
10 //! build.rs
11 //!
12 //! ```rust,no_run
13 //! extern crate phf_codegen;
14 //!
15 //! use std::env;
16 //! use std::fs::File;
17 //! use std::io::{BufWriter, Write};
18 //! use std::path::Path;
19 //!
20 //! fn main() {
21 //! let path = Path::new(&env::var("OUT_DIR").unwrap()).join("codegen.rs");
22 //! let mut file = BufWriter::new(File::create(&path).unwrap());
23 //!
24 //! write!(&mut file, "static KEYWORDS: phf::Map<&'static str, Keyword> =
25 //! ").unwrap();
26 //! phf_codegen::Map::new()
27 //! .entry("loop", "Keyword::Loop")
28 //! .entry("continue", "Keyword::Continue")
29 //! .entry("break", "Keyword::Break")
30 //! .entry("fn", "Keyword::Fn")
31 //! .entry("extern", "Keyword::Extern")
32 //! .build(&mut file)
33 //! .unwrap();
34 //! write!(&mut file, ";\n").unwrap();
35 //! }
36 //! ```
37 //!
38 //! lib.rs
39 //!
40 //! ```ignore
41 //! extern crate phf;
42 //!
43 //! #[derive(Clone)]
44 //! enum Keyword {
45 //! Loop,
46 //! Continue,
47 //! Break,
48 //! Fn,
49 //! Extern,
50 //! }
51 //!
52 //! include!(concat!(env!("OUT_DIR"), "/codegen.rs"));
53 //!
54 //! pub fn parse_keyword(keyword: &str) -> Option<Keyword> {
55 //! KEYWORDS.get(keyword).cloned()
56 //! }
57 //! ```
58 //!
59 //! # Note
60 //!
61 //! The compiler's stack will overflow when processing extremely long method
62 //! chains (500+ calls). When generating large PHF data structures, consider
63 //! looping over the entries or making each call a separate statement:
64 //!
65 //! ```rust
66 //! let entries = [("hello", "1"), ("world", "2")];
67 //!
68 //! let mut builder = phf_codegen::Map::new();
69 //! for &(key, value) in &entries {
70 //! builder.entry(key, value);
71 //! }
72 //! // ...
73 //! ```
74 //!
75 //! ```rust
76 //! let mut builder = phf_codegen::Map::new();
77 //! builder.entry("hello", "1");
78 //! builder.entry("world", "2");
79 //! // ...
80 //! ```
81 #![doc(html_root_url="https://docs.rs/phf_codegen/0.7.20")]
82 extern crate phf_shared;
83 extern crate phf_generator;
84
85 use phf_shared::PhfHash;
86 use std::collections::HashSet;
87 use std::fmt;
88 use std::hash::Hash;
89 use std::io;
90 use std::io::prelude::*;
91
92 /// A builder for the `phf::Map` type.
93 pub struct Map<K> {
94 keys: Vec<K>,
95 values: Vec<String>,
96 path: String,
97 }
98
99 impl<K: Hash+PhfHash+Eq+fmt::Debug> Map<K> {
100 /// Creates a new `phf::Map` builder.
101 pub fn new() -> Map<K> {
102 // FIXME rust#27438
103 //
104 // On Windows/MSVC there are major problems with the handling of dllimport.
105 // Here, because downstream build scripts only invoke generics from phf_codegen,
106 // the linker ends up throwing a way a bunch of static symbols we actually need.
107 // This works around the problem, assuming that all clients call `Map::new` by
108 // calling a non-generic function.
109 fn noop_fix_for_27438() {
110 }
111 noop_fix_for_27438();
112
113 Map {
114 keys: vec![],
115 values: vec![],
116 path: String::from("::phf"),
117 }
118 }
119
120 /// Set the path to the `phf` crate from the global namespace
121 pub fn phf_path(&mut self, path: &str) -> &mut Map<K> {
122 self.path = path.to_owned();
123 self
124 }
125
126 /// Adds an entry to the builder.
127 ///
128 /// `value` will be written exactly as provided in the constructed source.
129 pub fn entry(&mut self, key: K, value: &str) -> &mut Map<K> {
130 self.keys.push(key);
131 self.values.push(value.to_owned());
132 self
133 }
134
135 /// Constructs a `phf::Map`, outputting Rust source to the provided writer.
136 ///
137 /// # Panics
138 ///
139 /// Panics if there are any duplicate keys.
140 pub fn build<W: Write>(&self, w: &mut W) -> io::Result<()> {
141 let mut set = HashSet::new();
142 for key in &self.keys {
143 if !set.insert(key) {
144 panic!("duplicate key `{:?}`", key);
145 }
146 }
147
148 let state = phf_generator::generate_hash(&self.keys);
149
150 try!(write!(w,
151 "{}::Map {{
152 key: {},
153 disps: {}::Slice::Static(&[",
154 self.path, state.key, self.path));
155 for &(d1, d2) in &state.disps {
156 try!(write!(w,
157 "
158 ({}, {}),",
159 d1,
160 d2));
161 }
162 try!(write!(w,
163 "
164 ]),
165 entries: {}::Slice::Static(&[", self.path));
166 for &idx in &state.map {
167 try!(write!(w,
168 "
169 ({:?}, {}),",
170 &self.keys[idx],
171 &self.values[idx]));
172 }
173 write!(w,
174 "
175 ]),
176 }}")
177 }
178 }
179
180 /// A builder for the `phf::Set` type.
181 pub struct Set<T> {
182 map: Map<T>,
183 }
184
185 impl<T: Hash+PhfHash+Eq+fmt::Debug> Set<T> {
186 /// Constructs a new `phf::Set` builder.
187 pub fn new() -> Set<T> {
188 Set {
189 map: Map::new(),
190 }
191 }
192
193 /// Set the path to the `phf` crate from the global namespace
194 pub fn phf_path(&mut self, path: &str) -> &mut Set<T> {
195 self.map.phf_path(path);
196 self
197 }
198
199 /// Adds an entry to the builder.
200 pub fn entry(&mut self, entry: T) -> &mut Set<T> {
201 self.map.entry(entry, "()");
202 self
203 }
204
205 /// Constructs a `phf::Set`, outputting Rust source to the provided writer.
206 ///
207 /// # Panics
208 ///
209 /// Panics if there are any duplicate entries.
210 pub fn build<W: Write>(&self, w: &mut W) -> io::Result<()> {
211 try!(write!(w, "{}::Set {{ map: ", self.map.path));
212 try!(self.map.build(w));
213 write!(w, " }}")
214 }
215 }
216
217 /// A builder for the `phf::OrderedMap` type.
218 pub struct OrderedMap<K> {
219 keys: Vec<K>,
220 values: Vec<String>,
221 path: String,
222 }
223
224 impl<K: Hash+PhfHash+Eq+fmt::Debug> OrderedMap<K> {
225 /// Constructs a enw `phf::OrderedMap` builder.
226 pub fn new() -> OrderedMap<K> {
227 OrderedMap {
228 keys: vec![],
229 values: vec![],
230 path: String::from("::phf"),
231 }
232 }
233
234 /// Set the path to the `phf` crate from the global namespace
235 pub fn phf_path(&mut self, path: &str) -> &mut OrderedMap<K> {
236 self.path = path.to_owned();
237 self
238 }
239
240 /// Adds an entry to the builder.
241 ///
242 /// `value` will be written exactly as provided in the constructed source.
243 pub fn entry(&mut self, key: K, value: &str) -> &mut OrderedMap<K> {
244 self.keys.push(key);
245 self.values.push(value.to_owned());
246 self
247 }
248
249 /// Constructs a `phf::OrderedMap`, outputting Rust source to the provided
250 /// writer.
251 ///
252 /// # Panics
253 ///
254 /// Panics if there are any duplicate keys.
255 pub fn build<W: Write>(&self, w: &mut W) -> io::Result<()> {
256 let mut set = HashSet::new();
257 for key in &self.keys {
258 if !set.insert(key) {
259 panic!("duplicate key `{:?}`", key);
260 }
261 }
262
263 let state = phf_generator::generate_hash(&self.keys);
264
265 try!(write!(w,
266 "{}::OrderedMap {{
267 key: {},
268 disps: {}::Slice::Static(&[",
269 self.path, state.key, self.path));
270 for &(d1, d2) in &state.disps {
271 try!(write!(w,
272 "
273 ({}, {}),",
274 d1,
275 d2));
276 }
277 try!(write!(w,
278 "
279 ]),
280 idxs: {}::Slice::Static(&[", self.path));
281 for &idx in &state.map {
282 try!(write!(w,
283 "
284 {},",
285 idx));
286 }
287 try!(write!(w,
288 "
289 ]),
290 entries: {}::Slice::Static(&[", self.path));
291 for (key, value) in self.keys.iter().zip(self.values.iter()) {
292 try!(write!(w,
293 "
294 ({:?}, {}),",
295 key,
296 value));
297 }
298 write!(w,
299 "
300 ]),
301 }}")
302 }
303 }
304
305 /// A builder for the `phf::OrderedSet` type.
306 pub struct OrderedSet<T> {
307 map: OrderedMap<T>,
308 }
309
310 impl<T: Hash+PhfHash+Eq+fmt::Debug> OrderedSet<T> {
311 /// Constructs a new `phf::OrderedSet` builder.
312 pub fn new() -> OrderedSet<T> {
313 OrderedSet {
314 map: OrderedMap::new(),
315 }
316 }
317
318 /// Set the path to the `phf` crate from the global namespace
319 pub fn phf_path(&mut self, path: &str) -> &mut OrderedSet<T> {
320 self.map.phf_path(path);
321 self
322 }
323
324 /// Adds an entry to the builder.
325 pub fn entry(&mut self, entry: T) -> &mut OrderedSet<T> {
326 self.map.entry(entry, "()");
327 self
328 }
329
330 /// Constructs a `phf::OrderedSet`, outputting Rust source to the provided
331 /// writer.
332 ///
333 /// # Panics
334 ///
335 /// Panics if there are any duplicate entries.
336 pub fn build<W: Write>(&self, w: &mut W) -> io::Result<()> {
337 try!(write!(w, "{}::OrderedSet {{ map: ", self.map.path));
338 try!(self.map.build(w));
339 write!(w, " }}")
340 }
341 }