122 lines
2.1 KiB
Rust
122 lines
2.1 KiB
Rust
|
|
use std::ffi::{OsStr, OsString};
|
||
|
|
use std::fmt::{Debug, Formatter};
|
||
|
|
use std::hash::{Hash, Hasher};
|
||
|
|
use std::ops::{Add, AddAssign};
|
||
|
|
use std::os::unix::ffi::OsStrExt;
|
||
|
|
|
||
|
|
#[derive(Clone, Default, Eq)]
|
||
|
|
pub struct OsStringBuilder {
|
||
|
|
result: OsString,
|
||
|
|
}
|
||
|
|
|
||
|
|
impl OsStringBuilder {
|
||
|
|
pub fn from(s: impl AsRef<OsStr>) -> Self {
|
||
|
|
Self {
|
||
|
|
result: s.as_ref().to_os_string(),
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
pub fn build(&self) -> OsString {
|
||
|
|
self.result.clone()
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
impl From<OsStringBuilder> for OsString {
|
||
|
|
fn from(value: OsStringBuilder) -> Self {
|
||
|
|
value.result
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
impl Debug for OsStringBuilder {
|
||
|
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||
|
|
Debug::fmt(&self.result, f)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
impl AsRef<OsStr> for OsStringBuilder {
|
||
|
|
fn as_ref(&self) -> &OsStr {
|
||
|
|
self.result.as_ref()
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
impl<P> Add<P> for OsStringBuilder
|
||
|
|
where
|
||
|
|
P: AsRef<OsStr>,
|
||
|
|
{
|
||
|
|
type Output = Self;
|
||
|
|
|
||
|
|
fn add(mut self, rhs: P) -> Self::Output {
|
||
|
|
self.result.push(rhs);
|
||
|
|
self
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
impl<P> AddAssign<P> for OsStringBuilder
|
||
|
|
where
|
||
|
|
P: AsRef<OsStr>,
|
||
|
|
{
|
||
|
|
fn add_assign(&mut self, rhs: P) {
|
||
|
|
self.result.push(rhs);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
impl<P> PartialEq<P> for OsStringBuilder
|
||
|
|
where
|
||
|
|
P: AsRef<OsStr>,
|
||
|
|
{
|
||
|
|
fn eq(&self, other: &P) -> bool {
|
||
|
|
self.result == other.as_ref()
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
impl Hash for OsStringBuilder {
|
||
|
|
fn hash<H: Hasher>(&self, state: &mut H) {
|
||
|
|
self.result.hash(state);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
pub fn ensure_trailing_slash(path: impl AsRef<OsStr>) -> OsString {
|
||
|
|
let mut str = path.as_ref().to_os_string();
|
||
|
|
if !str.as_bytes().ends_with(b"/") {
|
||
|
|
str.push("/")
|
||
|
|
}
|
||
|
|
str
|
||
|
|
}
|
||
|
|
|
||
|
|
#[macro_export]
|
||
|
|
macro_rules! dir {
|
||
|
|
($path:expr) => {{
|
||
|
|
use $crate::os_string_builder::ensure_trailing_slash;
|
||
|
|
ensure_trailing_slash($path)
|
||
|
|
}};
|
||
|
|
}
|
||
|
|
|
||
|
|
#[macro_export]
|
||
|
|
macro_rules! osf {
|
||
|
|
() => {{
|
||
|
|
use $crate::os_string_builder::OsStringBuilder;
|
||
|
|
OsStringBuilder::default()
|
||
|
|
}};
|
||
|
|
($s:expr) => {
|
||
|
|
osf!() + $s
|
||
|
|
};
|
||
|
|
}
|
||
|
|
|
||
|
|
#[cfg(test)]
|
||
|
|
mod test {
|
||
|
|
use std::path::PathBuf;
|
||
|
|
|
||
|
|
#[test]
|
||
|
|
fn test_build() {
|
||
|
|
assert_eq!(osf!("foo") + "Bar", "fooBar");
|
||
|
|
}
|
||
|
|
|
||
|
|
#[test]
|
||
|
|
fn test_add_dir() {
|
||
|
|
let foo = PathBuf::from("foo");
|
||
|
|
let bar = PathBuf::from("bar");
|
||
|
|
|
||
|
|
assert_eq!(osf!("cd ") + dir!(foo) + dir!(bar), "cd foo/bar/");
|
||
|
|
}
|
||
|
|
}
|