1use crate::ParsablePath;
2use core::marker::PhantomData;
3
4#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
6pub enum Component<'a> {
7 Prefix(&'a str),
9 Root,
11 CurDir,
13 ParentDir,
15 Normal(&'a str),
17}
18
19impl Component<'_> {
20 pub fn as_str(&self) -> &str {
22 match self {
23 Component::Prefix(s) => s,
24 Component::Root => "/",
25 Component::CurDir => ".",
26 Component::ParentDir => "..",
27 Component::Normal(s) => s,
28 }
29 }
30}
31
32#[cfg(feature = "std")]
33mod std_impls {
34 use super::*;
35 use std::path::Component as StdComponent;
36
37 impl<'a> TryFrom<StdComponent<'a>> for Component<'a> {
38 type Error = ();
39
40 fn try_from(c: StdComponent<'a>) -> Result<Self, Self::Error> {
41 match c {
42 StdComponent::Prefix(p) => Ok(Component::Prefix(p.as_os_str().to_str().ok_or(())?)),
43 StdComponent::RootDir => Ok(Component::Root),
44 StdComponent::CurDir => Ok(Component::CurDir),
45 StdComponent::ParentDir => Ok(Component::ParentDir),
46 StdComponent::Normal(p) => Ok(Component::Normal(p.to_str().ok_or(())?)),
47 }
48 }
49 }
50
51 impl PartialEq<StdComponent<'_>> for Component<'_> {
52 fn eq(&self, other: &StdComponent<'_>) -> bool {
53 match (self, other) {
54 (Component::Prefix(a), StdComponent::Prefix(b)) => {
55 Some(*a) == b.as_os_str().to_str()
56 }
57 (Component::Root, StdComponent::RootDir) => true,
58 (Component::CurDir, StdComponent::CurDir) => true,
59 (Component::ParentDir, StdComponent::ParentDir) => true,
60 (Component::Normal(a), StdComponent::Normal(b)) => a == b,
61 _ => false,
62 }
63 }
64 }
65
66 impl<'a> PartialEq<Component<'a>> for StdComponent<'a> {
67 fn eq(&self, other: &Component<'a>) -> bool {
68 other == self
69 }
70 }
71}
72
73pub struct Components<'a, P: ParsablePath> {
75 s: &'a str,
76 p: PhantomData<P>,
77 progressed_front: bool,
78 progressed_back: bool,
79}
80
81impl<'a, P: ParsablePath> Components<'a, P> {
82 pub fn new(s: &'a str) -> Self {
84 Self {
85 s,
86 p: PhantomData,
87 progressed_front: false,
88 progressed_back: false,
89 }
90 }
91}
92
93impl<'a, P: ParsablePath> Iterator for Components<'a, P> {
94 type Item = Component<'a>;
95
96 fn next(&mut self) -> Option<Self::Item> {
97 let (first, rest) = P::split_first_component(self.s, self.progressed_front);
98 self.progressed_front = true;
99 self.s = rest.unwrap_or("");
100 first
101 }
102}
103
104impl<P: ParsablePath> DoubleEndedIterator for Components<'_, P> {
105 fn next_back(&mut self) -> Option<Self::Item> {
106 let (rest, last) = P::split_last_component(self.s, self.progressed_back);
107 self.progressed_back = true;
108 self.s = rest.unwrap_or("");
109 last
110 }
111}