1use crate::builder::Str; 2 3/// A UTF-8-encoded fixed string 4/// 5/// **NOTE:** To support dynamic values (i.e. `OsString`), enable the [`string` 6/// feature][crate::_features] 7#[derive(Default, Clone, Eq, PartialEq, PartialOrd, Ord, Hash)] 8pub struct OsStr { 9 name: Inner, 10} 11 12impl OsStr { 13 #[cfg(feature = "string")] 14 pub(crate) fn from_string(name: std::ffi::OsString) -> Self { 15 Self { 16 name: Inner::from_string(name), 17 } 18 } 19 20 #[cfg(feature = "string")] 21 pub(crate) fn from_ref(name: &std::ffi::OsStr) -> Self { 22 Self { 23 name: Inner::from_ref(name), 24 } 25 } 26 27 pub(crate) fn from_static_ref(name: &'static std::ffi::OsStr) -> Self { 28 Self { 29 name: Inner::from_static_ref(name), 30 } 31 } 32 33 /// Get the raw string as an `std::ffi::OsStr` 34 pub fn as_os_str(&self) -> &std::ffi::OsStr { 35 self.name.as_os_str() 36 } 37 38 /// Get the raw string as an `OsString` 39 pub fn to_os_string(&self) -> std::ffi::OsString { 40 self.as_os_str().to_owned() 41 } 42} 43 44impl From<&'_ OsStr> for OsStr { 45 fn from(id: &'_ OsStr) -> Self { 46 id.clone() 47 } 48} 49 50#[cfg(feature = "string")] 51impl From<Str> for OsStr { 52 fn from(id: Str) -> Self { 53 match id.into_inner() { 54 crate::builder::StrInner::Static(s) => Self::from_static_ref(std::ffi::OsStr::new(s)), 55 crate::builder::StrInner::Owned(s) => Self::from_ref(std::ffi::OsStr::new(s.as_ref())), 56 } 57 } 58} 59 60#[cfg(not(feature = "string"))] 61impl From<Str> for OsStr { 62 fn from(id: Str) -> Self { 63 Self::from_static_ref(std::ffi::OsStr::new(id.into_inner().0)) 64 } 65} 66 67#[cfg(feature = "perf")] 68impl From<&'_ Str> for OsStr { 69 fn from(id: &'_ Str) -> Self { 70 match id.clone().into_inner() { 71 crate::builder::StrInner::Static(s) => Self::from_static_ref(std::ffi::OsStr::new(s)), 72 crate::builder::StrInner::Owned(s) => Self::from_ref(std::ffi::OsStr::new(s.as_ref())), 73 } 74 } 75} 76 77impl From<&'_ Str> for OsStr { 78 fn from(id: &'_ Str) -> Self { 79 id.clone().into() 80 } 81} 82 83#[cfg(feature = "string")] 84impl From<std::ffi::OsString> for OsStr { 85 fn from(name: std::ffi::OsString) -> Self { 86 Self::from_string(name) 87 } 88} 89 90#[cfg(feature = "string")] 91impl From<&'_ std::ffi::OsString> for OsStr { 92 fn from(name: &'_ std::ffi::OsString) -> Self { 93 Self::from_ref(name.as_os_str()) 94 } 95} 96 97#[cfg(feature = "string")] 98impl From<std::string::String> for OsStr { 99 fn from(name: std::string::String) -> Self { 100 Self::from_string(name.into()) 101 } 102} 103 104#[cfg(feature = "string")] 105impl From<&'_ std::string::String> for OsStr { 106 fn from(name: &'_ std::string::String) -> Self { 107 Self::from_ref(name.as_str().as_ref()) 108 } 109} 110 111impl From<&'static std::ffi::OsStr> for OsStr { 112 fn from(name: &'static std::ffi::OsStr) -> Self { 113 Self::from_static_ref(name) 114 } 115} 116 117impl From<&'_ &'static std::ffi::OsStr> for OsStr { 118 fn from(name: &'_ &'static std::ffi::OsStr) -> Self { 119 Self::from_static_ref(name) 120 } 121} 122 123impl From<&'static str> for OsStr { 124 fn from(name: &'static str) -> Self { 125 Self::from_static_ref(name.as_ref()) 126 } 127} 128 129impl From<&'_ &'static str> for OsStr { 130 fn from(name: &'_ &'static str) -> Self { 131 Self::from_static_ref((*name).as_ref()) 132 } 133} 134 135impl From<OsStr> for std::ffi::OsString { 136 fn from(name: OsStr) -> Self { 137 name.name.into_os_string() 138 } 139} 140 141impl From<OsStr> for std::path::PathBuf { 142 fn from(name: OsStr) -> Self { 143 std::ffi::OsString::from(name).into() 144 } 145} 146 147impl std::fmt::Debug for OsStr { 148 #[inline] 149 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 150 std::fmt::Debug::fmt(self.as_os_str(), f) 151 } 152} 153 154impl std::ops::Deref for OsStr { 155 type Target = std::ffi::OsStr; 156 157 #[inline] 158 fn deref(&self) -> &std::ffi::OsStr { 159 self.as_os_str() 160 } 161} 162 163impl AsRef<std::ffi::OsStr> for OsStr { 164 #[inline] 165 fn as_ref(&self) -> &std::ffi::OsStr { 166 self.as_os_str() 167 } 168} 169 170impl AsRef<std::path::Path> for OsStr { 171 #[inline] 172 fn as_ref(&self) -> &std::path::Path { 173 std::path::Path::new(self) 174 } 175} 176 177impl std::borrow::Borrow<std::ffi::OsStr> for OsStr { 178 #[inline] 179 fn borrow(&self) -> &std::ffi::OsStr { 180 self.as_os_str() 181 } 182} 183 184impl PartialEq<str> for OsStr { 185 #[inline] 186 fn eq(&self, other: &str) -> bool { 187 PartialEq::eq(self.as_os_str(), other) 188 } 189} 190impl PartialEq<OsStr> for str { 191 #[inline] 192 fn eq(&self, other: &OsStr) -> bool { 193 PartialEq::eq(self, other.as_os_str()) 194 } 195} 196 197impl PartialEq<&'_ str> for OsStr { 198 #[inline] 199 fn eq(&self, other: &&str) -> bool { 200 PartialEq::eq(self.as_os_str(), *other) 201 } 202} 203impl PartialEq<OsStr> for &'_ str { 204 #[inline] 205 fn eq(&self, other: &OsStr) -> bool { 206 PartialEq::eq(*self, other.as_os_str()) 207 } 208} 209 210impl PartialEq<&'_ std::ffi::OsStr> for OsStr { 211 #[inline] 212 fn eq(&self, other: &&std::ffi::OsStr) -> bool { 213 PartialEq::eq(self.as_os_str(), *other) 214 } 215} 216impl PartialEq<OsStr> for &'_ std::ffi::OsStr { 217 #[inline] 218 fn eq(&self, other: &OsStr) -> bool { 219 PartialEq::eq(*self, other.as_os_str()) 220 } 221} 222 223impl PartialEq<std::string::String> for OsStr { 224 #[inline] 225 fn eq(&self, other: &std::string::String) -> bool { 226 PartialEq::eq(self.as_os_str(), other.as_str()) 227 } 228} 229impl PartialEq<OsStr> for std::string::String { 230 #[inline] 231 fn eq(&self, other: &OsStr) -> bool { 232 PartialEq::eq(self.as_str(), other.as_os_str()) 233 } 234} 235 236impl PartialEq<std::ffi::OsString> for OsStr { 237 #[inline] 238 fn eq(&self, other: &std::ffi::OsString) -> bool { 239 PartialEq::eq(self.as_os_str(), other.as_os_str()) 240 } 241} 242impl PartialEq<OsStr> for std::ffi::OsString { 243 #[inline] 244 fn eq(&self, other: &OsStr) -> bool { 245 PartialEq::eq(self.as_os_str(), other.as_os_str()) 246 } 247} 248 249#[cfg(feature = "string")] 250pub(crate) mod inner { 251 #[derive(Clone)] 252 pub(crate) enum Inner { 253 Static(&'static std::ffi::OsStr), 254 Owned(Box<std::ffi::OsStr>), 255 } 256 257 impl Inner { 258 pub(crate) fn from_string(name: std::ffi::OsString) -> Self { 259 Self::Owned(name.into_boxed_os_str()) 260 } 261 262 pub(crate) fn from_ref(name: &std::ffi::OsStr) -> Self { 263 Self::Owned(Box::from(name)) 264 } 265 266 pub(crate) fn from_static_ref(name: &'static std::ffi::OsStr) -> Self { 267 Self::Static(name) 268 } 269 270 pub(crate) fn as_os_str(&self) -> &std::ffi::OsStr { 271 match self { 272 Self::Static(s) => s, 273 Self::Owned(s) => s.as_ref(), 274 } 275 } 276 277 pub(crate) fn into_os_string(self) -> std::ffi::OsString { 278 self.as_os_str().to_owned() 279 } 280 } 281} 282 283#[cfg(not(feature = "string"))] 284pub(crate) mod inner { 285 #[derive(Clone)] 286 pub(crate) struct Inner(&'static std::ffi::OsStr); 287 288 impl Inner { 289 pub(crate) fn from_static_ref(name: &'static std::ffi::OsStr) -> Self { 290 Self(name) 291 } 292 293 pub(crate) fn as_os_str(&self) -> &std::ffi::OsStr { 294 self.0 295 } 296 297 pub(crate) fn into_os_string(self) -> std::ffi::OsString { 298 self.as_os_str().to_owned() 299 } 300 } 301} 302 303pub(crate) use inner::Inner; 304 305impl Default for Inner { 306 fn default() -> Self { 307 Self::from_static_ref(std::ffi::OsStr::new("")) 308 } 309} 310 311impl PartialEq for Inner { 312 fn eq(&self, other: &Inner) -> bool { 313 self.as_os_str() == other.as_os_str() 314 } 315} 316 317impl PartialOrd for Inner { 318 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> { 319 self.as_os_str().partial_cmp(other.as_os_str()) 320 } 321} 322 323impl Ord for Inner { 324 fn cmp(&self, other: &Inner) -> std::cmp::Ordering { 325 self.as_os_str().cmp(other.as_os_str()) 326 } 327} 328 329impl Eq for Inner {} 330 331impl std::hash::Hash for Inner { 332 #[inline] 333 fn hash<H: std::hash::Hasher>(&self, state: &mut H) { 334 self.as_os_str().hash(state); 335 } 336} 337