path.rs 1.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. use crate::prelude::*;
  2. use bindings::ENOENT;
  3. pub struct Path<'lt> {
  4. all: &'lt [u8],
  5. }
  6. pub struct PathIterator<'lt> {
  7. rem: &'lt [u8],
  8. }
  9. impl<'lt> Path<'lt> {
  10. pub fn new(all: &'lt [u8]) -> KResult<Self> {
  11. if all.is_empty() {
  12. Err(ENOENT)
  13. } else {
  14. Ok(Self { all })
  15. }
  16. }
  17. pub fn from_str(all: &'lt str) -> KResult<Self> {
  18. Self::new(all.as_bytes())
  19. }
  20. pub fn is_absolute(&self) -> bool {
  21. self.all.starts_with(&['/' as u8])
  22. }
  23. pub fn iter(&self) -> PathIterator<'lt> {
  24. PathIterator::new(self.all)
  25. }
  26. }
  27. impl<'lt> PathIterator<'lt> {
  28. fn new(all: &'lt [u8]) -> Self {
  29. Self { rem: all }
  30. }
  31. }
  32. #[derive(Debug)]
  33. pub enum PathComponent<'lt> {
  34. Name(&'lt [u8]),
  35. TrailingEmpty,
  36. Current,
  37. Parent,
  38. }
  39. impl<'lt> Iterator for PathIterator<'lt> {
  40. type Item = PathComponent<'lt>;
  41. fn next(&mut self) -> Option<Self::Item> {
  42. if self.rem.is_empty() {
  43. return None;
  44. }
  45. let trimmed = self
  46. .rem
  47. .iter()
  48. .position(|&c| c != '/' as u8)
  49. .map(|pos| self.rem.split_at(pos).1)
  50. .unwrap_or(&[]);
  51. let next_start = trimmed
  52. .iter()
  53. .position(|&c| c == '/' as u8)
  54. .unwrap_or(trimmed.len());
  55. let (cur, rem) = trimmed.split_at(next_start);
  56. self.rem = rem;
  57. match cur {
  58. cur if cur.is_empty() => Some(PathComponent::TrailingEmpty),
  59. cur if cur == b"." => Some(PathComponent::Current),
  60. cur if cur == b".." => Some(PathComponent::Parent),
  61. cur => Some(PathComponent::Name(cur)),
  62. }
  63. }
  64. }