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
use core::{fmt, str};
pub struct Path<'a> {
pub(crate) parent: Option<&'a Path<'a>>,
pub(crate) name: &'a [u8],
}
impl Path<'_> {
pub(crate) const ROOT: Self = Self {
parent: None,
name: &[],
};
#[inline]
pub fn level(&self) -> usize {
if let Some(parent) = self.parent {
parent.level() + 1
} else {
0
}
}
#[inline]
pub fn last(&self) -> &[u8] {
self.name
}
pub fn join(&self, buf: &mut [u8]) -> Result<usize, usize> {
let len = match self.parent {
Some(parent) => parent.join(buf)?,
None => return Ok(0),
};
match buf.len() - len {
0 => Err(buf.len()),
mut rest => {
buf[len] = b'/';
rest -= 1;
if self.name.len() > rest {
buf[len + 1..].copy_from_slice(&self.name[..rest]);
Err(buf.len())
} else {
buf[len + 1..][..self.name.len()].copy_from_slice(self.name);
Ok(len + self.name.len() + 1)
}
}
}
}
}
impl fmt::Display for Path<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if let Some(parent) = self.parent {
parent.fmt(f)?;
'/'.fmt(f)?;
unsafe { str::from_utf8_unchecked(self.name) }.fmt(f)
} else {
Ok(())
}
}
}