1use core::range::Range;
2
3#[derive(Clone, Debug, PartialEq)]
5#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
6pub struct D2Root {
7 pub elements: Vec<D2Element>,
9 #[cfg_attr(feature = "serde", serde(with = "oak_core::serde_range"))]
11 pub span: Range<usize>,
12}
13
14#[derive(Clone, Debug, PartialEq)]
16#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
17pub enum D2Element {
18 Shape(Shape),
20 Connection(Connection),
22}
23
24#[derive(Clone, Debug, PartialEq)]
26#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
27pub struct Shape {
28 pub id: String,
30 pub label: Option<String>,
32}
33
34#[derive(Clone, Debug, PartialEq)]
36#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
37pub struct Connection {
38 pub from: String,
40 pub to: String,
42 #[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}