diff options
Diffstat (limited to 'third_party/rust/phf_codegen')
-rw-r--r-- | third_party/rust/phf_codegen/.cargo-checksum.json | 1 | ||||
-rw-r--r-- | third_party/rust/phf_codegen/Cargo.toml | 25 | ||||
-rw-r--r-- | third_party/rust/phf_codegen/src/lib.rs | 486 |
3 files changed, 512 insertions, 0 deletions
diff --git a/third_party/rust/phf_codegen/.cargo-checksum.json b/third_party/rust/phf_codegen/.cargo-checksum.json new file mode 100644 index 0000000000..1f6ffe9fcf --- /dev/null +++ b/third_party/rust/phf_codegen/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{"Cargo.toml":"f6fd52523100ca5655e0326407e2e4b7c9df947ab55a2d1079b424ada242e9cc","src/lib.rs":"26542892e9f9aac772fe1c37b5f5d8119ec64db91bf8c4f8b018c30cdff33ee8"},"package":"4fb1c3a8bc4dd4e5cfce29b44ffc14bedd2ee294559a294e2a4d4c9e9a6a13cd"}
\ No newline at end of file diff --git a/third_party/rust/phf_codegen/Cargo.toml b/third_party/rust/phf_codegen/Cargo.toml new file mode 100644 index 0000000000..c22369fb27 --- /dev/null +++ b/third_party/rust/phf_codegen/Cargo.toml @@ -0,0 +1,25 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2018" +name = "phf_codegen" +version = "0.10.0" +authors = ["Steven Fackler <sfackler@gmail.com>"] +description = "Codegen library for PHF types" +readme = "../README.md" +license = "MIT" +repository = "https://github.com/sfackler/rust-phf" +[dependencies.phf_generator] +version = "0.10.0" + +[dependencies.phf_shared] +version = "0.10.0" diff --git a/third_party/rust/phf_codegen/src/lib.rs b/third_party/rust/phf_codegen/src/lib.rs new file mode 100644 index 0000000000..dfcf6ed0ec --- /dev/null +++ b/third_party/rust/phf_codegen/src/lib.rs @@ -0,0 +1,486 @@ +//! A set of builders to generate Rust source for PHF data structures at +//! compile time. +//! +//! The provided builders are intended to be used in a Cargo build script to +//! generate a Rust source file that will be included in a library at build +//! time. +//! +//! # Examples +//! +//! build.rs: +//! +//! ```rust,no_run +//! use std::env; +//! use std::fs::File; +//! use std::io::{BufWriter, Write}; +//! use std::path::Path; +//! +//! fn main() { +//! let path = Path::new(&env::var("OUT_DIR").unwrap()).join("codegen.rs"); +//! let mut file = BufWriter::new(File::create(&path).unwrap()); +//! +//! writeln!( +//! &mut file, +//! "static KEYWORDS: phf::Map<&'static str, Keyword> = \n{};\n", +//! phf_codegen::Map::new() +//! .entry("loop", "Keyword::Loop") +//! .entry("continue", "Keyword::Continue") +//! .entry("break", "Keyword::Break") +//! .entry("fn", "Keyword::Fn") +//! .entry("extern", "Keyword::Extern") +//! .build() +//! ).unwrap(); +//! } +//! ``` +//! +//! lib.rs: +//! +//! ```ignore +//! #[derive(Clone)] +//! enum Keyword { +//! Loop, +//! Continue, +//! Break, +//! Fn, +//! Extern, +//! } +//! +//! include!(concat!(env!("OUT_DIR"), "/codegen.rs")); +//! +//! pub fn parse_keyword(keyword: &str) -> Option<Keyword> { +//! KEYWORDS.get(keyword).cloned() +//! } +//! ``` +//! +//! ##### Byte-String Keys +//! Byte strings by default produce references to fixed-size arrays; the compiler needs a hint +//! to coerce them to slices: +//! +//! build.rs: +//! +//! ```rust,no_run +//! use std::env; +//! use std::fs::File; +//! use std::io::{BufWriter, Write}; +//! use std::path::Path; +//! +//! fn main() { +//! let path = Path::new(&env::var("OUT_DIR").unwrap()).join("codegen.rs"); +//! let mut file = BufWriter::new(File::create(&path).unwrap()); +//! +//! writeln!( +//! &mut file, +//! "static KEYWORDS: phf::Map<&'static [u8], Keyword> = \n{};\n", +//! phf_codegen::Map::<&[u8]>::new() +//! .entry(b"loop", "Keyword::Loop") +//! .entry(b"continue", "Keyword::Continue") +//! .entry(b"break", "Keyword::Break") +//! .entry(b"fn", "Keyword::Fn") +//! .entry(b"extern", "Keyword::Extern") +//! .build() +//! ).unwrap(); +//! } +//! ``` +//! +//! lib.rs: +//! +//! ```rust,ignore +//! #[derive(Clone)] +//! enum Keyword { +//! Loop, +//! Continue, +//! Break, +//! Fn, +//! Extern, +//! } +//! +//! include!(concat!(env!("OUT_DIR"), "/codegen.rs")); +//! +//! pub fn parse_keyword(keyword: &[u8]) -> Option<Keyword> { +//! KEYWORDS.get(keyword).cloned() +//! } +//! ``` +//! +//! # Note +//! +//! The compiler's stack will overflow when processing extremely long method +//! chains (500+ calls). When generating large PHF data structures, consider +//! looping over the entries or making each call a separate statement: +//! +//! ```rust +//! let entries = [("hello", "1"), ("world", "2")]; +//! +//! let mut builder = phf_codegen::Map::new(); +//! for &(key, value) in &entries { +//! builder.entry(key, value); +//! } +//! // ... +//! ``` +//! +//! ```rust +//! let mut builder = phf_codegen::Map::new(); +//! builder.entry("hello", "1"); +//! builder.entry("world", "2"); +//! // ... +//! ``` +#![doc(html_root_url = "https://docs.rs/phf_codegen/0.9")] + +use phf_shared::{FmtConst, PhfHash}; +use std::collections::HashSet; +use std::fmt; +use std::hash::Hash; + +use phf_generator::HashState; + +struct Delegate<T>(T); + +impl<T: FmtConst> fmt::Display for Delegate<T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.0.fmt_const(f) + } +} + +/// A builder for the `phf::Map` type. +pub struct Map<K> { + keys: Vec<K>, + values: Vec<String>, + path: String, +} + +impl<K: Hash + PhfHash + Eq + FmtConst> Map<K> { + /// Creates a new `phf::Map` builder. + pub fn new() -> Map<K> { + // FIXME rust#27438 + // + // On Windows/MSVC there are major problems with the handling of dllimport. + // Here, because downstream build scripts only invoke generics from phf_codegen, + // the linker ends up throwing a way a bunch of static symbols we actually need. + // This works around the problem, assuming that all clients call `Map::new` by + // calling a non-generic function. + fn noop_fix_for_27438() {} + noop_fix_for_27438(); + + Map { + keys: vec![], + values: vec![], + path: String::from("::phf"), + } + } + + /// Set the path to the `phf` crate from the global namespace + pub fn phf_path(&mut self, path: &str) -> &mut Map<K> { + self.path = path.to_owned(); + self + } + + /// Adds an entry to the builder. + /// + /// `value` will be written exactly as provided in the constructed source. + pub fn entry(&mut self, key: K, value: &str) -> &mut Map<K> { + self.keys.push(key); + self.values.push(value.to_owned()); + self + } + + /// Calculate the hash parameters and return a struct implementing + /// [`Display`](::std::fmt::Display) which will print the constructed `phf::Map`. + /// + /// # Panics + /// + /// Panics if there are any duplicate keys. + pub fn build(&self) -> DisplayMap<'_, K> { + let mut set = HashSet::new(); + for key in &self.keys { + if !set.insert(key) { + panic!("duplicate key `{}`", Delegate(key)); + } + } + + let state = phf_generator::generate_hash(&self.keys); + + DisplayMap { + path: &self.path, + keys: &self.keys, + values: &self.values, + state, + } + } +} + +/// An adapter for printing a [`Map`](Map). +pub struct DisplayMap<'a, K> { + path: &'a str, + state: HashState, + keys: &'a [K], + values: &'a [String], +} + +impl<'a, K: FmtConst + 'a> fmt::Display for DisplayMap<'a, K> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + // funky formatting here for nice output + write!( + f, + "{}::Map {{ + key: {:?}, + disps: &[", + self.path, self.state.key + )?; + + // write map displacements + for &(d1, d2) in &self.state.disps { + write!( + f, + " + ({}, {}),", + d1, d2 + )?; + } + + write!( + f, + " + ], + entries: &[", + )?; + + // write map entries + for &idx in &self.state.map { + write!( + f, + " + ({}, {}),", + Delegate(&self.keys[idx]), + &self.values[idx] + )?; + } + + write!( + f, + " + ], +}}" + ) + } +} + +/// A builder for the `phf::Set` type. +pub struct Set<T> { + map: Map<T>, +} + +impl<T: Hash + PhfHash + Eq + FmtConst> Set<T> { + /// Constructs a new `phf::Set` builder. + pub fn new() -> Set<T> { + Set { map: Map::new() } + } + + /// Set the path to the `phf` crate from the global namespace + pub fn phf_path(&mut self, path: &str) -> &mut Set<T> { + self.map.phf_path(path); + self + } + + /// Adds an entry to the builder. + pub fn entry(&mut self, entry: T) -> &mut Set<T> { + self.map.entry(entry, "()"); + self + } + + /// Calculate the hash parameters and return a struct implementing + /// [`Display`](::std::fmt::Display) which will print the constructed `phf::Set`. + /// + /// # Panics + /// + /// Panics if there are any duplicate keys. + pub fn build(&self) -> DisplaySet<'_, T> { + DisplaySet { + inner: self.map.build(), + } + } +} + +/// An adapter for printing a [`Set`](Set). +pub struct DisplaySet<'a, T> { + inner: DisplayMap<'a, T>, +} + +impl<'a, T: FmtConst + 'a> fmt::Display for DisplaySet<'a, T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}::Set {{ map: {} }}", self.inner.path, self.inner) + } +} + +/// A builder for the `phf::OrderedMap` type. +pub struct OrderedMap<K> { + keys: Vec<K>, + values: Vec<String>, + path: String, +} + +impl<K: Hash + PhfHash + Eq + FmtConst> OrderedMap<K> { + /// Constructs a enw `phf::OrderedMap` builder. + pub fn new() -> OrderedMap<K> { + OrderedMap { + keys: vec![], + values: vec![], + path: String::from("::phf"), + } + } + + /// Set the path to the `phf` crate from the global namespace + pub fn phf_path(&mut self, path: &str) -> &mut OrderedMap<K> { + self.path = path.to_owned(); + self + } + + /// Adds an entry to the builder. + /// + /// `value` will be written exactly as provided in the constructed source. + pub fn entry(&mut self, key: K, value: &str) -> &mut OrderedMap<K> { + self.keys.push(key); + self.values.push(value.to_owned()); + self + } + + /// Calculate the hash parameters and return a struct implementing + /// [`Display`](::std::fmt::Display) which will print the constructed + /// `phf::OrderedMap`. + /// + /// # Panics + /// + /// Panics if there are any duplicate keys. + pub fn build(&self) -> DisplayOrderedMap<'_, K> { + let mut set = HashSet::new(); + for key in &self.keys { + if !set.insert(key) { + panic!("duplicate key `{}`", Delegate(key)); + } + } + + let state = phf_generator::generate_hash(&self.keys); + + DisplayOrderedMap { + path: &self.path, + state, + keys: &self.keys, + values: &self.values, + } + } +} + +/// An adapter for printing a [`OrderedMap`](OrderedMap). +pub struct DisplayOrderedMap<'a, K> { + path: &'a str, + state: HashState, + keys: &'a [K], + values: &'a [String], +} + +impl<'a, K: FmtConst + 'a> fmt::Display for DisplayOrderedMap<'a, K> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!( + f, + "{}::OrderedMap {{ + key: {:?}, + disps: &[", + self.path, self.state.key + )?; + for &(d1, d2) in &self.state.disps { + write!( + f, + " + ({}, {}),", + d1, d2 + )?; + } + write!( + f, + " + ], + idxs: &[", + )?; + for &idx in &self.state.map { + write!( + f, + " + {},", + idx + )?; + } + write!( + f, + " + ], + entries: &[", + )?; + for (key, value) in self.keys.iter().zip(self.values.iter()) { + write!( + f, + " + ({}, {}),", + Delegate(key), + value + )?; + } + write!( + f, + " + ], +}}" + ) + } +} + +/// A builder for the `phf::OrderedSet` type. +pub struct OrderedSet<T> { + map: OrderedMap<T>, +} + +impl<T: Hash + PhfHash + Eq + FmtConst> OrderedSet<T> { + /// Constructs a new `phf::OrderedSet` builder. + pub fn new() -> OrderedSet<T> { + OrderedSet { + map: OrderedMap::new(), + } + } + + /// Set the path to the `phf` crate from the global namespace + pub fn phf_path(&mut self, path: &str) -> &mut OrderedSet<T> { + self.map.phf_path(path); + self + } + + /// Adds an entry to the builder. + pub fn entry(&mut self, entry: T) -> &mut OrderedSet<T> { + self.map.entry(entry, "()"); + self + } + + /// Calculate the hash parameters and return a struct implementing + /// [`Display`](::std::fmt::Display) which will print the constructed + /// `phf::OrderedSet`. + /// + /// # Panics + /// + /// Panics if there are any duplicate keys. + pub fn build(&self) -> DisplayOrderedSet<'_, T> { + DisplayOrderedSet { + inner: self.map.build(), + } + } +} + +/// An adapter for printing a [`OrderedSet`](OrderedSet). +pub struct DisplayOrderedSet<'a, T> { + inner: DisplayOrderedMap<'a, T>, +} + +impl<'a, T: FmtConst + 'a> fmt::Display for DisplayOrderedSet<'a, T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!( + f, + "{}::OrderedSet {{ map: {} }}", + self.inner.path, self.inner + ) + } +} |