1use alloc::borrow::Cow;
6use alloc::vec::Vec;
7
8#[derive(Clone, PartialEq, Eq, Hash, Debug)]
12#[non_exhaustive]
13pub enum Expression<'a> {
14 Literal(LiteralExpression<'a>),
16 Variable(VariableExpression<'a>),
18 Function(FunctionExpression<'a>),
20}
21
22#[derive(Clone, PartialEq, Eq, Hash, Debug)]
24pub struct LiteralExpression<'a> {
25 pub arg: Literal<'a>,
27 pub function: Option<FunctionRef<'a>>,
29 pub attributes: Attributes<'a>,
31}
32
33#[derive(Clone, PartialEq, Eq, Hash, Debug)]
35pub struct VariableExpression<'a> {
36 pub arg: VariableRef<'a>,
38 pub function: Option<FunctionRef<'a>>,
40 pub attributes: Attributes<'a>,
42}
43
44#[derive(Clone, PartialEq, Eq, Hash, Debug)]
46pub struct FunctionExpression<'a> {
47 pub function: FunctionRef<'a>,
49 pub attributes: Attributes<'a>,
51}
52
53impl<'a> Expression<'a> {
54 pub fn function(&self) -> Option<&FunctionRef<'a>> {
56 match self {
57 Expression::Literal(e) => e.function.as_ref(),
58 Expression::Variable(e) => e.function.as_ref(),
59 Expression::Function(e) => Some(&e.function),
60 }
61 }
62
63 pub fn attributes(&self) -> &Attributes<'a> {
65 match self {
66 Expression::Literal(e) => &e.attributes,
67 Expression::Variable(e) => &e.attributes,
68 Expression::Function(e) => &e.attributes,
69 }
70 }
71
72 pub fn into_owned(self) -> Expression<'static> {
74 match self {
75 Expression::Literal(e) => Expression::Literal(e.into_owned()),
76 Expression::Variable(e) => Expression::Variable(e.into_owned()),
77 Expression::Function(e) => Expression::Function(e.into_owned()),
78 }
79 }
80}
81
82impl LiteralExpression<'_> {
83 pub fn into_owned(self) -> LiteralExpression<'static> {
85 LiteralExpression {
86 arg: self.arg.into_owned(),
87 function: self.function.map(FunctionRef::into_owned),
88 attributes: self.attributes.into_owned(),
89 }
90 }
91}
92
93impl VariableExpression<'_> {
94 pub fn into_owned(self) -> VariableExpression<'static> {
96 VariableExpression {
97 arg: self.arg.into_owned(),
98 function: self.function.map(FunctionRef::into_owned),
99 attributes: self.attributes.into_owned(),
100 }
101 }
102}
103
104impl FunctionExpression<'_> {
105 pub fn into_owned(self) -> FunctionExpression<'static> {
107 FunctionExpression {
108 function: self.function.into_owned(),
109 attributes: self.attributes.into_owned(),
110 }
111 }
112}
113
114fn own(s: Cow<'_, str>) -> Cow<'static, str> {
115 Cow::Owned(s.into_owned())
116}
117
118#[derive(Clone, PartialEq, Eq, Hash, Debug)]
121pub struct Literal<'a> {
122 pub value: Cow<'a, str>,
124}
125
126impl Literal<'_> {
127 pub fn into_owned(self) -> Literal<'static> {
129 Literal {
130 value: own(self.value),
131 }
132 }
133}
134
135#[derive(Clone, PartialEq, Eq, Hash, Debug)]
137pub struct VariableRef<'a> {
138 pub name: Cow<'a, str>,
140}
141
142impl VariableRef<'_> {
143 pub fn into_owned(self) -> VariableRef<'static> {
145 VariableRef {
146 name: own(self.name),
147 }
148 }
149}
150
151#[derive(Clone, PartialEq, Eq, Hash, Debug)]
153pub struct FunctionRef<'a> {
154 pub name: Cow<'a, str>,
156 pub options: Options<'a>,
158}
159
160impl FunctionRef<'_> {
161 pub fn into_owned(self) -> FunctionRef<'static> {
163 FunctionRef {
164 name: own(self.name),
165 options: self.options.into_owned(),
166 }
167 }
168}
169
170#[derive(Clone, PartialEq, Eq, Hash, Debug)]
172#[non_exhaustive]
175pub enum OptionValue<'a> {
176 Literal(Literal<'a>),
178 Variable(VariableRef<'a>),
180}
181
182impl OptionValue<'_> {
183 pub fn into_owned(self) -> OptionValue<'static> {
185 match self {
186 OptionValue::Literal(l) => OptionValue::Literal(l.into_owned()),
187 OptionValue::Variable(v) => OptionValue::Variable(v.into_owned()),
188 }
189 }
190}
191
192#[derive(Clone, Default, PartialEq, Eq, Hash, Debug)]
197pub struct Options<'a>(pub(crate) Vec<(Cow<'a, str>, OptionValue<'a>)>);
198
199impl<'a> Options<'a> {
200 pub const fn new() -> Self {
202 Options(Vec::new())
203 }
204
205 pub fn with_capacity(capacity: usize) -> Self {
207 Options(Vec::with_capacity(capacity))
208 }
209
210 pub fn push(&mut self, name: Cow<'a, str>, value: OptionValue<'a>) {
212 self.0.push((name, value));
213 }
214
215 pub fn iter(&self) -> impl Iterator<Item = (&str, &OptionValue<'a>)> {
217 self.0.iter().map(|(k, v)| (k.as_ref(), v))
218 }
219
220 pub fn get(&self, name: &str) -> Option<&OptionValue<'a>> {
222 self.0.iter().find(|(k, _)| k == name).map(|(_, v)| v)
223 }
224
225 pub fn len(&self) -> usize {
227 self.0.len()
228 }
229
230 pub fn is_empty(&self) -> bool {
232 self.0.is_empty()
233 }
234
235 pub fn into_owned(self) -> Options<'static> {
237 Options(
238 self.0
239 .into_iter()
240 .map(|(k, v)| (own(k), v.into_owned()))
241 .collect(),
242 )
243 }
244}
245
246impl<'a> FromIterator<(Cow<'a, str>, OptionValue<'a>)> for Options<'a> {
247 fn from_iter<I: IntoIterator<Item = (Cow<'a, str>, OptionValue<'a>)>>(iter: I) -> Self {
248 Options(iter.into_iter().collect())
249 }
250}
251
252#[derive(Clone, PartialEq, Eq, Hash, Debug)]
254pub struct Markup<'a> {
255 pub kind: MarkupKind,
257 pub name: Cow<'a, str>,
259 pub options: Options<'a>,
261 pub attributes: Attributes<'a>,
263}
264
265impl Markup<'_> {
266 pub fn into_owned(self) -> Markup<'static> {
268 Markup {
269 kind: self.kind,
270 name: own(self.name),
271 options: self.options.into_owned(),
272 attributes: self.attributes.into_owned(),
273 }
274 }
275}
276
277#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
279pub enum MarkupKind {
280 Open,
282 Standalone,
284 Close,
286}
287
288#[derive(Clone, Default, PartialEq, Eq, Hash, Debug)]
291pub struct Attributes<'a>(pub(crate) Vec<(Cow<'a, str>, Option<Literal<'a>>)>);
292
293impl<'a> Attributes<'a> {
294 pub const fn new() -> Self {
296 Attributes(Vec::new())
297 }
298
299 pub fn with_capacity(capacity: usize) -> Self {
301 Attributes(Vec::with_capacity(capacity))
302 }
303
304 pub fn push(&mut self, name: Cow<'a, str>, value: Option<Literal<'a>>) {
306 self.0.push((name, value));
307 }
308
309 pub fn iter(&self) -> impl Iterator<Item = (&str, Option<&Literal<'a>>)> {
311 self.0.iter().map(|(k, v)| (k.as_ref(), v.as_ref()))
312 }
313
314 pub fn get(&self, name: &str) -> Option<Option<&Literal<'a>>> {
318 self.0
319 .iter()
320 .rfind(|(k, _)| k == name)
321 .map(|(_, v)| v.as_ref())
322 }
323
324 pub fn len(&self) -> usize {
326 self.0.len()
327 }
328
329 pub fn is_empty(&self) -> bool {
331 self.0.is_empty()
332 }
333
334 pub fn into_owned(self) -> Attributes<'static> {
336 Attributes(
337 self.0
338 .into_iter()
339 .map(|(k, v)| (own(k), v.map(Literal::into_owned)))
340 .collect(),
341 )
342 }
343}
344
345impl<'a> FromIterator<(Cow<'a, str>, Option<Literal<'a>>)> for Attributes<'a> {
346 fn from_iter<I: IntoIterator<Item = (Cow<'a, str>, Option<Literal<'a>>)>>(iter: I) -> Self {
347 Attributes(iter.into_iter().collect())
348 }
349}
350
351pub fn split_identifier(identifier: &str) -> (Option<&str>, &str) {
355 match identifier.split_once(':') {
356 Some((ns, name)) => (Some(ns), name),
357 None => (None, identifier),
358 }
359}
360
361#[cfg(test)]
362mod tests {
363 use alloc::borrow::Cow;
364
365 use super::{
366 Attributes, Expression, FunctionExpression, FunctionRef, Literal, OptionValue, Options,
367 VariableExpression, VariableRef, split_identifier,
368 };
369
370 fn lit(s: &str) -> Literal<'_> {
371 Literal {
372 value: Cow::Borrowed(s),
373 }
374 }
375
376 #[test]
377 fn options_keep_order_and_duplicates() {
378 let mut o = Options::new();
379 assert!(o.is_empty());
380 o.push("b".into(), OptionValue::Literal(lit("1")));
381 o.push(
382 "a".into(),
383 OptionValue::Variable(VariableRef { name: "x".into() }),
384 );
385 o.push("b".into(), OptionValue::Literal(lit("2")));
386 assert_eq!(o.len(), 3);
387 let names: alloc::vec::Vec<&str> = o.iter().map(|(k, _)| k).collect();
388 assert_eq!(names, ["b", "a", "b"]);
389 assert_eq!(o.get("b"), Some(&OptionValue::Literal(lit("1"))));
391 assert_eq!(
392 o.get("a"),
393 Some(&OptionValue::Variable(VariableRef { name: "x".into() }))
394 );
395 assert_eq!(o.get("c"), None);
396 let mut n = Options::new();
398 n.push("\u{e9}".into(), OptionValue::Literal(lit("1")));
399 assert!(n.get("e\u{301}").is_none());
400 }
401
402 #[test]
403 fn attributes_keep_order_and_duplicates() {
404 let mut a = Attributes::new();
405 a.push("flag".into(), None);
406 a.push("x".into(), Some(lit("1")));
407 a.push("flag".into(), Some(lit("2")));
408 assert_eq!(a.len(), 3);
409 assert_eq!(a.get("flag"), Some(Some(&lit("2"))));
411 assert_eq!(a.get("x"), Some(Some(&lit("1"))));
412 assert_eq!(a.get("y"), None);
413 let all: alloc::vec::Vec<(&str, Option<&Literal<'_>>)> = a.iter().collect();
414 assert_eq!(all[2], ("flag", Some(&lit("2"))));
415 }
416
417 #[test]
418 fn split_identifiers() {
419 assert_eq!(split_identifier("ns:name"), (Some("ns"), "name"));
420 assert_eq!(split_identifier("name"), (None, "name"));
421 assert_eq!(split_identifier("u:dir"), (Some("u"), "dir"));
422 assert_eq!(split_identifier(""), (None, ""));
423 }
424
425 #[test]
426 fn expression_accessors_and_owning() {
427 let mut attrs = Attributes::new();
428 attrs.push("a".into(), None);
429 let f = FunctionRef {
430 name: "number".into(),
431 options: Options::new(),
432 };
433 let e = Expression::Variable(VariableExpression {
434 arg: VariableRef { name: "n".into() },
435 function: Some(f.clone()),
436 attributes: attrs.clone(),
437 });
438 assert_eq!(e.function(), Some(&f));
439 assert_eq!(e.attributes(), &attrs);
440 let fe = Expression::Function(FunctionExpression {
441 function: f.clone(),
442 attributes: Attributes::new(),
443 });
444 assert_eq!(fe.function().map(|f| f.name.as_ref()), Some("number"));
445 let owned: Expression<'static> = e.clone().into_owned();
446 assert_eq!(owned, e);
447 if let Expression::Variable(v) = owned {
448 assert!(matches!(v.arg.name, Cow::Owned(_)));
449 }
450 }
451}