1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
/// This enumeration represents all possible arrow edge
/// as defined in [grapviz documentation](http://www.graphviz.org/content/arrow-shapes).
#[derive(Clone, Copy, Hash, PartialEq, Eq)]
pub enum Shape {
/// No arrow will be displayed
NoArrow,
/// Arrow that ends in a triangle. Basically a normal arrow.
/// NOTE: there is error in official documentation, this supports both fill and side clipping
Normal(crate::Fill, crate::Side),
/// Arrow ending in a small square box
Box(crate::Fill, crate::Side),
/// Arrow ending in a three branching lines also called crow's foot
Crow(crate::Side),
/// Arrow ending in a curve
Curve(crate::Side),
/// Arrow ending in an inverted curve
ICurve(crate::Fill, crate::Side),
/// Arrow ending in an diamond shaped rectangular shape.
Diamond(crate::Fill, crate::Side),
/// Arrow ending in a circle.
Dot(crate::Fill),
/// Arrow ending in an inverted triangle.
Inv(crate::Fill, crate::Side),
/// Arrow ending with a T shaped arrow.
Tee(crate::Side),
/// Arrow ending with a V shaped arrow.
Vee(crate::Side),
}
impl Shape {
/// Constructor which returns no arrow.
pub fn none() -> Self {
Self::NoArrow
}
/// Constructor which returns normal arrow.
pub fn normal() -> Self {
Self::Normal(crate::Fill::Filled, crate::Side::Both)
}
/// Constructor which returns a regular box arrow.
pub fn boxed() -> Self {
Self::Box(crate::Fill::Filled, crate::Side::Both)
}
/// Constructor which returns a regular crow arrow.
pub fn crow() -> Self {
Self::Crow(crate::Side::Both)
}
/// Constructor which returns a regular curve arrow.
pub fn curve() -> Self {
Self::Curve(crate::Side::Both)
}
/// Constructor which returns an inverted curve arrow.
pub fn icurve() -> Self {
Self::ICurve(crate::Fill::Filled, crate::Side::Both)
}
/// Constructor which returns a diamond arrow.
pub fn diamond() -> Self {
Self::Diamond(crate::Fill::Filled, crate::Side::Both)
}
/// Constructor which returns a circle shaped arrow.
pub fn dot() -> Self {
Self::Diamond(crate::Fill::Filled, crate::Side::Both)
}
/// Constructor which returns an inverted triangle arrow.
pub fn inv() -> Self {
Self::Inv(crate::Fill::Filled, crate::Side::Both)
}
/// Constructor which returns a T shaped arrow.
pub fn tee() -> Self {
Self::Tee(crate::Side::Both)
}
/// Constructor which returns a V shaped arrow.
pub fn vee() -> Self {
Self::Vee(crate::Side::Both)
}
}
impl std::fmt::Display for Shape {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Box(fill, side)
| Self::ICurve(fill, side)
| Self::Diamond(fill, side)
| Self::Inv(fill, side)
| Self::Normal(fill, side) => {
write!(f, "{fill}")?;
if matches!(side, crate::Side::Left | crate::Side::Right) {
write!(f, "{side}")?;
}
}
Self::Dot(fill) => write!(f, "{fill}")?,
Self::Crow(side) | Self::Curve(side) | Self::Tee(side) | Self::Vee(side) => {
if matches!(side, crate::Side::Left | crate::Side::Right) {
write!(f, "{side}")?;
}
}
Self::NoArrow => {}
};
let s = match self {
Self::NoArrow => "none",
Self::Normal(_, _) => "normal",
Self::Box(_, _) => "box",
Self::Crow(_) => "crow",
Self::Curve(_) => "curve",
Self::ICurve(_, _) => "icurve",
Self::Diamond(_, _) => "diamond",
Self::Dot(_) => "dot",
Self::Inv(_, _) => "inv",
Self::Tee(_) => "tee",
Self::Vee(_) => "vee",
};
write!(f, "{s}")
}
}
/// This structure holds all information that can describe an arrow connected to
/// either start or end of an edge.
#[derive(Clone, Hash, PartialEq, Eq)]
pub struct Arrow {
pub arrows: Vec<Shape>,
}
impl Arrow {
/// Return `true` if this is a default arrow.
pub(crate) fn is_default(&self) -> bool {
self.arrows.is_empty()
}
/// Arrow constructor which returns a default arrow
pub fn default() -> Self {
Self { arrows: vec![] }
}
/// Arrow constructor which returns an empty arrow
pub fn none() -> Self {
Self {
arrows: vec![Shape::NoArrow],
}
}
/// Arrow constructor which returns a regular triangle arrow, without modifiers
pub fn normal() -> Self {
Self {
arrows: vec![Shape::normal()],
}
}
/// Arrow constructor which returns an arrow created by a given Shape.
pub fn from_arrow(arrow: Shape) -> Self {
Self {
arrows: vec![arrow],
}
}
}
impl std::fmt::Display for Arrow {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
for arrow in &self.arrows {
write!(f, "{arrow}")?;
}
Ok(())
}
}
impl From<[Shape; 2]> for Arrow {
fn from(shape: [Shape; 2]) -> Self {
Self {
arrows: vec![shape[0], shape[1]],
}
}
}
impl From<[Shape; 3]> for Arrow {
fn from(shape: [Shape; 3]) -> Self {
Self {
arrows: vec![shape[0], shape[1], shape[2]],
}
}
}
impl From<[Shape; 4]> for Arrow {
fn from(shape: [Shape; 4]) -> Self {
Self {
arrows: vec![shape[0], shape[1], shape[2], shape[3]],
}
}
}