1use std::{collections::HashMap, fmt, iter::FromIterator};
2
3use crate::R;
4
5#[derive(Debug, Clone, Eq, PartialEq, Hash)]
6pub struct Ident(String);
7
8impl Ident {
9 pub fn as_str(&self) -> &str {
10 &self.0
11 }
12}
13
14pub type TypeExpr = crate::TypeExpr<Ident, crate::Expr<R<Ident>>>;
15pub type Expr = crate::Expr<R<Ident>>;
16pub type Field = crate::Field<TypeExpr>;
17pub type NodeApp = crate::NodeApp<Ident, crate::Expr<R<Ident>>>;
18
19impl std::str::FromStr for Ident {
21 type Err = std::convert::Infallible;
22
23 fn from_str(s: &str) -> Result<Self, Self::Err> {
24 Ok(Ident(s.into()))
25 }
26}
27
28impl fmt::Display for Ident {
29 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
30 write!(f, "{}", self.as_str())
31 }
32}
33
34#[derive(Debug, Clone)]
35pub struct Path(Vec<Ident>);
36
37impl Path {
38 pub fn len(&self) -> usize {
39 self.0.len()
40 }
41
42 pub fn is_empty(&self) -> bool {
43 self.0.is_empty()
44 }
45
46 pub fn split_branch(self) -> Result<(Ident, Path, Ident), Self> {
47 if self.len() >= 2 {
48 let mut components = self.0;
49 let name = components.pop().unwrap();
50 let root = components.remove(0);
51 Ok((root, Path(components), name))
52 } else {
53 Err(self)
54 }
55 }
56}
57
58impl<'a> FromIterator<&'a Ident> for Path {
59 fn from_iter<T>(iter: T) -> Path
60 where
61 T: IntoIterator<Item = &'a Ident>,
62 {
63 Path(iter.into_iter().cloned().collect())
64 }
65}
66
67impl fmt::Display for Path {
68 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
69 for (i, ident) in self.0.iter().enumerate() {
70 write!(f, "{}", ident)?;
71 if i + 1 < self.0.len() {
72 f.write_str(".")?;
73 }
74 }
75 Ok(())
76 }
77}
78
79impl std::str::FromStr for Path {
80 type Err = std::convert::Infallible;
81
82 fn from_str(s: &str) -> Result<Self, Self::Err> {
83 Ok(Path(s.split('.').map(|s| s.parse().unwrap()).collect()))
85 }
86}
87
88impl<'a> IntoIterator for &'a Path {
89 type IntoIter = std::slice::Iter<'a, Ident>;
90 type Item = &'a Ident;
91
92 fn into_iter(self) -> Self::IntoIter {
93 self.0.iter()
94 }
95}
96
97impl IntoIterator for Path {
98 type IntoIter = std::vec::IntoIter<Ident>;
99 type Item = Ident;
100
101 fn into_iter(self) -> Self::IntoIter {
102 self.0.into_iter()
103 }
104}
105
106#[derive(Debug, Clone)]
107pub struct Root {
108 pub name: Ident,
109 pub description: Option<String>,
110 pub fields: Vec<Field>,
111}
112
113#[derive(Debug, Clone)]
114pub struct Branch {
115 pub root: Ident,
116 pub path: Path,
117 pub name: Ident,
118 pub description: Option<String>,
119 pub condition: Expr,
120 pub implies: Vec<NodeApp>,
121 pub fields: Vec<Field>,
122 pub properties: HashMap<String, lexpr::Value>,
123}
124
125#[derive(Debug, Clone)]
126pub struct Enum {
127 pub name: Ident,
128 pub description: Option<String>,
129 pub discriminants: Vec<Field>,
130 pub variants: Vec<Variant>,
131}
132
133#[derive(Debug, Clone)]
134pub struct Variant {
135 pub name: Ident,
136 pub condition: Expr,
137 pub fields: Vec<Field>,
138 pub properties: HashMap<String, lexpr::Value>,
139}