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(())
}
}
}