1use std::fmt;
2use std::path::PathBuf;
3
4use arctree::Node as ArcNode;
5
6#[derive(Clone, Copy, Debug, PartialEq, Eq)]
8pub enum NodeKind {
9 Directory,
11
12 File,
14}
15
16#[derive(Clone, PartialEq)]
21pub struct Node {
22 node: ArcNode<NodeData>,
23}
24
25impl fmt::Debug for Node {
26 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
27 let node = self.node.read();
28 f.debug_struct("Node")
29 .field("name", &node.name)
30 .field("kind", &node.kind)
31 .field("cache_offset", &node.cache_offset)
32 .field("timestamp", &node.timestamp)
33 .field("comp_len", &node.comp_len)
34 .field("len", &node.len)
35 .finish()
36 }
37}
38
39pub trait FileNode {
41 fn cache_offset(&self) -> i64;
43
44 fn timestamp(&self) -> i64;
46
47 fn comp_len(&self) -> i32;
49
50 fn len(&self) -> i32;
52}
53
54pub trait DirectoryNode {
56 fn children(&self) -> Vec<Node>;
58
59 fn get_child(&self, name: &str) -> Option<Node>;
61}
62
63impl Node {
64 fn new(
65 name: &str,
66 kind: NodeKind,
67 cache_offset: Option<i64>,
68 timestamp: Option<i64>,
69 comp_len: Option<i32>,
70 len: Option<i32>,
71 ) -> Self {
72 Self {
73 node: ArcNode::new(NodeData::new(
74 name,
75 kind,
76 cache_offset,
77 timestamp,
78 comp_len,
79 len,
80 )),
81 }
82 }
83
84 pub(super) fn root() -> Self {
85 Self::directory("")
86 }
87
88 pub(super) fn file(
89 name: &str,
90 cache_offset: i64,
91 timestamp: i64,
92 comp_len: i32,
93 len: i32,
94 ) -> Self {
95 Self::new(
96 name,
97 NodeKind::File,
98 Some(cache_offset),
99 Some(timestamp),
100 Some(comp_len),
101 Some(len),
102 )
103 }
104
105 pub(super) fn directory(name: &str) -> Self {
106 Self::new(name, NodeKind::Directory, None, None, None, None)
107 }
108
109 pub(super) fn append(&mut self, child: Node) {
110 self.node.append(child.node.clone());
111 }
112
113 pub fn name(&self) -> String {
115 self.node.read().name().to_string()
116 }
117
118 pub fn path(&self) -> PathBuf {
120 let mut ancestors = Vec::new();
121 let mut ancestor = self.node.parent();
122 while let Some(current_ancestor) = ancestor {
123 ancestors.push(current_ancestor.clone());
124 ancestor = current_ancestor.parent();
125 }
126
127 let mut path = PathBuf::from("/");
128 for ancestor in ancestors.iter().rev() {
129 path.push(ancestor.read().name());
130 }
131
132 path.push(self.name());
133
134 path
135 }
136
137 pub fn kind(&self) -> NodeKind {
139 self.node.read().kind()
140 }
141
142 pub fn parent(&self) -> Option<Node> {
144 self.node.parent().map(|parent| Node { node: parent })
145 }
146}
147
148impl FileNode for Node {
149 fn cache_offset(&self) -> i64 {
150 self.node.read().cache_offset().unwrap().clone()
151 }
152
153 fn timestamp(&self) -> i64 {
154 self.node.read().timestamp().unwrap().clone()
155 }
156
157 fn comp_len(&self) -> i32 {
158 self.node.read().comp_len().unwrap().clone()
159 }
160
161 fn len(&self) -> i32 {
162 self.node.read().len().unwrap().clone()
163 }
164}
165
166impl DirectoryNode for Node {
167 fn children(&self) -> Vec<Node> {
168 self.node
169 .children()
170 .map(|child| Node {
171 node: child.clone(),
172 })
173 .collect()
174 }
175
176 fn get_child(&self, name: &str) -> Option<Node> {
177 self.node
178 .children()
179 .find(|child| *child.read().name() == *name)
180 .map(|child| Node {
181 node: child.clone(),
182 })
183 }
184}
185
186#[derive(Debug)]
187struct NodeData {
188 name: String,
189 kind: NodeKind,
190 cache_offset: Option<i64>,
191 timestamp: Option<i64>,
192 comp_len: Option<i32>,
193 len: Option<i32>,
194}
195
196impl NodeData {
197 fn new(
198 name: &str,
199 kind: NodeKind,
200 cache_offset: Option<i64>,
201 timestamp: Option<i64>,
202 comp_len: Option<i32>,
203 len: Option<i32>,
204 ) -> Self {
205 Self {
206 name: String::from(name),
207 kind,
208 cache_offset,
209 timestamp,
210 comp_len,
211 len,
212 }
213 }
214
215 fn name(&self) -> &String {
216 &self.name
217 }
218
219 fn kind(&self) -> NodeKind {
220 self.kind
221 }
222
223 fn cache_offset(&self) -> Option<&i64> {
224 self.cache_offset.as_ref()
225 }
226
227 fn timestamp(&self) -> Option<&i64> {
228 self.timestamp.as_ref()
229 }
230
231 fn comp_len(&self) -> Option<&i32> {
232 self.comp_len.as_ref()
233 }
234
235 fn len(&self) -> Option<&i32> {
236 self.len.as_ref()
237 }
238}