use crate::ast::Side;
use crate::span::Span;
use std::collections::{BTreeMap, HashMap};
pub struct Program {
pub vars: VarTable,
pub scene: ResolvedScene,
pub links: Vec<ResolvedLink>,
pub sheet: SheetInputs,
}
#[derive(Default, Clone)]
pub struct SheetInputs {
pub class_rules: Vec<(String, AttrMap)>,
pub link_defaults: AttrMap,
pub root_font_size: f64,
pub root_text: AttrMap,
}
pub struct ResolvedScene {
pub attrs: AttrMap,
pub nodes: Vec<ResolvedInst>,
}
pub struct ResolvedInst {
pub id: Option<String>,
pub shape: ShapeKind,
pub type_chain: Vec<String>,
pub applied_styles: Vec<String>,
pub label: Option<String>,
pub attrs: AttrMap,
pub own_style: AttrMap,
pub markers: Markers,
pub children: Vec<ResolvedInst>,
pub span: Span,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum ShapeKind {
Block,
Oval,
Hex,
Slant,
Cyl,
Diamond,
Cloud,
Poly,
Path,
Text,
Line,
Icon,
Image,
}
impl ShapeKind {
pub const ALL: [ShapeKind; 13] = [
Self::Block,
Self::Oval,
Self::Hex,
Self::Slant,
Self::Cyl,
Self::Diamond,
Self::Cloud,
Self::Poly,
Self::Path,
Self::Text,
Self::Line,
Self::Icon,
Self::Image,
];
pub fn parse(s: &str) -> Option<Self> {
Some(match s {
"block" => Self::Block,
"oval" => Self::Oval,
"hex" => Self::Hex,
"slant" => Self::Slant,
"cyl" => Self::Cyl,
"diamond" => Self::Diamond,
"cloud" => Self::Cloud,
"poly" => Self::Poly,
"path" => Self::Path,
"line" => Self::Line,
"icon" => Self::Icon,
"image" => Self::Image,
_ => return None,
})
}
pub fn as_str(self) -> &'static str {
match self {
Self::Block => "block",
Self::Oval => "oval",
Self::Hex => "hex",
Self::Slant => "slant",
Self::Cyl => "cyl",
Self::Diamond => "diamond",
Self::Cloud => "cloud",
Self::Poly => "poly",
Self::Path => "path",
Self::Text => "text",
Self::Line => "line",
Self::Icon => "icon",
Self::Image => "image",
}
}
}
#[derive(Default, Clone, Debug)]
pub struct AttrMap {
pub map: BTreeMap<String, ResolvedValue>,
}
impl AttrMap {
pub fn new() -> Self {
Self::default()
}
pub fn insert(&mut self, name: impl Into<String>, value: ResolvedValue) {
self.map.insert(name.into(), value);
}
pub fn get(&self, name: &str) -> Option<&ResolvedValue> {
self.map.get(name)
}
pub fn number(&self, name: &str) -> Option<f64> {
self.get(name).and_then(ResolvedValue::as_number)
}
}
#[derive(Clone, Debug)]
pub enum ResolvedValue {
Number(f64),
Percent(f64),
String(String),
Hex(String),
Ident(String),
RawCss(String),
Tuple(Vec<ResolvedValue>),
List(Vec<ResolvedValue>),
Call(ResolvedCall),
LiveVar {
name: String,
raw: bool,
},
}
impl ResolvedValue {
pub fn as_number(&self) -> Option<f64> {
match self {
ResolvedValue::Number(n) => Some(*n),
_ => None,
}
}
}
#[derive(Clone, Debug)]
pub struct ResolvedCall {
pub name: String,
pub args: Vec<ResolvedValue>,
}
#[derive(Clone, Debug, Default)]
pub struct VarTable {
pub entries: HashMap<String, ResolvedValue>,
}
impl VarTable {
pub fn new() -> Self {
Self {
entries: HashMap::new(),
}
}
pub fn get(&self, name: &str) -> Option<&ResolvedValue> {
self.entries.get(name)
}
pub fn set(&mut self, name: impl Into<String>, value: ResolvedValue) {
self.entries.insert(name.into(), value);
}
}
#[derive(Clone, Debug, Default)]
pub struct Markers {
pub start: MarkerKind,
pub end: MarkerKind,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Default)]
pub enum MarkerKind {
#[default]
None,
Arrow,
Dot,
Diamond,
Crow,
}
impl MarkerKind {
pub fn parse(s: &str) -> Option<Self> {
Some(match s {
"none" => Self::None,
"arrow" => Self::Arrow,
"dot" => Self::Dot,
"diamond" => Self::Diamond,
"crow" => Self::Crow,
_ => return None,
})
}
pub fn from_marker(m: crate::ast::LinkMarker) -> Self {
match m {
crate::ast::LinkMarker::None => Self::None,
crate::ast::LinkMarker::Arrow => Self::Arrow,
crate::ast::LinkMarker::Crow => Self::Crow,
crate::ast::LinkMarker::Dot => Self::Dot,
crate::ast::LinkMarker::Diamond => Self::Diamond,
}
}
}
pub struct ResolvedLink {
pub endpoints: Vec<ResolvedEndpoint>,
pub attrs: AttrMap,
pub applied_styles: Vec<String>,
pub markers: Markers,
pub texts: Vec<ResolvedText>,
pub span: Span,
}
pub struct ResolvedEndpoint {
pub path: String,
pub side: Option<Side>,
pub span: Span,
}
#[derive(Clone)]
pub struct ResolvedText {
pub text: String,
pub along: Along,
pub attrs: AttrMap,
}
#[derive(Clone, Debug)]
pub enum Along {
Auto,
Fraction(f64),
}