1use std::sync::{Arc, RwLock};
5
6pub struct Tree {
7 root: Arc<RwLock<Box<Node>>>,
8}
9
10impl Tree {
11 pub fn new() -> Self {
12 Self {
13 root: Arc::new(RwLock::new(Box::new(Node::new("", Some(""))))),
14 }
15 }
16
17 pub fn insert(&mut self, path: impl AsRef<str>, id: impl AsRef<str>) {
18 let p = path.as_ref().to_owned();
19 let mut components = p.split("/").collect::<Vec<_>>();
20 components = format_components(components);
21
22 let mut node = self.root.clone();
23 for &c in components.iter() {
24 let next_node = match node
25 .read()
26 .unwrap()
27 .children
28 .iter()
29 .find(|child| child.read().unwrap().name.as_str() == c)
30 {
31 Some(child) => Some(child.clone()),
32 None => None,
33 };
34 node = next_node.unwrap_or_else(|| {
35 let mut node_write = node.write().unwrap();
36 node_write
37 .children
38 .push(Arc::new(RwLock::new(Box::new(Node::new(
39 c,
40 None as Option<String>,
41 )))));
42 node_write.children.last().unwrap().clone()
43 });
44 }
45 node.write().unwrap().id = Some(id.as_ref().to_owned());
46 }
47
48 pub fn get(&self, path: impl AsRef<str>) -> Option<String> {
49 let p = path.as_ref().to_owned();
50 let mut components = p.split("/").collect::<Vec<_>>();
51 components = format_components(components);
52
53 let mut node = self.root.clone();
54 for &c in components.iter() {
55 let next_node = match node
56 .read()
57 .unwrap()
58 .children
59 .iter()
60 .find(|child| child.read().unwrap().name.as_str() == c)
61 {
62 Some(child) => child.clone(),
63 None => return None,
64 };
65 node = next_node;
66 }
67 let id = node.read().unwrap().id.clone();
68 id
69 }
70
71 pub fn invalid(&self, path: impl AsRef<str>) {
72 let p = path.as_ref().to_owned();
73 let mut components = p.split("/").collect::<Vec<_>>();
74 components = format_components(components);
75 let last_component = match components.last() {
76 Some(&c) => c,
77 None => return,
78 };
79 components.pop();
80
81 let mut node = self.root.clone();
82 for &c in components.iter() {
83 let next_node = match node
84 .read()
85 .unwrap()
86 .children
87 .iter()
88 .find(|child| child.read().unwrap().name.as_str() == c)
89 {
90 Some(child) => child.clone(),
91 None => return,
92 };
93 node = next_node
94 }
95 let mut node_write = node.write().unwrap();
96 if let Some(i) = node_write
97 .children
98 .iter()
99 .enumerate()
100 .find(|(_, child)| child.read().unwrap().name.as_str() == last_component)
101 .map(|(i, _)| i)
102 {
103 node_write.children.remove(i);
104 }
105 }
106}
107
108fn format_components(mut components: Vec<&str>) -> Vec<&str> {
109 if components.first().map(|&c| c == "").unwrap_or(false) {
110 components.remove(0);
111 }
112 if components.last().map(|&c| c == "").unwrap_or(false) {
113 components.pop();
114 }
115 components
116}
117
118struct Node {
119 name: String,
120 id: Option<String>,
121 children: Vec<Arc<RwLock<Box<Node>>>>,
122}
123
124impl Node {
125 fn new(name: impl AsRef<str>, id: Option<impl AsRef<str>>) -> Self {
126 Self {
127 name: name.as_ref().to_owned(),
128 id: id.map(|i| i.as_ref().to_owned()),
129 children: Vec::new(),
130 }
131 }
132}
133
134#[cfg(test)]
135mod tests {
136 use super::*;
137
138 #[test]
139 fn test_insert() {
140 let mut tree = Tree::new();
141 tree.insert("/test", "0");
142 let root = tree.root.read().unwrap();
143 assert_eq!(root.children.len(), 1);
144 let new_node = root.children[0].read().unwrap();
145 assert_eq!(new_node.name, "test");
146 assert_eq!(new_node.id.as_deref(), Some("0"));
147 }
148
149 #[test]
150 fn test_get() {
151 let mut tree = Tree::new();
152 tree.insert("/test", "0");
153 tree.insert("/test/test/test", "1");
154 assert_eq!(tree.get("/test").as_deref(), Some("0"));
155 assert_eq!(tree.get("/test/test/test").as_deref(), Some("1"));
156 assert_eq!(tree.get("/test/test"), None);
157 assert_eq!(tree.get("/test/test/test/test"), None);
158 }
159
160 #[test]
161 fn test_invalid() {
162 let mut tree = Tree::new();
163 tree.insert("/test", "0");
164 tree.insert("/test/test", "1");
165 tree.insert("/test/test/test", "2");
166 tree.invalid("/test/test/test/test");
167 tree.invalid("/test/test");
168 assert_eq!(tree.get("/test/test/test"), None);
169 assert_eq!(tree.get("/test").as_deref(), Some("0"));
170 }
171}