use std::fmt;
use chumsky::span::{SimpleSpan, Spanned};
use svugy_model::model::ViewAngle;
pub(crate) type Span = SimpleSpan<usize>;
#[derive(Debug, Default)]
pub(crate) struct Document {
pub(crate) view: Option<ViewAngle>,
pub(crate) styles: Vec<StyleDefinition>,
pub(crate) components: Vec<ComponentItem>,
pub(crate) workflows: Vec<WorkflowSection>,
}
#[derive(Debug)]
pub(crate) struct StyleDefinition {
pub(crate) name: Spanned<String>,
pub(crate) entries: Vec<Entry>,
}
#[derive(Debug)]
pub(crate) struct ComponentItem {
pub(crate) id: Spanned<String>,
pub(crate) display_name: Option<String>,
pub(crate) entries: Vec<Entry>,
pub(crate) description: Option<Description>,
pub(crate) children: Vec<ComponentItem>,
pub(crate) span: Span,
}
#[derive(Debug)]
pub(crate) struct WorkflowSection {
pub(crate) id: Spanned<String>,
pub(crate) title: String,
pub(crate) subtitle: Option<String>,
pub(crate) prose: Option<Description>,
pub(crate) overrides: Vec<OverrideItem>,
pub(crate) steps: Vec<StepSection>,
}
#[derive(Debug)]
pub(crate) struct StepSection {
pub(crate) id: Spanned<String>,
pub(crate) title: String,
pub(crate) prose: Option<Description>,
pub(crate) items: Vec<StepItem>,
}
#[derive(Debug)]
pub(crate) struct OverrideItem {
pub(crate) reference: Reference,
pub(crate) entries: Vec<Entry>,
pub(crate) span: Span,
}
#[derive(Debug)]
pub(crate) enum StepItem {
Element(Reference),
ListedEdge(ListedEdge),
Edge(EdgeItem),
Chain(ChainItem),
}
#[derive(Debug)]
pub(crate) struct ListedEdge {
pub(crate) from: Reference,
pub(crate) to: Reference,
pub(crate) ordinal: u32,
pub(crate) span: Span,
}
#[derive(Debug)]
pub(crate) struct EdgeItem {
pub(crate) from: Reference,
pub(crate) to: Reference,
pub(crate) label: Option<Spanned<String>>,
pub(crate) entries: Vec<Entry>,
pub(crate) description: Option<Description>,
}
#[derive(Debug)]
pub(crate) struct ChainItem {
pub(crate) start: Reference,
pub(crate) first_hop: Reference,
pub(crate) second_hop: Reference,
pub(crate) later_hops: Vec<Reference>,
}
#[derive(Debug)]
pub(crate) struct Description {
pub(crate) text: String,
pub(crate) span: Span,
}
#[derive(Debug, Clone)]
pub(crate) struct Reference {
pub(crate) segments: Vec<String>,
pub(crate) span: Span,
}
#[derive(Debug, Clone)]
pub(crate) enum Entry {
Style {
name: Spanned<String>,
may_end_label: bool,
},
Assignment(Assignment),
}
#[derive(Debug, Clone)]
pub(crate) struct Assignment {
pub(crate) key: Spanned<String>,
pub(crate) value: Spanned<Value>,
}
#[derive(Debug, Clone)]
pub(crate) enum Value {
Quoted(String),
Bare(Vec<String>),
}
impl Entry {
pub(crate) fn relabelled(self, span: Span) -> Self {
match self {
Self::Style {
name,
may_end_label,
} => {
let relabelled_name = Spanned {
inner: name.inner,
span,
};
Self::Style {
name: relabelled_name,
may_end_label,
}
}
Self::Assignment(Assignment { key, value }) => {
let relabelled_key = Spanned {
inner: key.inner,
span,
};
let relabelled_value = Spanned {
inner: value.inner,
span,
};
let relabelled_assignment = Assignment {
key: relabelled_key,
value: relabelled_value,
};
Self::Assignment(relabelled_assignment)
}
}
}
}
impl Reference {
pub(crate) fn from_dotted(dotted: &str, span: Span) -> Self {
let segments = dotted.split('.').map(str::to_owned).collect();
Self { segments, span }
}
}
impl fmt::Display for Reference {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
let dotted = self.segments.join(".");
formatter.write_str(&dotted)
}
}