Skip to main content

yazi_shared/path/
buf.rs

1use std::{borrow::Cow, ffi::OsString, hash::{Hash, Hasher}};
2
3use hashbrown::Equivalent;
4
5use crate::{path::{AsPath, Component, PathDyn, PathDynError, PathKind, SetNameError}, strand::AsStrand, wtf8::FromWtf8Vec};
6
7// --- PathBufDyn
8#[derive(Clone, Debug, Eq)]
9pub enum PathBufDyn {
10	Os(std::path::PathBuf),
11	Unix(typed_path::UnixPathBuf),
12}
13
14impl From<&std::path::Path> for PathBufDyn {
15	fn from(value: &std::path::Path) -> Self { Self::Os(value.into()) }
16}
17
18impl From<std::path::PathBuf> for PathBufDyn {
19	fn from(value: std::path::PathBuf) -> Self { Self::Os(value) }
20}
21
22impl From<typed_path::UnixPathBuf> for PathBufDyn {
23	fn from(value: typed_path::UnixPathBuf) -> Self { Self::Unix(value) }
24}
25
26impl From<PathDyn<'_>> for PathBufDyn {
27	fn from(value: PathDyn<'_>) -> Self { value.to_owned() }
28}
29
30impl From<Cow<'_, std::path::Path>> for PathBufDyn {
31	fn from(value: Cow<'_, std::path::Path>) -> Self { Self::Os(value.into_owned()) }
32}
33
34impl TryFrom<PathBufDyn> for std::path::PathBuf {
35	type Error = PathDynError;
36
37	fn try_from(value: PathBufDyn) -> Result<Self, Self::Error> { value.into_os() }
38}
39
40impl TryFrom<PathBufDyn> for typed_path::UnixPathBuf {
41	type Error = PathDynError;
42
43	fn try_from(value: PathBufDyn) -> Result<Self, Self::Error> { value.into_unix() }
44}
45
46// --- Hash
47impl Hash for PathBufDyn {
48	fn hash<H: Hasher>(&self, state: &mut H) { self.as_path().hash(state) }
49}
50
51// --- PartialEq
52impl PartialEq for PathBufDyn {
53	fn eq(&self, other: &Self) -> bool { self.as_path() == other.as_path() }
54}
55
56impl PartialEq<PathDyn<'_>> for PathBufDyn {
57	fn eq(&self, other: &PathDyn<'_>) -> bool { self.as_path() == *other }
58}
59
60impl PartialEq<PathDyn<'_>> for &PathBufDyn {
61	fn eq(&self, other: &PathDyn<'_>) -> bool { self.as_path() == *other }
62}
63
64impl Equivalent<PathDyn<'_>> for PathBufDyn {
65	fn equivalent(&self, key: &PathDyn<'_>) -> bool { self.as_path() == *key }
66}
67
68impl PathBufDyn {
69	#[inline]
70	pub unsafe fn from_encoded_bytes<K>(kind: K, bytes: Vec<u8>) -> Self
71	where
72		K: Into<PathKind>,
73	{
74		match kind.into() {
75			PathKind::Os => Self::Os(unsafe { OsString::from_encoded_bytes_unchecked(bytes) }.into()),
76			PathKind::Unix => Self::Unix(bytes.into()),
77		}
78	}
79
80	#[inline]
81	pub fn from_components<'a, K, I>(kind: K, iter: I) -> Result<Self, PathDynError>
82	where
83		K: Into<PathKind>,
84		I: IntoIterator<Item = Component<'a>>,
85	{
86		Ok(match kind.into() {
87			PathKind::Os => Self::Os(iter.into_iter().collect::<Result<_, PathDynError>>()?),
88			PathKind::Unix => Self::Unix(iter.into_iter().collect::<Result<_, PathDynError>>()?),
89		})
90	}
91
92	pub fn into_encoded_bytes(self) -> Vec<u8> {
93		match self {
94			Self::Os(p) => p.into_os_string().into_encoded_bytes(),
95			Self::Unix(p) => p.into_vec(),
96		}
97	}
98
99	#[inline]
100	pub fn into_os(self) -> Result<std::path::PathBuf, PathDynError> {
101		Ok(match self {
102			Self::Os(p) => p,
103			Self::Unix(_) => Err(PathDynError::AsOs)?,
104		})
105	}
106
107	#[inline]
108	pub fn into_unix(self) -> Result<typed_path::UnixPathBuf, PathDynError> {
109		Ok(match self {
110			Self::Os(_) => Err(PathDynError::AsUnix)?,
111			Self::Unix(p) => p,
112		})
113	}
114
115	#[inline]
116	pub fn new(kind: PathKind) -> Self {
117		match kind {
118			PathKind::Os => Self::Os(std::path::PathBuf::new()),
119			PathKind::Unix => Self::Unix(typed_path::UnixPathBuf::new()),
120		}
121	}
122
123	pub fn try_extend<T>(&mut self, paths: T) -> Result<(), PathDynError>
124	where
125		T: IntoIterator,
126		T::Item: AsPath,
127	{
128		for p in paths {
129			self.try_push(p)?;
130		}
131		Ok(())
132	}
133
134	pub fn try_push<T>(&mut self, path: T) -> Result<(), PathDynError>
135	where
136		T: AsPath,
137	{
138		let path = path.as_path();
139		Ok(match self {
140			Self::Os(p) => p.push(path.as_os()?),
141			Self::Unix(p) => p.push(path.encoded_bytes()),
142		})
143	}
144
145	pub fn try_set_name<T>(&mut self, name: T) -> Result<(), SetNameError>
146	where
147		T: AsStrand,
148	{
149		let s = name.as_strand();
150		Ok(match self {
151			Self::Os(p) => p.set_file_name(s.as_os()?),
152			Self::Unix(p) => p.set_file_name(s.encoded_bytes()),
153		})
154	}
155
156	pub fn with<K>(kind: K, bytes: Vec<u8>) -> Result<Self, PathDynError>
157	where
158		K: Into<PathKind>,
159	{
160		Ok(match kind.into() {
161			PathKind::Os => {
162				Self::Os(std::path::PathBuf::from_wtf8_vec(bytes).map_err(|_| PathDynError::AsOs)?)
163			}
164			PathKind::Unix => Self::Unix(bytes.into()),
165		})
166	}
167
168	pub fn with_capacity<K>(kind: K, capacity: usize) -> Self
169	where
170		K: Into<PathKind>,
171	{
172		match kind.into() {
173			PathKind::Os => Self::Os(std::path::PathBuf::with_capacity(capacity)),
174			PathKind::Unix => Self::Unix(typed_path::UnixPathBuf::with_capacity(capacity)),
175		}
176	}
177
178	pub fn with_str<K, S>(kind: K, s: S) -> Self
179	where
180		K: Into<PathKind>,
181		S: Into<String>,
182	{
183		let s = s.into();
184		match kind.into() {
185			PathKind::Os => Self::Os(s.into()),
186			PathKind::Unix => Self::Unix(s.into()),
187		}
188	}
189}