1#![no_std]
42#![forbid(
43 unsafe_code,
44 missing_docs,
45 missing_debug_implementations,
46 missing_copy_implementations,
47 trivial_casts,
48 trivial_numeric_casts,
49 unused_import_braces,
50 unused_qualifications,
51 future_incompatible,
52 rust_2018_idioms
53)]
54
55extern crate alloc;
56
57use alloc::string::String;
58use core::fmt::{self, Write};
59use core::{write, writeln};
60
61use intern_str::{CaseInsensitive, Graph, Segmentable};
62
63pub fn generate<Input: Key, Output>(
67 graph: &Graph<'_, '_, Input, Output>,
68 input_type: &str,
69 output_type: &str,
70 mut write_output: impl FnMut(&mut dyn Write, &Output) -> fmt::Result,
71) -> String {
72 let mut out = String::new();
73
74 writeln!(out, "{{").ok();
75
76 writeln!(
78 out,
79 "{}const NODES: &[intern_str::Node<'static, {}, {}>] = &[",
80 Indent(4),
81 input_type,
82 output_type
83 )
84 .ok();
85
86 for node in graph.nodes().iter() {
87 writeln!(out, "{}intern_str::Node::new(", Indent(8)).ok();
88
89 writeln!(out, "{}&[", Indent(12)).ok();
90
91 for (input, next) in node.inputs() {
92 writeln!(
93 out,
94 "{}({}, {}),",
95 Indent(16),
96 WriteKey(input),
97 next
98 )
99 .ok();
100 }
101
102 writeln!(out, "{}],", Indent(12)).ok();
103
104 write!(out, "{}", Indent(12)).ok();
105 write_output(&mut out, node.output()).ok();
106 writeln!(out, ",").ok();
107
108 writeln!(out, "{}{},", Indent(12), node.default(),).ok();
109
110 writeln!(out, "{}{},", Indent(12), Index(node.amount()),).ok();
111
112 writeln!(out, "{}),", Indent(8)).ok();
113 }
114
115 writeln!(out, "{}];", Indent(4)).ok();
116
117 writeln!(
119 out,
120 "{}const GRAPH: intern_str::Graph<'static, 'static, {}, {}> = intern_str::Graph::new(NODES, {});",
121 Indent(4),
122 input_type,
123 output_type,
124 graph.start(),
125 ).ok();
126
127 writeln!(out, "{}GRAPH", Indent(4)).ok();
128
129 writeln!(out, "}}").ok();
130
131 out
132}
133
134pub trait Key: Segmentable {
136 fn format(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result;
138}
139
140impl<'a> Key for &'a str {
141 fn format(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
142 write!(f, "\"{}\"", self)
143 }
144}
145
146impl<'a, T: fmt::Debug + Ord> Key for &'a [T] {
147 fn format(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
148 write!(f, "&[")?;
149
150 for (i, item) in self.iter().enumerate() {
151 if i != 0 {
152 write!(f, ", ")?;
153 }
154
155 write!(f, "{:?}", item)?;
156 }
157
158 write!(f, "]")
159 }
160}
161
162impl<T: AsRef<[u8]> + Key> Key for CaseInsensitive<T> {
163 fn format(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
164 write!(f, "intern_str::CaseInsensitive({})", WriteKey(&self.0))
165 }
166}
167
168struct WriteKey<'a, T>(&'a T);
169
170impl<'a, T: Key> fmt::Display for WriteKey<'a, T> {
171 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
172 self.0.format(f)
173 }
174}
175
176struct Indent(usize);
177
178impl fmt::Display for Indent {
179 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
180 for _ in 0..self.0 {
181 write!(f, " ")?;
182 }
183
184 Ok(())
185 }
186}
187
188struct Index(usize);
189
190impl fmt::Display for Index {
191 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
192 if self.0 == core::usize::MAX {
193 f.write_str("core::usize::MAX")
194 } else {
195 fmt::Display::fmt(&self.0, f)
196 }
197 }
198}