1use core::{fmt, str};
2
3pub struct Path<'a> {
5 pub(crate) parent: Option<&'a Path<'a>>,
6 pub(crate) name: &'a [u8],
7}
8
9impl Path<'_> {
10 pub(crate) const ROOT: Self = Self {
11 parent: None,
12 name: &[],
13 };
14
15 #[inline]
17 pub fn level(&self) -> usize {
18 if let Some(parent) = self.parent {
19 parent.level() + 1
20 } else {
21 0
22 }
23 }
24
25 #[inline]
27 pub fn last(&self) -> &[u8] {
28 self.name
29 }
30
31 pub fn join(&self, buf: &mut [u8]) -> Result<usize, usize> {
36 let len = match self.parent {
37 Some(parent) => parent.join(buf)?,
38 None => return Ok(0),
39 };
40 match buf.len() - len {
41 0 => Err(buf.len()),
42 mut rest => {
43 buf[len] = b'/';
44 rest -= 1;
45 if self.name.len() > rest {
46 buf[len + 1..].copy_from_slice(&self.name[..rest]);
47 Err(buf.len())
48 } else {
49 buf[len + 1..][..self.name.len()].copy_from_slice(self.name);
50 Ok(len + self.name.len() + 1)
51 }
52 }
53 }
54 }
55}
56
57impl fmt::Display for Path<'_> {
58 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
59 if let Some(parent) = self.parent {
60 parent.fmt(f)?;
61 '/'.fmt(f)?;
62 unsafe { str::from_utf8_unchecked(self.name) }.fmt(f)
63 } else {
64 Ok(())
65 }
66 }
67}