extern crate phf_generator;
use std::collections::HashSet;
use std::fs::File;
use std::io::{self, Write, BufWriter};
use std::path::Path;
#[allow(dead_code)]
mod shared;
pub struct AtomType {
path: String,
macro_name: String,
atoms: HashSet<String>,
}
impl AtomType {
pub fn new(path: &str, macro_name: &str) -> Self {
assert!(macro_name.ends_with("!"));
AtomType {
path: path.to_owned(),
macro_name: macro_name[..macro_name.len() - "!".len()].to_owned(),
atoms: HashSet::new(),
}
}
pub fn atom(&mut self, s: &str) -> &mut Self {
self.atoms.insert(s.to_owned());
self
}
pub fn atoms<I>(&mut self, iter: I) -> &mut Self
where I: IntoIterator, I::Item: AsRef<str> {
self.atoms.extend(iter.into_iter().map(|s| s.as_ref().to_owned()));
self
}
pub fn write_to<W>(&mut self, mut destination: W) -> io::Result<()> where W: Write {
self.atoms.insert(String::new());
let atoms: Vec<&str> = self.atoms.iter().map(|s| &**s).collect();
let hash_state = phf_generator::generate_hash(&atoms);
let atoms: Vec<&str> = hash_state.map.iter().map(|&idx| atoms[idx]).collect();
let empty_string_index = atoms.iter().position(|s| s.is_empty()).unwrap();
let type_name = if let Some(position) = self.path.rfind("::") {
&self.path[position + "::".len() ..]
} else {
&self.path
};
macro_rules! w {
($($arg: expr),+) => { try!(writeln!(destination, $($arg),+)) }
}
w!("pub type {} = ::string_cache::Atom<{}StaticSet>;", type_name, type_name);
w!("pub struct {}StaticSet;", type_name);
w!("impl ::string_cache::StaticAtomSet for {}StaticSet {{", type_name);
w!(" fn get() -> &'static ::string_cache::PhfStrSet {{");
w!(" static SET: ::string_cache::PhfStrSet = ::string_cache::PhfStrSet {{");
w!(" key: {},", hash_state.key);
w!(" disps: &{:?},", hash_state.disps);
w!(" atoms: &{:#?},", atoms);
w!(" }};");
w!(" &SET");
w!(" }}");
w!(" fn empty_string_index() -> u32 {{");
w!(" {}", empty_string_index);
w!(" }}");
w!("}}");
w!("#[macro_export]");
w!("macro_rules! {} {{", self.macro_name);
for (i, atom) in atoms.iter().enumerate() {
w!("({:?}) => {{ $crate::{} {{ unsafe_data: 0x{:x}, phantom: ::std::marker::PhantomData }} }};",
atom,
self.path,
shared::pack_static(i as u32)
);
}
w!("}}");
Ok(())
}
pub fn write_to_file(&mut self, path: &Path) -> io::Result<()> {
self.write_to(BufWriter::new(try!(File::create(path))))
}
}