1#![deny(warnings)]
2
3use std::collections::HashMap;
4use std::error;
5use std::fmt;
6use std::io::Write;
7use std::result;
8use std::str;
9
10use heck::SnakeCase;
11use itertools::Itertools;
12
13type Result<T> = result::Result<T, Box<error::Error>>;
14
15struct ByteStrDisplay<'a>(&'a [u8]);
16
17impl<'a> fmt::Display for ByteStrDisplay<'a> {
18 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
19 if let Ok(s) = str::from_utf8(self.0) {
20 write!(f, "b{:?}", s)
21 } else {
22 write!(f, "&[{}]", itertools::join(self.0, ", "))
23 }
24 }
25}
26
27fn generate_inner<W: Write>(writer: &mut W, lower_name: &str, atoms: Vec<(&[u8], &str)>) -> Result<()> {
28 for (_prefix_byte, atoms) in &atoms.into_iter().group_by(|&(s, _)| s[0]) {
29 let mut atoms = atoms.collect_vec();
30 let mut prefix = Vec::new();
31
32 let s = loop {
33 let &(bytes, s) = atoms.first().unwrap();
34
35 let prefix_byte = if let Some(&b) = bytes.first() {
36 b
37 } else {
38 break Some(s);
39 };
40
41 if atoms.iter().all(|(s, _)| s[0] == prefix_byte) {
42 prefix.push(prefix_byte);
43 for (s, _) in atoms.iter_mut() {
44 *s = &s[1..];
45 }
46 } else {
47 break None;
48 }
49 };
50
51 writeln!(
52 writer,
53 "if let Some(s) = s.expect({prefix}) {{",
54 prefix = ByteStrDisplay(&prefix[..])
55 )?;
56
57 if let Some(s) = s {
58 write!(writer, "Ok({lower_name}!({s:?}))", lower_name = lower_name, s = s)?;
59 } else {
60 generate_inner(writer, lower_name, atoms)?;
61 }
62
63 write!(writer, "}} else ")?;
64 }
65
66 writeln!(writer, "{{ Err(()) }}")?;
67 Ok(())
68}
69
70pub fn generate<W: Write>(
71 mut writer: W,
72 mod_name: &str,
73 name: &str,
74 atoms: Vec<&str>,
75 visitors: Vec<&str>,
76) -> Result<()> {
77 let mod_name = if mod_name.is_empty() {
78 String::new()
79 } else {
80 mod_name.to_owned() + "::"
81 };
82
83 let lower_name = name.to_snake_case();
84 let visitors = visitors
85 .into_iter()
86 .map(|visitor| (visitor, visitor.to_snake_case()))
87 .collect_vec();
88
89 let mut by_len = HashMap::new();
90 for &s in atoms.iter() {
91 let bytes = s.as_bytes();
92 by_len.entry(bytes.len()).or_insert_with(Vec::new).push((bytes, s));
93 }
94
95 writeln!(
96 writer,
97 "\
98 #[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
99 pub enum {name} {{",
100 name = name
101 )?;
102
103 for (index, &s) in atoms.iter().enumerate() {
104 writeln!(writer, "_{index}, // {s:?}", index = index, s = s)?;
105 }
106
107 writeln!(
108 writer,
109 "\
110 }}
111
112 #[doc(hide)]
113 pub mod _{lower_name}_types {{",
114 lower_name = lower_name
115 )?;
116
117 for (index, &s) in atoms.iter().enumerate() {
118 writeln!(
119 writer,
120 "\
121 #[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
122 pub struct _{index}; // {s:?}",
123 index = index,
124 s = s
125 )?;
126 }
127
128 writeln!(
129 writer,
130 "\
131 }}
132
133 #[macro_export]
134 macro_rules! {lower_name} {{",
135 lower_name = lower_name
136 )?;
137 for (index, &s) in atoms.iter().enumerate() {
138 writeln!(
139 writer,
140 "({s:?}) => {{ $crate::{mod_name}{name}::_{index} }};",
141 mod_name = mod_name,
142 name = name,
143 index = index,
144 s = s
145 )?;
146 }
147
148 writeln!(
149 writer,
150 "\
151 }}
152
153 #[macro_export]
154 macro_rules! {lower_name}_type {{",
155 lower_name = lower_name
156 )?;
157
158 for (index, &s) in atoms.iter().enumerate() {
159 writeln!(
160 writer,
161 "({s:?}) => {{ $crate::{mod_name}_{lower_name}_types::_{index} }};",
162 mod_name = mod_name,
163 lower_name = lower_name,
164 index = index,
165 s = s
166 )?;
167 }
168
169 writeln!(
170 writer,
171 "\
172 }}
173
174 impl ::std::str::FromStr for {name} {{
175 type Err = ();
176
177 #[allow(unused_variables)]
178 fn from_str(s: &str) -> ::std::result::Result<Self, ()> {{
179 use ::static_atom::Expect;
180
181 let s = s.as_bytes();
182 match s.len() {{",
183 name = name
184 )?;
185
186 for (len, mut atoms) in by_len.into_iter().sorted_by_key(|&(len, _)| len) {
187 writeln!(writer, "{len} => {{", len = len)?;
188 atoms.sort_by_key(|&(bytes, _)| bytes);
189 generate_inner(&mut writer, &lower_name, atoms)?;
190 writeln!(writer, "}}")?;
191 }
192
193 writeln!(
194 writer,
195 "\
196 _ => Err(())
197 }}
198 }}
199 }}
200
201 impl {name} {{
202 pub fn as_str(&self) -> &'static str {{
203 match self {{",
204 name = name
205 )?;
206
207 for &s in atoms.iter() {
208 writeln!(writer, "{lower_name}!({s:?}) => {s:?},", lower_name = lower_name, s = s)?;
209 }
210
211 writeln!(
212 writer,
213 "\
214 }}
215 }}"
216 )?;
217
218 for &(visitor, ref lower_visitor) in visitors.iter() {
219 writeln!(
220 writer,
221 "\
222 pub fn visit_{lower_visitor}<V: {visitor}Visitor>(self, visitor: V) -> V::Value {{
223 match self {{",
224 visitor = visitor,
225 lower_visitor = lower_visitor,
226 )?;
227
228 for s in atoms.iter() {
229 writeln!(
230 writer,
231 "{lower_name}!({s:?}) => visitor.visit::<{lower_name}_type!({s:?})>(),",
232 lower_name = lower_name,
233 s = s,
234 )?;
235 }
236
237 writeln!(
238 writer,
239 "\
240 }}
241 }}"
242 )?;
243 }
244
245 writeln!(
246 writer,
247 "\
248 }}
249
250 impl From<{name}> for usize {{
251 fn from(token: {name}) -> Self {{
252 match token {{",
253 name = name
254 )?;
255
256 for (index, &s) in atoms.iter().enumerate() {
257 writeln!(
258 writer,
259 "{lower_name}!({s:?}) => {index},",
260 lower_name = lower_name,
261 index = index,
262 s = s
263 )?;
264 }
265
266 writeln!(
267 writer,
268 "\
269 }}
270 }}
271 }}
272
273 impl ::static_atom::TryFrom<usize> for {name} {{
274 type Err = ();
275
276 fn try_from(n: usize) -> Result<Self, ()> {{
277 match n {{",
278 name = name
279 )?;
280
281 for (index, &s) in atoms.iter().enumerate() {
282 writeln!(
283 writer,
284 "{index} => Ok({lower_name}!({s:?})),",
285 lower_name = lower_name,
286 index = index,
287 s = s
288 )?;
289 }
290
291 writeln!(
292 writer,
293 "\
294 _ => Err(()),
295 }}
296 }}
297 }}"
298 )?;
299
300 #[cfg(feature = "serde")]
301 {
302 writeln!(
303 writer,
304 "\
305 impl ::serde::Serialize for {name} {{
306 fn serialize<S: ::serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {{
307 self.as_str().serialize(serializer)
308 }}
309 }}
310
311 impl<'de> ::serde::Deserialize<'de> for {name} {{
312 fn deserialize<D: ::serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {{
313 use serde::de::Error;
314
315 <&str>::deserialize(deserializer).and_then(|s| {{
316 s.parse().map_err(|()| Error::custom(format!(\"can't parse {{}} as {name}\", s)))
317 }})
318 }}
319 }}",
320 name = name
321 )?;
322 }
323
324 let where_mapping = atoms
325 .iter()
326 .map(|&s| {
327 format!(
328 "M: ::static_atom::Mapping<{lower_name}_type!({s:?})>",
329 lower_name = lower_name,
330 s = s
331 )
332 })
333 .join("\n,");
334
335 writeln!(
336 writer,
337 "\
338 impl ::std::fmt::Debug for {name} {{
339 fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {{
340 write!(f, \"{lower_name}!({{}})\", self.as_str())
341 }}
342 }}
343
344 impl ::std::fmt::Display for {name} {{
345 fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {{
346 f.write_str(self.as_str())
347 }}
348 }}
349
350 #[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
351 pub struct {name}Map<T>([Option<T>; {len}]);
352
353 impl<T> {name}Map<T> {{
354 pub fn new() -> Self {{
355 {name}Map(Default::default())
356 }}
357 }}
358
359 impl<T> ::static_atom::AtomMap for {name}Map<T> {{
360 type Key = {name};
361 type Value = T;
362
363 fn entry(&self, key: {name}) -> &Option<T> {{
364 &self.0[usize::from(key)]
365 }}
366
367 fn entry_mut(&mut self, key: {name}) -> &mut Option<T> {{
368 &mut self.0[usize::from(key)]
369 }}
370
371 fn entries(&self) -> &[Option<T>] {{
372 &self.0
373 }}
374
375 fn entries_mut(&mut self) -> &mut [Option<T>] {{
376 &mut self.0
377 }}
378 }}
379
380 impl<T> ::std::iter::FromIterator<({name}, T)> for {name}Map<T> {{
381 fn from_iter<I: ::std::iter::IntoIterator<Item = ({name}, T)>>(iter: I) -> Self {{
382 let mut map = {name}Map::new();
383 for (key, value) in iter {{
384 map.0[usize::from(key)] = Some(value);
385 }}
386
387 map
388 }}
389 }}
390
391 pub struct Typed{name}Map<M>
392 where {where_mapping}
393 {{",
394 lower_name = lower_name,
395 name = name,
396 len = atoms.len(),
397 where_mapping = where_mapping
398 )?;
399
400 for (index, &s) in atoms.iter().enumerate() {
401 writeln!(
402 writer,
403 "_{index}: Option<<M as ::static_atom::Mapping<{lower_name}_type!({s:?})>>::Value>,",
404 index = index,
405 lower_name = lower_name,
406 s = s
407 )?;
408 }
409
410 writeln!(
411 writer,
412 "\
413 }}
414
415 impl<M> Typed{name}Map<M>
416 where {where_mapping}
417 {{
418 pub fn new() -> Self {{
419 Typed{name}Map {{",
420 name = name,
421 where_mapping = where_mapping
422 )?;
423
424 for (index, &s) in atoms.iter().enumerate() {
425 writeln!(writer, "_{index}: None, // {s:?}", index = index, s = s)?;
426 }
427
428 writeln!(
429 writer,
430 "\
431 }}
432 }}
433 }}
434
435 impl<M> ::static_atom::TypedAtomMap<M> for Typed{name}Map<M>
436 where {where_mapping}
437 {{
438 fn entry<A>(&self) -> &Option<<M as ::static_atom::Mapping<A>>::Value>
439 where
440 M: ::static_atom::Mapping<A>,
441 A: 'static,
442 {{
443 use std::any::TypeId;
444 use std::mem;
445
446 let id = TypeId::of::<A>();",
447 name = name,
448 where_mapping = where_mapping
449 )?;
450
451 for (index, &s) in atoms.iter().enumerate() {
452 write!(
453 writer,
454 "\
455 if id == TypeId::of::<{lower_name}_type!({s:?})>() {{
456 unsafe {{ mem::transmute(&self._{index}) }}
457 }} else ",
458 lower_name = lower_name,
459 index = index,
460 s = s
461 )?;
462 }
463
464 writeln!(
465 writer,
466 "\
467 {{
468 unreachable!()
469 }}
470 }}
471
472 fn entry_mut<A>(&mut self) -> &mut Option<<M as ::static_atom::Mapping<A>>::Value>
473 where
474 M: ::static_atom::Mapping<A>,
475 A: 'static,
476 {{
477 use std::any::TypeId;
478 use std::mem;
479
480 let id = TypeId::of::<A>();"
481 )?;
482
483 for (index, &s) in atoms.iter().enumerate() {
484 write!(
485 writer,
486 "\
487 if id == TypeId::of::<{lower_name}_type!({s:?})>() {{
488 unsafe {{ mem::transmute(&mut self._{index}) }}
489 }} else ",
490 lower_name = lower_name,
491 index = index,
492 s = s
493 )?;
494 }
495
496 writeln!(
497 writer,
498 "\
499 {{
500 unreachable!()
501 }}
502 }}
503 }}"
504 )?;
505
506 Ok(())
507}