standard_lib/fs/path/
dispatch.rs1use std::{ffi::OsStr, num::NonZero, str::FromStr};
2
3use crate::fs::error::{EmptyStrError, HomeResolutionError};
4
5use super::{Abs, OwnedPath, Path, PathParseError, Rel};
6
7pub enum DispatchedPath {
10 Abs(OwnedPath<Abs>),
11 Rel(OwnedPath<Rel>),
12}
13
14impl FromStr for DispatchedPath {
15 type Err = PathParseError;
17
18 fn from_str(s: &str) -> Result<Self, Self::Err> {
19 match s.chars().next() {
20 Some('/') => {
21 Ok(DispatchedPath::Abs(
22 OwnedPath::from(s)
23 ))
24 },
25 Some('~') => {
27 Ok(DispatchedPath::Abs(
28 OwnedPath::from(&s[1..])
29 .resolve_home()
30 .ok_or(HomeResolutionError)?
31 ))
32 },
33 Some(_) => {
35 Ok(DispatchedPath::Rel(
36 OwnedPath::from(s)
37 ))
38 },
39 None => Err(EmptyStrError)?,
40 }
41 }
42}
43
44macro_rules! dispatch_ref {
45 ($this:ident.$name:ident) => {
46 match $this {
47 DispatchedPath::Abs(abs) => abs.$name(),
48 DispatchedPath::Rel(rel) => rel.$name(),
49 }
50 };
51}
52
53impl DispatchedPath {
54 pub fn abs_or_resolve(self, target: OwnedPath<Abs>) -> OwnedPath<Abs> {
55 match self {
56 DispatchedPath::Abs(abs) => abs,
57 DispatchedPath::Rel(rel) => rel.resolve(target),
58 }
59 }
60
61 pub fn rel_or_make_relative<P: AsRef<Path<Abs>>>(self, target: P) -> OwnedPath<Rel> {
62 match self {
63 DispatchedPath::Abs(abs) => abs.make_relative(target),
64 DispatchedPath::Rel(rel) => rel,
65 }
66 }
67
68 pub fn len(&self) -> NonZero<usize> {
69 match self {
DispatchedPath::Abs(abs) => abs.len(),
DispatchedPath::Rel(rel) => rel.len(),
}dispatch_ref!(self.len)
70 }
71
72 pub fn as_os_str(&self) -> &OsStr {
73 match self {
DispatchedPath::Abs(abs) => abs.as_os_str(),
DispatchedPath::Rel(rel) => rel.as_os_str(),
}dispatch_ref!(self.as_os_str)
74 }
75
76 pub fn as_os_str_no_lead(&self) -> &OsStr {
77 match self {
DispatchedPath::Abs(abs) => abs.as_os_str_no_lead(),
DispatchedPath::Rel(rel) => rel.as_os_str_no_lead(),
}dispatch_ref!(self.as_os_str_no_lead)
78 }
79
80 pub fn as_bytes(&self) -> &[u8] {
81 match self {
DispatchedPath::Abs(abs) => abs.as_bytes(),
DispatchedPath::Rel(rel) => rel.as_bytes(),
}dispatch_ref!(self.as_bytes)
82 }
83
84 pub fn basename(&self) -> &OsStr {
85 match self {
DispatchedPath::Abs(abs) => abs.basename(),
DispatchedPath::Rel(rel) => rel.basename(),
}dispatch_ref!(self.basename)
86 }
87}
88
89impl From<OwnedPath<Abs>> for DispatchedPath {
90 fn from(value: OwnedPath<Abs>) -> Self {
91 DispatchedPath::Abs(value)
92 }
93}
94
95impl From<OwnedPath<Rel>> for DispatchedPath {
96 fn from(value: OwnedPath<Rel>) -> Self {
97 DispatchedPath::Rel(value)
98 }
99}
100
101