1use alux_shape::{FieldAlg, ShapeAlg, Sorts, Words};
8use serde::{Deserialize, Serialize};
9
10#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
12#[serde(rename_all = "camelCase")]
13pub enum Term {
14 Truth,
15 Unit,
16 Text,
17 Literal(String),
18 NameWord(Vec<String>),
19 Int { signed: bool, bits: u16 },
20 Float { bits: u16 },
21 Bytes { len: Option<usize> },
22 Hex(Box<Term>),
23 Decimal(Box<Term>),
24 Base64(Box<Term>),
25 Opt(Box<Term>),
26 Seq(Box<Term>),
27 Map(Box<Term>, Box<Term>),
28 Product(Vec<Member>),
29 Choice(Vec<Term>),
30 Named { words: Vec<String>, body: Box<Term> },
31 Reference(Vec<String>),
32}
33
34#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
36#[serde(rename_all = "camelCase")]
37pub enum Member {
38 Field { words: Vec<String>, shape: Term },
40 Merge(Term),
42}
43
44fn borrow(words: &[String]) -> Vec<&str> {
46 words.iter().map(String::as_str).collect()
47}
48
49fn own(words: Words<'_>) -> Vec<String> {
51 words.iter().map(|word| (*word).to_owned()).collect()
52}
53
54impl Term {
55 pub fn fold<A>(&self, alg: &A) -> A::Ty
61 where
62 A: ShapeAlg + FieldAlg,
63 {
64 match self {
65 Self::Truth => alg.truth(),
66 Self::Unit => alg.unit(),
67 Self::Text => alg.text(),
68 Self::Literal(text) => alg.literal(text),
69 Self::NameWord(words) => alg.name_word(&borrow(words)),
70 Self::Int { signed, bits } => alg.int(*signed, *bits),
71 Self::Float { bits } => alg.float(*bits),
72 Self::Bytes { len } => alg.bytes(*len),
73 Self::Hex(item) => alg.hex(item.fold(alg)),
74 Self::Decimal(item) => alg.decimal(item.fold(alg)),
75 Self::Base64(item) => alg.base64(item.fold(alg)),
76 Self::Opt(item) => alg.opt(item.fold(alg)),
77 Self::Seq(item) => alg.seq(item.fold(alg)),
78 Self::Map(key, value) => alg.map(key.fold(alg), value.fold(alg)),
79 Self::Product(members) => alg.product(members.iter().map(|member| member.fold(alg)).collect()),
80 Self::Choice(alternatives) => alg.choice(alternatives.iter().map(|item| item.fold(alg)).collect()),
81 Self::Named { words, body } => alg.named(&borrow(words), body.fold(alg)),
82 Self::Reference(words) => alg.reference(&borrow(words)),
83 }
84 }
85
86 #[must_use]
95 pub fn resolved(&self) -> Self {
96 let mut definitions = Vec::new();
97 self.definitions(&mut definitions);
98
99 self.expand(&definitions, &mut Vec::new())
100 }
101
102 fn definitions<'a>(&'a self, found: &mut Vec<(&'a [String], &'a Self)>) {
104 if let Self::Named { words, body } = self {
105 found.push((words, body));
106 }
107
108 self.children().for_each(|child| child.definitions(found));
109 }
110
111 fn expand(&self, definitions: &[(&[String], &Self)], expanding: &mut Vec<Vec<String>>) -> Self {
113 match self {
114 Self::Reference(words) => {
115 let known = definitions.iter().find(|(name, _)| *name == words.as_slice());
116
117 match known {
118 Some((_, body)) if !expanding.iter().any(|name| name == words) => {
119 expanding.push(words.clone());
120 let expanded = body.expand(definitions, expanding);
121 expanding.pop();
122
123 Self::Named { words: words.clone(), body: Box::new(expanded) }
124 }
125 _ => self.clone(),
126 }
127 }
128 Self::Hex(item) => Self::Hex(Box::new(item.expand(definitions, expanding))),
129 Self::Decimal(item) => Self::Decimal(Box::new(item.expand(definitions, expanding))),
130 Self::Base64(item) => Self::Base64(Box::new(item.expand(definitions, expanding))),
131 Self::Opt(item) => Self::Opt(Box::new(item.expand(definitions, expanding))),
132 Self::Seq(item) => Self::Seq(Box::new(item.expand(definitions, expanding))),
133 Self::Map(key, value) => {
134 Self::Map(Box::new(key.expand(definitions, expanding)), Box::new(value.expand(definitions, expanding)))
135 }
136 Self::Product(members) => {
137 Self::Product(members.iter().map(|member| member.expand(definitions, expanding)).collect())
138 }
139 Self::Choice(alternatives) => {
140 Self::Choice(alternatives.iter().map(|item| item.expand(definitions, expanding)).collect())
141 }
142 Self::Named { words, body } => {
143 expanding.push(words.clone());
144 let body = body.expand(definitions, expanding);
145 expanding.pop();
146
147 Self::Named { words: words.clone(), body: Box::new(body) }
148 }
149 leaf => leaf.clone(),
150 }
151 }
152
153 fn children(&self) -> Box<dyn Iterator<Item = &Self> + '_> {
155 match self {
156 Self::Hex(item)
157 | Self::Decimal(item)
158 | Self::Base64(item)
159 | Self::Opt(item)
160 | Self::Seq(item)
161 | Self::Named { body: item, .. } => Box::new(std::iter::once(&**item)),
162 Self::Map(key, value) => Box::new([&**key, &**value].into_iter()),
163 Self::Product(members) => Box::new(members.iter().map(Member::shape)),
164 Self::Choice(alternatives) => Box::new(alternatives.iter()),
165 _ => Box::new(std::iter::empty()),
166 }
167 }
168}
169
170impl Member {
171 fn shape(&self) -> &Term {
173 match self {
174 Self::Field { shape, .. } | Self::Merge(shape) => shape,
175 }
176 }
177
178 fn expand(&self, definitions: &[(&[String], &Term)], expanding: &mut Vec<Vec<String>>) -> Self {
180 match self {
181 Self::Field { words, shape } => {
182 Self::Field { words: words.clone(), shape: shape.expand(definitions, expanding) }
183 }
184 Self::Merge(shape) => Self::Merge(shape.expand(definitions, expanding)),
185 }
186 }
187
188 pub fn fold<A>(&self, alg: &A) -> A::Field
190 where
191 A: ShapeAlg + FieldAlg,
192 {
193 match self {
194 Self::Field { words, shape } => alg.field(&borrow(words), shape.fold(alg)),
195 Self::Merge(shape) => alg.merge(shape.fold(alg)),
196 }
197 }
198}
199
200#[derive(Debug, Clone, Copy, Default)]
202pub struct TermShape;
203
204impl Sorts for TermShape {
205 type Ty = Term;
206 type Field = Member;
207}
208
209impl ShapeAlg for TermShape {
210 fn truth(&self) -> Term {
211 Term::Truth
212 }
213
214 fn unit(&self) -> Term {
215 Term::Unit
216 }
217
218 fn text(&self) -> Term {
219 Term::Text
220 }
221
222 fn literal(&self, text: &str) -> Term {
223 Term::Literal(text.to_owned())
224 }
225
226 fn name_word(&self, words: Words<'_>) -> Term {
227 Term::NameWord(own(words))
228 }
229
230 fn int(&self, signed: bool, bits: u16) -> Term {
231 Term::Int { signed, bits }
232 }
233
234 fn float(&self, bits: u16) -> Term {
235 Term::Float { bits }
236 }
237
238 fn bytes(&self, len: Option<usize>) -> Term {
239 Term::Bytes { len }
240 }
241
242 fn hex(&self, item: Term) -> Term {
243 Term::Hex(Box::new(item))
244 }
245
246 fn decimal(&self, item: Term) -> Term {
247 Term::Decimal(Box::new(item))
248 }
249
250 fn base64(&self, item: Term) -> Term {
251 Term::Base64(Box::new(item))
252 }
253
254 fn opt(&self, item: Term) -> Term {
255 Term::Opt(Box::new(item))
256 }
257
258 fn seq(&self, item: Term) -> Term {
259 Term::Seq(Box::new(item))
260 }
261
262 fn map(&self, key: Term, value: Term) -> Term {
263 Term::Map(Box::new(key), Box::new(value))
264 }
265
266 fn product(&self, fields: Vec<Member>) -> Term {
267 Term::Product(fields)
268 }
269
270 fn choice(&self, alternatives: Vec<Term>) -> Term {
271 Term::Choice(alternatives)
272 }
273
274 fn named(&self, words: Words<'_>, body: Term) -> Term {
275 Term::Named { words: own(words), body: Box::new(body) }
276 }
277
278 fn reference(&self, words: Words<'_>) -> Term {
279 Term::Reference(own(words))
280 }
281}
282
283impl FieldAlg for TermShape {
284 fn field(&self, words: Words<'_>, shape: Term) -> Member {
285 Member::Field { words: own(words), shape }
286 }
287
288 fn merge(&self, shape: Term) -> Member {
289 Member::Merge(shape)
290 }
291}