Skip to main content

oak_d2/ast/
mod.rs

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