aopt_core/
str.rs

1use std::borrow::Cow;
2use std::ffi::OsStr;
3use std::ffi::OsString;
4
5#[cfg(target_family = "windows")]
6pub fn split_once(str: &OsStr, ch: char) -> Option<(Cow<'_, OsStr>, Cow<'_, OsStr>)> {
7    use std::ffi::OsString;
8    use std::os::windows::ffi::{OsStrExt, OsStringExt};
9
10    let enc = str.encode_wide();
11    let mut buf = [0; 1];
12    let sep = ch.encode_utf16(&mut buf);
13    let enc = enc.collect::<Vec<u16>>();
14
15    enc.iter()
16        .enumerate()
17        .find(|(_, ch)| ch == &&sep[0])
18        .map(|(i, _)| {
19            (
20                Cow::Owned(OsString::from_wide(&enc[0..i])),
21                Cow::Owned(OsString::from_wide(&enc[i + 1..])),
22            )
23        })
24}
25
26#[cfg(any(target_family = "wasm", target_family = "unix"))]
27pub fn split_once(str: &'_ OsStr, ch: char) -> Option<(Cow<'_, OsStr>, Cow<'_, OsStr>)> {
28    #[cfg(target_family = "unix")]
29    use std::os::unix::ffi::OsStrExt;
30    #[cfg(target_family = "wasm")]
31    use std::os::wasi::ffi::OsStrExt;
32
33    let enc = str.as_bytes();
34    let mut buf = [0; 1];
35    let sep = ch.encode_utf8(&mut buf).as_bytes();
36
37    enc.iter()
38        .enumerate()
39        .find(|(_, ch)| ch == &&sep[0])
40        .map(|(i, _)| {
41            (
42                Cow::Borrowed(OsStr::from_bytes(&enc[0..i])),
43                Cow::Borrowed(OsStr::from_bytes(&enc[i + 1..])),
44            )
45        })
46}
47
48/// Convert a [`OsStr`] to [`Cow<'_, str>`].
49pub fn osstr_to_str_i<'a>(val: &[&'a OsStr], i: usize) -> Option<Cow<'a, str>> {
50    val.get(i).and_then(|v| v.to_str().map(Cow::Borrowed))
51}
52
53pub fn display_of_str(val: Option<&str>) -> String {
54    if let Some(val) = val {
55        format!("Some({})", val)
56    } else {
57        "None".to_string()
58    }
59}
60
61pub fn display_of_osstr(val: Option<&OsStr>) -> String {
62    if let Some(val) = val {
63        format!("Some({})", std::path::Path::new(val).display())
64    } else {
65        "None".to_string()
66    }
67}
68
69pub trait CowOsStrUtils<'a> {
70    fn split_once(&self, sep: char) -> Option<(Cow<'a, OsStr>, Cow<'a, OsStr>)>;
71
72    fn to_str(&self, func: impl Fn(&str) -> &str) -> Option<Cow<'a, str>>;
73}
74
75impl<'a> CowOsStrUtils<'a> for Cow<'a, OsStr> {
76    fn split_once(&self, sep: char) -> Option<(Cow<'a, OsStr>, Cow<'a, OsStr>)> {
77        match self {
78            Cow::Borrowed(v) => split_once(v, sep),
79            Cow::Owned(v) => split_once(v, sep)
80                .map(|(a, b)| (Cow::Owned(a.into_owned()), Cow::Owned(b.into_owned()))),
81        }
82    }
83
84    fn to_str(&self, func: impl Fn(&str) -> &str) -> Option<Cow<'a, str>> {
85        match &self {
86            Cow::Borrowed(v) => v.to_str().map(func).map(Cow::Borrowed),
87            Cow::Owned(v) => v.to_str().map(func).map(String::from).map(Cow::Owned),
88        }
89    }
90}
91
92pub trait CowStrUtils<'a> {
93    fn split_at(&self, mid: usize) -> (Cow<'a, str>, Cow<'a, str>);
94
95    fn to_os_str(self) -> Cow<'a, OsStr>;
96}
97
98impl<'a> CowStrUtils<'a> for Cow<'a, str> {
99    fn split_at(&self, mid: usize) -> (Cow<'a, str>, Cow<'a, str>) {
100        match self {
101            Cow::Borrowed(v) => {
102                let (a, b) = v.split_at(mid);
103
104                (Cow::Borrowed(a), Cow::Borrowed(b))
105            }
106            Cow::Owned(v) => {
107                let (a, b) = v.split_at(mid);
108
109                (Cow::Owned(a.to_string()), Cow::Owned(b.to_string()))
110            }
111        }
112    }
113
114    fn to_os_str(self) -> Cow<'a, OsStr> {
115        match self {
116            Cow::Borrowed(v) => Cow::Borrowed(OsStr::new(v)),
117            Cow::Owned(v) => Cow::Owned(OsString::from(v)),
118        }
119    }
120}