pathbufd/
lib.rs

1use std::collections::TryReserveError;
2use std::env::current_dir;
3use std::ffi::{OsStr, OsString};
4use std::fmt::{Arguments, Display};
5use std::path::{Path, PathBuf};
6use std::cmp::Eq;
7
8use serde::{Deserialize, Serialize};
9
10/// [`PathBuf`] wrapper
11#[derive(Serialize, Deserialize, Clone, PartialEq, Eq, Debug)]
12pub struct PathBufD(PathBuf);
13
14impl PathBufD {
15    /// Creates a new [`PathBufD`]
16    pub fn new() -> Self {
17        Self(PathBuf::new())
18    }
19
20    /// Creates a new [`PathBufD`] with a given capacity.
21    pub fn with_capacity(capacity: usize) -> Self {
22        Self(PathBuf::with_capacity(capacity))
23    }
24
25    /// Creates a new [`PathBufD`] in the current directory
26    pub fn current() -> Self {
27        Self(current_dir().unwrap_or(PathBuf::new()))
28    }
29
30    /// Coerces to a [`Path`] slice.
31    pub fn as_path(&self) -> &Path {
32        self.0.as_path()
33    }
34
35    /// Gets `Vec<u8>` representation of the inner string.
36    pub fn as_bytes(&self) -> Vec<u8> {
37        self.to_string().as_bytes().to_owned()
38    }
39
40    /// Extends self with path.
41    pub fn push<P>(&mut self, path: P) -> ()
42    where
43        P: AsRef<Path>,
44    {
45        self.0.push(path)
46    }
47
48    /// Creates an owned [`PathBufD`] with path adjoined to self.
49    pub fn join<P>(&self, path: P) -> Self
50    where
51        P: AsRef<Path>,
52    {
53        Self(self.0.join(path))
54    }
55
56    /// Truncates `self` to [`self.parent`]
57    ///
58    /// Returns `false` and does nothing if [`self.parent`] is [`None`].
59    /// Otherwise, returns `true`.
60    ///
61    /// [`self.parent`]: Path::parent
62    pub fn pop(&mut self) -> bool {
63        self.0.pop()
64    }
65
66    /// Updates [`self.file_name`] to `file_name`
67    ///
68    /// [`self.file_name`]: Path::file_name
69    pub fn set_file_name<S>(&mut self, file_name: S)
70    where
71        S: AsRef<OsStr>,
72    {
73        self.0.set_file_name(file_name);
74    }
75
76    /// Updates [`self.extension`] to `Some(extension)` or to `None` if `extension` is empty.
77    ///
78    /// [`self.extension`]: Path::extension
79    pub fn set_extension<S>(&mut self, extension: S)
80    where
81        S: AsRef<OsStr>,
82    {
83        self.0.set_extension(extension);
84    }
85
86    /// Yields a mutable reference to the underlying [`OsString`] instance.
87    pub fn as_mut_os_string(&mut self) -> &mut OsString {
88        self.0.as_mut_os_string()
89    }
90
91    /// Consumes the [`PathBufD`], yielding its internal [`OsString`] storage.
92    pub fn into_os_string(self) -> OsString {
93        self.0.into_os_string()
94    }
95
96    /// Converts this [`PathBufD`] into a [boxed](Box) [`Path`].
97    pub fn into_boxed_path(self) -> Box<Path> {
98        self.0.into_boxed_path()
99    }
100
101    /// Invokes [`capacity`] on the underlying instance of [`OsString`].
102    pub fn capacity(&self) -> usize {
103        self.0.capacity()
104    }
105
106    /// Invokes [`clear`] on the underlying instance of [`OsString`].
107    ///
108    /// [`clear`]: OsString::clear
109    pub fn clear(&mut self) -> () {
110        self.0.clear()
111    }
112
113    /// Invokes [`reserve`] on the underlying instance of [`OsString`].
114    ///
115    /// [`reserve`]: OsString::reserve
116    pub fn reserve(&mut self, additional: usize) -> () {
117        self.0.reserve(additional)
118    }
119
120    /// Invokes [`try_reserve`] on the underlying instance of [`OsString`].
121    ///
122    /// [`try_reserve`]: OsString::try_reserve
123    pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> {
124        self.0.try_reserve(additional)
125    }
126
127    /// Invokes [`reserve_exact`] on the underlying instance of [`OsString`].
128    ///
129    /// [`reserve_exact`]: OsString::reserve_exact
130    pub fn reserve_exact(&mut self, additional: usize) -> () {
131        self.0.reserve_exact(additional)
132    }
133
134    /// Invokes [`try_reserve_exact`] on the underlying instance of [`OsString`].
135    ///
136    /// [`try_reserve_exact`]: OsString::try_reserve_exact
137    pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError> {
138        self.0.try_reserve_exact(additional)
139    }
140
141    /// Invokes [`shrink_to_fit`] on the underlying instance of [`OsString`].
142    ///
143    /// [`shrink_to_fit`]: OsString::shrink_to_fit
144    pub fn shrink_to_fit(&mut self) {
145        self.0.shrink_to_fit()
146    }
147
148    /// Invokes [`shrink_to`] on the underlying instance of [`OsString`].
149    ///
150    /// [`shrink_to`]: OsString::shrink_to
151    pub fn shrink_to(&mut self, min_capacity: usize) -> () {
152        self.0.shrink_to(min_capacity)
153    }
154
155    /// Creates an owned [`PathBufD`] with all paths from `paths` adjoined to self.
156    pub fn extend<P>(self, paths: &[P]) -> Self
157    where
158        P: AsRef<Path>,
159    {
160        let mut buf = self;
161
162        for path in paths {
163            buf.push(path)
164        }
165
166        buf
167    }
168}
169
170impl Default for PathBufD {
171    fn default() -> Self {
172        Self(PathBuf::default())
173    }
174}
175
176impl Display for PathBufD {
177    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
178        write!(f, "{}", self.0.to_str().unwrap_or(""))
179    }
180}
181
182impl AsRef<Path> for PathBufD {
183    fn as_ref(&self) -> &Path {
184        self.as_path()
185    }
186}
187
188impl Into<PathBufD> for PathBuf {
189    fn into(self) -> PathBufD {
190        PathBufD(self)
191    }
192}
193
194impl From<PathBufD> for PathBuf {
195    fn from(value: PathBufD) -> Self {
196        value.0
197    }
198}
199
200// macro
201/// Format [`Arguments`] into a [`PathBufD`]
202pub fn pathbufd_fmt(args: Arguments) -> PathBufD {
203    let string = if let Some(s) = args.as_str() {
204        s
205    } else {
206        &args.to_string()
207    };
208
209    let mut pathbufd = PathBufD::new();
210    for split in string.split("/") {
211        if split.is_empty() {
212            pathbufd.push("/");
213            continue;
214        }
215
216        pathbufd.push(split);
217    }
218
219    return pathbufd;
220}
221
222#[macro_export]
223macro_rules! pathd {
224    ($($arg:tt)*) => {
225        pathbufd::pathbufd_fmt(std::format_args!($($arg)*)).to_string()
226    }
227}