1use alloc::string::String;
2use core::iter;
3
4#[derive(Debug, Ord, PartialOrd, Eq, PartialEq, Clone)]
7pub struct PathBuf(pub String);
8
9impl PathBuf {
10 pub fn new<S: AsRef<str>>(path: S) -> Self {
12 Self(String::from(path.as_ref()))
13 }
14 pub fn iter(&self) -> impl Iterator<Item = &str> {
16 iter::once("/").chain(self.0[1..].split_terminator('/'))
17 }
18 pub fn to_str(&self) -> &str {
20 self.0.as_str()
21 }
22 pub fn display(&self) -> &str {
24 self.to_str()
25 }
26 pub fn is_absolute(&self) -> bool {
28 self.0.starts_with('/')
29 }
30 pub fn parent(&self) -> Option<PathBuf> {
32 if self.0 == "/" {
33 return None;
34 }
35 let trimmed = self.0.trim_end_matches('/');
36 match trimmed.rfind('/') {
37 Some(0) => Some(PathBuf::from("/")),
38 Some(pos) => Some(PathBuf::from(&trimmed[..pos])),
39 None => None,
40 }
41 }
42 pub fn file_name(&self) -> Option<&str> {
44 let trimmed = self.0.trim_end_matches('/');
45 if trimmed.is_empty() {
46 return None;
47 }
48 match trimmed.rfind('/') {
49 Some(pos) => {
50 let name = &trimmed[pos + 1..];
51 if name.is_empty() { None } else { Some(name) }
52 }
53 None => Some(trimmed),
54 }
55 }
56 pub fn starts_with(&self, base: &PathBuf) -> bool {
58 let self_trimmed = self.0.trim_end_matches('/');
59 let base_trimmed = base.0.trim_end_matches('/');
60 if base_trimmed == "/" {
61 return self_trimmed.starts_with('/');
62 }
63 self_trimmed == base_trimmed
64 || self_trimmed.starts_with(&alloc::format!("{}/", base_trimmed))
65 }
66}
67impl core::fmt::Display for PathBuf {
68 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
69 write!(f, "{}", self.0)
70 }
71}
72impl PartialEq<String> for &PathBuf {
73 fn eq(&self, other: &String) -> bool {
74 other.as_str() == self.0.as_str()
75 }
76}
77impl PartialEq<&str> for &PathBuf {
78 fn eq(&self, other: &&str) -> bool {
79 *other == self.0.as_str()
80 }
81}
82impl PartialEq<&str> for PathBuf {
83 fn eq(&self, other: &&str) -> bool {
84 *other == self.0.as_str()
85 }
86}
87
88impl From<&str> for PathBuf {
89 fn from(s: &str) -> Self {
90 Self::new(s)
91 }
92}
93impl From<String> for PathBuf {
94 fn from(s: String) -> Self {
95 Self::new(s)
96 }
97}