evobench_tools/utillib/
safe_string.rs

1//! Try to use data from the OS (OsString) as strings, if possible,
2//! fall back to the original data (lossless) if not possible.
3
4use std::{
5    convert::Infallible,
6    ffi::{OsStr, OsString},
7    str::FromStr,
8};
9
10#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, serde::Serialize, serde::Deserialize)]
11pub enum SafeString {
12    OsString(OsString),
13    String(String),
14}
15
16impl From<OsString> for SafeString {
17    fn from(value: OsString) -> Self {
18        match value.into_string() {
19            Ok(s) => Self::String(s),
20            Err(value) => Self::OsString(value),
21        }
22    }
23}
24
25impl From<String> for SafeString {
26    fn from(value: String) -> Self {
27        Self::String(value)
28    }
29}
30
31impl From<SafeString> for OsString {
32    fn from(value: SafeString) -> Self {
33        match value {
34            SafeString::OsString(os_string) => os_string,
35            SafeString::String(s) => OsString::from(s),
36        }
37    }
38}
39
40// Required for Clap. Hmm, but does it still handle byte fallbacks??
41impl FromStr for SafeString {
42    type Err = Infallible;
43
44    fn from_str(s: &str) -> Result<Self, Self::Err> {
45        Ok(s.to_owned().into())
46    }
47}
48
49impl AsRef<OsStr> for SafeString {
50    fn as_ref(&self) -> &OsStr {
51        match self {
52            SafeString::OsString(os_string) => os_string.as_ref(),
53            SafeString::String(s) => s.as_ref(),
54        }
55    }
56}
57
58// XX add *custom* Debug, custom eq and ord, as well as conversions
59// from references?