1use super::AttrMap;
2use crate::file::Inode;
3use crate::path::BoxPath;
4use crate::record::DirectoryRecord;
5use crate::Record;
6use std::{
7 borrow::Cow,
8 collections::{BTreeMap, VecDeque},
9 fmt::Display,
10};
11
12#[derive(Debug, Default)]
13pub struct BoxMetadata {
14 pub(crate) root: Vec<Inode>,
16
17 pub(crate) inodes: Vec<Record>,
20
21 pub(crate) attr_keys: Vec<String>,
23
24 pub(crate) attrs: AttrMap,
26 }
29
30#[derive(Debug)]
31pub struct Records<'a> {
32 meta: &'a BoxMetadata,
33 inodes: &'a [Inode],
34 base_path: Option<BoxPath>,
35 cur_inode: usize,
36 cur_dir: Option<Box<Records<'a>>>,
37}
38
39impl<'a> Records<'a> {
40 pub(crate) fn new(
41 meta: &'a BoxMetadata,
42 inodes: &'a [Inode],
43 base_path: Option<BoxPath>,
44 ) -> Records<'a> {
45 Records {
46 meta,
47 inodes,
48 base_path,
49 cur_inode: 0,
50 cur_dir: None,
51 }
52 }
53}
54
55#[non_exhaustive]
56#[derive(Debug)]
57pub struct RecordsItem<'a> {
58 pub(crate) inode: Inode,
59 pub path: BoxPath,
60 pub record: &'a Record,
61}
62
63impl<'a> Iterator for Records<'a> {
64 type Item = RecordsItem<'a>;
65
66 fn next(&mut self) -> Option<Self::Item> {
67 if let Some(dir) = self.cur_dir.as_mut() {
69 if let Some(record) = dir.next() {
70 return Some(record);
71 }
72
73 self.cur_dir = None;
75 }
76 let inode = match self.inodes.get(self.cur_inode) {
77 Some(i) => *i,
78 None => return None,
79 };
80
81 let record = match self.meta.record(inode) {
82 Some(v) => v,
83 None => return None,
84 };
85
86 let base_path = match self.base_path.as_ref() {
87 Some(x) => x.join_unchecked(record.name()),
88 None => BoxPath(record.name().to_string()),
89 };
90
91 if let Record::Directory(record) = record {
92 self.cur_dir = Some(Box::new(Records::new(
93 self.meta,
94 &*record.inodes,
95 Some(base_path.clone()),
96 )));
97 }
98
99 self.cur_inode += 1;
100 Some(RecordsItem {
101 inode,
102 path: base_path,
103 record,
104 })
105 }
106}
107
108#[derive(Debug)]
109pub struct FindRecord<'a> {
110 meta: &'a BoxMetadata,
111 query: VecDeque<String>,
112 inodes: &'a [Inode],
113}
114
115impl<'a> FindRecord<'a> {
116 pub(crate) fn new(
117 meta: &'a BoxMetadata,
118 query: VecDeque<String>,
119 inodes: &'a [Inode],
120 ) -> FindRecord<'a> {
121 log::debug!("FindRecord query: {:?}", query);
122
123 FindRecord {
124 meta,
125 query,
126 inodes,
127 }
128 }
129}
130
131impl<'a> Iterator for FindRecord<'a> {
132 type Item = Inode;
133
134 fn next(&mut self) -> Option<Self::Item> {
135 let candidate_name = match self.query.pop_front() {
136 Some(v) => v,
137 None => return None,
138 };
139
140 log::debug!("candidate_name: {}", &candidate_name);
141
142 let result = self
143 .inodes
144 .iter()
145 .map(|inode| (*inode, self.meta.record(*inode).unwrap()))
146 .find(|x| x.1.name() == candidate_name);
147
148 match result {
149 Some(v) => {
150 log::debug!("{:?}", v);
151 if self.query.is_empty() {
152 Some(v.0)
153 } else if let Record::Directory(record) = v.1 {
154 let mut tmp = VecDeque::new();
155 std::mem::swap(&mut self.query, &mut tmp);
156 let result = FindRecord::new(self.meta, tmp, &*record.inodes).next();
157 log::debug!("FindRecord result: {:?}", &result);
158 result
159 } else {
160 None
161 }
162 }
163 None => None,
164 }
165 }
166}
167
168impl BoxMetadata {
169 #[inline(always)]
170 pub fn iter(&self) -> Records {
171 Records::new(self, &*self.root, None)
172 }
173
174 #[inline(always)]
175 pub fn root_records(&self) -> Vec<(Inode, &Record)> {
176 self.root
177 .iter()
178 .copied()
179 .filter_map(|x| self.record(x).map(|r| (x, r)))
180 .collect()
181 }
182
183 #[inline(always)]
184 pub fn records(&self, dir_record: &DirectoryRecord) -> Vec<(Inode, &Record)> {
185 dir_record
186 .inodes
187 .iter()
188 .copied()
189 .filter_map(|x| self.record(x).map(|r| (x, r)))
190 .collect()
191 }
192
193 #[inline(always)]
194 pub fn inode(&self, path: &BoxPath) -> Option<Inode> {
195 FindRecord::new(self, path.iter().map(str::to_string).collect(), &*self.root).next()
200 }
201
202 #[inline(always)]
203 pub fn record(&self, inode: Inode) -> Option<&Record> {
204 self.inodes.get(inode.get() as usize - 1)
205 }
206
207 #[inline(always)]
208 pub fn record_mut(&mut self, inode: Inode) -> Option<&mut Record> {
209 self.inodes.get_mut(inode.get() as usize - 1)
210 }
211
212 #[inline(always)]
213 pub fn insert_record(&mut self, record: Record) -> Inode {
214 self.inodes.push(record);
215 Inode::new(self.inodes.len() as u64).unwrap()
216 }
217
218 #[inline(always)]
219 pub fn attr<S: AsRef<str>>(&self, path: &BoxPath, key: S) -> Option<&[u8]> {
220 let key = self.attr_key(key.as_ref())?;
221
222 if let Some(record) = self.inode(path).and_then(|x| self.record(x)) {
223 record.attrs().get(&key).map(|x| &**x)
224 } else {
225 None
226 }
227 }
228
229 pub fn file_attrs(&self) -> BTreeMap<&str, AttrValue<'_>> {
230 let mut map = BTreeMap::new();
231
232 for key in self.attr_keys.iter() {
233 let k = self.attr_key(key).unwrap();
234 if let Some(v) = self.attrs.get(&k) {
235 let value = std::str::from_utf8(v)
236 .map(|v| {
237 serde_json::from_str(v)
238 .map(AttrValue::Json)
239 .unwrap_or(AttrValue::String(v))
240 })
241 .unwrap_or(AttrValue::Bytes(v));
242 map.insert(&**key, value);
243 }
244 }
245
246 map
247 }
248
249 #[inline(always)]
250 pub fn file_attr<S: AsRef<str>>(&self, key: S) -> Option<&Vec<u8>> {
251 let key = self.attr_key(key.as_ref())?;
252
253 self.attrs.get(&key)
254 }
255
256 #[inline(always)]
257 pub fn attr_key(&self, key: &str) -> Option<usize> {
258 self.attr_keys.iter().position(|r| r == key)
259 }
260
261 #[inline(always)]
262 pub fn attr_key_or_create(&mut self, key: &str) -> usize {
263 match self.attr_keys.iter().position(|r| r == key) {
264 Some(v) => v,
265 None => {
266 let len = self.attr_keys.len();
267 self.attr_keys.push(key.to_string());
268 len
269 }
270 }
271 }
272}
273
274#[derive(Debug)]
275pub enum AttrValue<'a> {
276 String(&'a str),
277 Bytes(&'a [u8]),
278 Json(serde_json::Value),
279}
280
281impl AttrValue<'_> {
282 pub fn as_bytes(&self) -> Cow<'_, [u8]> {
283 match self {
284 AttrValue::String(x) => Cow::Borrowed(x.as_bytes()),
285 AttrValue::Bytes(x) => Cow::Borrowed(*x),
286 AttrValue::Json(x) => Cow::Owned(serde_json::to_vec(x).unwrap()),
287 }
288 }
289}
290
291impl Display for AttrValue<'_> {
292 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
293 match self {
294 AttrValue::String(v) => f.write_str(v),
295 AttrValue::Bytes(bytes) => {
296 let mut bytes = bytes.iter();
297 if let Some(v) = bytes.next() {
298 f.write_fmt(format_args!("{:02x}", v))?;
299 }
300 for b in bytes {
301 f.write_fmt(format_args!(" {:02x}", b))?;
302 }
303 Ok(())
304 }
305 AttrValue::Json(value) => {
306 let v = serde_json::to_string_pretty(value).unwrap();
307 f.write_str(&v)
308 }
309 }
310 }
311}