1use std::collections::VecDeque;
2use crate::slot::Slot;
3use serde::{Deserialize, Serialize};
4use std::fmt::{Display, Formatter};
5
6#[derive(PartialEq, Debug, Clone, Eq, Hash, Serialize, Deserialize)]
8pub struct Path {
9 slots: VecDeque<Slot>,
10}
11
12#[macro_export]
13macro_rules! path {
14 ($($x:expr),*) => {{
15 let mut temp_vec = vec![$($x),*];
16 temp_vec.reverse();
17 Path::from(temp_vec)
18 }};
19 }
20
21impl Path {
22 pub fn new() -> Self {
28 Self { slots: vec![].into() }
29 }
30
31 pub fn push(&mut self, slot: Slot) {
37 self.slots.push_front(slot);
38 }
39
40 pub fn pull(&mut self) -> Option<Slot> {
46 self.slots.pop_front()
47 }
48
49 pub fn is_root(&self) -> bool {
56 self.slots.is_empty()
57 }
58
59 pub fn matches(&self, p: &Path) -> bool {
70 self == p
71 }
72
73 pub fn head(&self) -> Option<&Slot> {
79 self.slots.front()
80 }
81}
82
83impl Default for Path {
84 fn default() -> Self {
85 Self::new()
86 }
87}
88
89impl From<Vec<Slot>> for Path {
90 fn from(slots: Vec<Slot>) -> Self {
91 let mut reversed_slots = slots;
92 reversed_slots.reverse();
93 Self {
94 slots: reversed_slots.into(),
95 }
96 }
97}
98
99impl Display for Path {
100 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
101 write!(f, "P://")?;
102 for (i, slot) in self.slots.iter().enumerate() {
103 if i != 0 {
104 write!(f, "/")?;
105 }
106 write!(f, "{}", slot)?;
107 }
108 Ok(())
109 }
110}
111
112#[cfg(test)]
113mod tests {
114 use super::*;
115 use crate::slot::Slot::*;
116
117 #[test]
118 fn test_is_root() {
119 let empty_path = Path::from(Vec::new());
120 let not_empty_path = Path::from(vec![Rep(0), Nbr(0), Nbr(1), Branch(0)]);
121 assert!(empty_path.is_root());
122 assert!(!not_empty_path.is_root())
123 }
124
125 #[test]
126 fn test_not_empty_head() {
127 let path = Path::from(vec![Rep(0), Nbr(0), Nbr(1), Branch(0)]);
128 assert_eq!(path.head().unwrap(), &Branch(0))
129 }
130
131 #[test]
132 fn test_empty_head() {
133 let path = Path::new();
134 assert!(path.head().is_none())
135 }
136
137 #[test]
138 fn test_push() {
139 let mut path = path![Nbr(1), Nbr(0), Rep(0)];
140 path.push(Branch(0));
141 assert_eq!(path, path![Branch(0), Nbr(1), Nbr(0), Rep(0)])
142 }
143
144 #[test]
145 fn test_not_empty_pull() {
146 let mut path = Path::from(vec![Rep(0), Nbr(0), Nbr(1), Branch(0)]);
147 path.pull();
148 assert_eq!(path.slots, vec![Nbr(1), Nbr(0), Rep(0)])
149 }
150
151 #[test]
152 fn test_empty_pull() {
153 let mut path = Path::new();
154 assert!(path.pull().is_none());
155 }
156
157 #[test]
158 fn test_to_str() {
159 let path = path![Branch(0), Nbr(1), Nbr(0), Rep(0)];
160 assert_eq!(path.to_string(), "P://Branch(0)/Nbr(1)/Nbr(0)/Rep(0)")
161 }
162
163 #[test]
164 fn test_matches() {
165 let path = Path::from(vec![Rep(0), Nbr(0), Nbr(1), Branch(0)]);
166 assert!(path.matches(&Path::from(vec![Rep(0), Nbr(0), Nbr(1), Branch(0)])));
167 assert!(!path.matches(&Path::from(vec![Nbr(0), Nbr(1), Branch(0)])))
168 }
169
170 #[test]
171 fn test_serialize_and_deserialize() {
172 let path = path!(Rep(0), FoldHood(0), Nbr(0), Nbr(1));
173 let path_str = serde_json::to_string(&path).unwrap();
174 let path_des = serde_json::from_str(&path_str).unwrap();
175 assert_eq!(path, path_des);
176 }
177}