bmx/
data.rs

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
19// FIXME: Limit allowed identifiers
20impl 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        // FIXME: limit identifiers
84        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}