use std::{collections::HashMap, fmt, iter::FromIterator};
use crate::R;
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub struct Ident(String);
impl Ident {
pub fn as_str(&self) -> &str {
&self.0
}
}
pub type TypeExpr = crate::TypeExpr<Ident, crate::Expr<R<Ident>>>;
pub type Expr = crate::Expr<R<Ident>>;
pub type Field = crate::Field<TypeExpr>;
pub type NodeApp = crate::NodeApp<Ident, crate::Expr<R<Ident>>>;
impl std::str::FromStr for Ident {
type Err = std::convert::Infallible;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(Ident(s.into()))
}
}
impl fmt::Display for Ident {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.as_str())
}
}
#[derive(Debug, Clone)]
pub struct Path(Vec<Ident>);
impl Path {
pub fn len(&self) -> usize {
self.0.len()
}
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
pub fn split_branch(self) -> Result<(Ident, Path, Ident), Self> {
if self.len() >= 2 {
let mut components = self.0;
let name = components.pop().unwrap();
let root = components.remove(0);
Ok((root, Path(components), name))
} else {
Err(self)
}
}
}
impl<'a> FromIterator<&'a Ident> for Path {
fn from_iter<T>(iter: T) -> Path
where
T: IntoIterator<Item = &'a Ident>,
{
Path(iter.into_iter().cloned().collect())
}
}
impl fmt::Display for Path {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
for (i, ident) in self.0.iter().enumerate() {
write!(f, "{}", ident)?;
if i + 1 < self.0.len() {
f.write_str(".")?;
}
}
Ok(())
}
}
impl std::str::FromStr for Path {
type Err = std::convert::Infallible;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(Path(s.split('.').map(|s| s.parse().unwrap()).collect()))
}
}
impl<'a> IntoIterator for &'a Path {
type IntoIter = std::slice::Iter<'a, Ident>;
type Item = &'a Ident;
fn into_iter(self) -> Self::IntoIter {
self.0.iter()
}
}
impl IntoIterator for Path {
type IntoIter = std::vec::IntoIter<Ident>;
type Item = Ident;
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
}
}
#[derive(Debug, Clone)]
pub struct Root {
pub name: Ident,
pub description: Option<String>,
pub fields: Vec<Field>,
}
#[derive(Debug, Clone)]
pub struct Branch {
pub root: Ident,
pub path: Path,
pub name: Ident,
pub description: Option<String>,
pub condition: Expr,
pub implies: Vec<NodeApp>,
pub fields: Vec<Field>,
pub properties: HashMap<String, lexpr::Value>,
}
#[derive(Debug, Clone)]
pub struct Enum {
pub name: Ident,
pub description: Option<String>,
pub discriminants: Vec<Field>,
pub variants: Vec<Variant>,
}
#[derive(Debug, Clone)]
pub struct Variant {
pub name: Ident,
pub condition: Expr,
pub fields: Vec<Field>,
pub properties: HashMap<String, lexpr::Value>,
}