1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
use crate::{Bstr, Ustr, Ustring};
use std::{
    borrow::Cow,
    ffi::{CStr, CString, OsStr, OsString},
    fmt::Debug,
    ops::Deref,
    os::unix::ffi::{OsStrExt, OsStringExt},
    path::{Path, PathBuf},
};

/// Trait for objects which can be turned into `Cow<'a, Ustr>`
///
/// # Provided Implementations
///
/// The implementations for `&Ustr` and `Ustring` return `self` unchanged.
///
/// The other provided implementations for borrowed objects first check if the object has a trailing
/// nul byte. If so, this byte is used as the trailing nul byte for the `Ustr`. This means that
/// `IntoUstr` does not guarantee to round-trip. For example
///
/// ```
/// # use uapi::IntoUstr;
/// assert_eq!(b"abc", b"abc\0".into_ustr().as_bytes());
/// ```
pub trait IntoUstr<'a>: Debug {
    /// Converts `self` into `Cow<'a, Ustr>`
    fn into_ustr(self) -> Cow<'a, Ustr>;
}

impl<'a> IntoUstr<'a> for Cow<'a, Ustr> {
    fn into_ustr(self) -> Cow<'a, Ustr> {
        self
    }
}

impl<'a> IntoUstr<'a> for &'a Cow<'a, Ustr> {
    fn into_ustr(self) -> Cow<'a, Ustr> {
        self.deref().into_ustr()
    }
}

impl<'a> IntoUstr<'a> for &'a Ustr {
    fn into_ustr(self) -> Cow<'a, Ustr> {
        Cow::Borrowed(self)
    }
}

impl<'a> IntoUstr<'a> for &'a Ustring {
    fn into_ustr(self) -> Cow<'a, Ustr> {
        self.deref().into_ustr()
    }
}

impl IntoUstr<'static> for Ustring {
    fn into_ustr(self) -> Cow<'static, Ustr> {
        Cow::Owned(self)
    }
}

impl<'a> IntoUstr<'a> for &'a [u8] {
    fn into_ustr(self) -> Cow<'a, Ustr> {
        if let Some(s) = Ustr::from_bytes(self) {
            return Cow::Borrowed(s);
        }
        Cow::Owned(Ustring::from_vec(self.to_owned()))
    }
}

impl<'a> IntoUstr<'a> for &'a Bstr {
    fn into_ustr(self) -> Cow<'a, Ustr> {
        self.as_bytes().into_ustr()
    }
}

impl IntoUstr<'static> for Vec<u8> {
    fn into_ustr(self) -> Cow<'static, Ustr> {
        Cow::Owned(Ustring::from_vec(self))
    }
}

impl<'a> IntoUstr<'a> for &'a str {
    fn into_ustr(self) -> Cow<'a, Ustr> {
        self.as_bytes().into_ustr()
    }
}

impl IntoUstr<'static> for String {
    fn into_ustr(self) -> Cow<'static, Ustr> {
        self.into_bytes().into_ustr()
    }
}

impl<'a> IntoUstr<'a> for &'a CStr {
    fn into_ustr(self) -> Cow<'a, Ustr> {
        Cow::Borrowed(Ustr::from_c_str(self))
    }
}

impl IntoUstr<'static> for CString {
    fn into_ustr(self) -> Cow<'static, Ustr> {
        Cow::Owned(Ustring::from_c_string(self))
    }
}

impl<'a> IntoUstr<'a> for &'a OsStr {
    fn into_ustr(self) -> Cow<'a, Ustr> {
        self.as_bytes().into_ustr()
    }
}

impl IntoUstr<'static> for OsString {
    fn into_ustr(self) -> Cow<'static, Ustr> {
        self.into_vec().into_ustr()
    }
}

impl<'a> IntoUstr<'a> for &'a Path {
    fn into_ustr(self) -> Cow<'a, Ustr> {
        self.as_os_str().into_ustr()
    }
}

impl IntoUstr<'static> for PathBuf {
    fn into_ustr(self) -> Cow<'static, Ustr> {
        self.into_os_string().into_ustr()
    }
}