|
9 | 9 |
|
10 | 10 | extern crate phf_generator; |
11 | 11 | extern crate string_cache_shared as shared; |
| 12 | +#[macro_use] extern crate quote; |
12 | 13 |
|
13 | 14 | use std::collections::HashSet; |
14 | 15 | use std::fs::File; |
15 | 16 | use std::io::{self, Write, BufWriter}; |
| 17 | +use std::iter; |
16 | 18 | use std::path::Path; |
17 | 19 |
|
18 | 20 | /// A builder for a static atom set and relevant macros |
@@ -67,52 +69,68 @@ impl AtomType { |
67 | 69 |
|
68 | 70 | /// Write generated code to `destination`. |
69 | 71 | pub fn write_to<W>(&mut self, mut destination: W) -> io::Result<()> where W: Write { |
| 72 | + destination.write_all( |
| 73 | + self.to_tokens() |
| 74 | + .as_str() |
| 75 | + // Insert some newlines to make the generated code slightly easier to read. |
| 76 | + .replace(" [ \"", "[\n\"") |
| 77 | + .replace("\" , ", "\",\n") |
| 78 | + .replace(" ( \"", "\n( \"") |
| 79 | + .replace("; ", ";\n") |
| 80 | + .as_bytes()) |
| 81 | + } |
| 82 | + |
| 83 | + fn to_tokens(&mut self) -> quote::Tokens { |
70 | 84 | // `impl Default for Atom` requires the empty string to be in the static set. |
71 | 85 | // This also makes sure the set in non-empty, |
72 | 86 | // which would cause divisions by zero in rust-phf. |
73 | 87 | self.atoms.insert(String::new()); |
74 | 88 |
|
75 | 89 | let atoms: Vec<&str> = self.atoms.iter().map(|s| &**s).collect(); |
76 | 90 | let hash_state = phf_generator::generate_hash(&atoms); |
77 | | - let atoms: Vec<&str> = hash_state.map.iter().map(|&idx| atoms[idx]).collect(); |
78 | | - let empty_string_index = atoms.iter().position(|s| s.is_empty()).unwrap(); |
| 91 | + let phf_generator::HashState { key, disps, map } = hash_state; |
| 92 | + let atoms: Vec<&str> = map.iter().map(|&idx| atoms[idx]).collect(); |
| 93 | + let empty_string_index = atoms.iter().position(|s| s.is_empty()).unwrap() as u32; |
| 94 | + let data = (0..atoms.len()).map(|i| quote::Hex(shared::pack_static(i as u32))); |
79 | 95 |
|
80 | 96 | let type_name = if let Some(position) = self.path.rfind("::") { |
81 | 97 | &self.path[position + "::".len() ..] |
82 | 98 | } else { |
83 | 99 | &self.path |
84 | 100 | }; |
| 101 | + let static_set_name = quote::Ident::from(format!("{}StaticSet", type_name)); |
| 102 | + let type_name = quote::Ident::from(type_name); |
| 103 | + let macro_name = quote::Ident::from(&*self.macro_name); |
| 104 | + let path = iter::repeat(quote::Ident::from(&*self.path)); |
85 | 105 |
|
86 | | - macro_rules! w { |
87 | | - ($($arg: expr),+) => { try!(writeln!(destination, $($arg),+)) } |
88 | | - } |
89 | | - |
90 | | - w!("pub type {} = ::string_cache::Atom<{}StaticSet>;", type_name, type_name); |
91 | | - w!("pub struct {}StaticSet;", type_name); |
92 | | - w!("impl ::string_cache::StaticAtomSet for {}StaticSet {{", type_name); |
93 | | - w!(" fn get() -> &'static ::string_cache::PhfStrSet {{"); |
94 | | - w!(" static SET: ::string_cache::PhfStrSet = ::string_cache::PhfStrSet {{"); |
95 | | - w!(" key: {},", hash_state.key); |
96 | | - w!(" disps: &{:?},", hash_state.disps); |
97 | | - w!(" atoms: &{:#?},", atoms); |
98 | | - w!(" }};"); |
99 | | - w!(" &SET"); |
100 | | - w!(" }}"); |
101 | | - w!(" fn empty_string_index() -> u32 {{"); |
102 | | - w!(" {}", empty_string_index); |
103 | | - w!(" }}"); |
104 | | - w!("}}"); |
105 | | - w!("#[macro_export]"); |
106 | | - w!("macro_rules! {} {{", self.macro_name); |
107 | | - for (i, atom) in atoms.iter().enumerate() { |
108 | | - w!("({:?}) => {{ $crate::{} {{ unsafe_data: 0x{:x}, phantom: ::std::marker::PhantomData }} }};", |
109 | | - atom, |
110 | | - self.path, |
111 | | - shared::pack_static(i as u32) |
112 | | - ); |
| 106 | + quote! { |
| 107 | + pub type #type_name = ::string_cache::Atom<#static_set_name>; |
| 108 | + pub struct #static_set_name; |
| 109 | + impl ::string_cache::StaticAtomSet for #static_set_name { |
| 110 | + fn get() -> &'static ::string_cache::PhfStrSet { |
| 111 | + static SET: ::string_cache::PhfStrSet = ::string_cache::PhfStrSet { |
| 112 | + key: #key, |
| 113 | + disps: &#disps, |
| 114 | + atoms: &#atoms, |
| 115 | + }; |
| 116 | + &SET |
| 117 | + } |
| 118 | + fn empty_string_index() -> u32 { |
| 119 | + #empty_string_index |
| 120 | + } |
| 121 | + } |
| 122 | + #[macro_export] |
| 123 | + macro_rules! #macro_name { |
| 124 | + #( |
| 125 | + (#atoms) => { |
| 126 | + $crate::#path { |
| 127 | + unsafe_data: #data, |
| 128 | + phantom: ::std::marker::PhantomData, |
| 129 | + } |
| 130 | + }; |
| 131 | + )* |
| 132 | + } |
113 | 133 | } |
114 | | - w!("}}"); |
115 | | - Ok(()) |
116 | 134 | } |
117 | 135 |
|
118 | 136 | /// Create a new file at `path` and write generated code there. |
|
0 commit comments