Skip to main content

oak_d2/ast/
mod.rs

1use core::range::Range;
2
3/// The root of a D2 Abstract Syntax Tree.
4#[derive(Clone, Debug, PartialEq)]
5#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
6pub struct D2Root {
7    /// The elements in the D2 diagram.
8    pub elements: Vec<D2Element>,
9    /// The span of the entire diagram in the source file.
10    #[cfg_attr(feature = "serde", serde(with = "oak_core::serde_range"))]
11    pub span: Range<usize>,
12}
13
14/// A top-level element in a D2 diagram.
15#[derive(Clone, Debug, PartialEq)]
16#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
17pub enum D2Element {
18    /// A shape definition.
19    Shape(Shape),
20    /// A connection between shapes.
21    Connection(Connection),
22}
23
24/// A shape in a D2 diagram.
25#[derive(Clone, Debug, PartialEq)]
26#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
27pub struct Shape {
28    /// The identifier of the shape.
29    pub id: String,
30    /// The optional label of the shape.
31    pub label: Option<String>,
32}
33
34/// A connection between shapes in a D2 diagram.
35#[derive(Clone, Debug, PartialEq)]
36#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
37pub struct Connection {
38    /// The source shape ID.
39    pub from: String,
40    /// The target shape ID.
41    pub to: String,
42    /// The span of the connection in the source file.
43    #[cfg_attr(feature = "serde", serde(with = "oak_core::serde_range"))]
44    pub span: Range<usize>,
45}
46
47impl std::fmt::Display for D2Root {
48    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
49        for element in &self.elements {
50            match element {
51                D2Element::Shape(s) => {
52                    if let Some(label) = &s.label {
53                        writeln!(f, "{}: {}", s.id, label)?;
54                    }
55                    else {
56                        writeln!(f, "{}", s.id)?;
57                    }
58                }
59                D2Element::Connection(c) => {
60                    writeln!(f, "{} -> {}", c.from, c.to)?;
61                }
62            }
63        }
64        Ok(())
65    }
66}