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