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
48pub 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}