1 use 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)] 8 pub struct OsStr { 9 name: Inner, 10 } 11 12 impl OsStr { 13 #[cfg(feature = "string")] from_string(name: std::ffi::OsString) -> Self14 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")] from_ref(name: &std::ffi::OsStr) -> Self21 pub(crate) fn from_ref(name: &std::ffi::OsStr) -> Self { 22 Self { 23 name: Inner::from_ref(name), 24 } 25 } 26 from_static_ref(name: &'static std::ffi::OsStr) -> Self27 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` as_os_str(&self) -> &std::ffi::OsStr34 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` to_os_string(&self) -> std::ffi::OsString39 pub fn to_os_string(&self) -> std::ffi::OsString { 40 self.as_os_str().to_owned() 41 } 42 } 43 44 impl From<&'_ OsStr> for OsStr { from(id: &'_ OsStr) -> Self45 fn from(id: &'_ OsStr) -> Self { 46 id.clone() 47 } 48 } 49 50 #[cfg(feature = "string")] 51 impl From<Str> for OsStr { from(id: Str) -> Self52 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"))] 61 impl From<Str> for OsStr { from(id: Str) -> Self62 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")] 68 impl From<&'_ Str> for OsStr { from(id: &'_ Str) -> Self69 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 77 impl From<&'_ Str> for OsStr { from(id: &'_ Str) -> Self78 fn from(id: &'_ Str) -> Self { 79 id.clone().into() 80 } 81 } 82 83 #[cfg(feature = "string")] 84 impl From<std::ffi::OsString> for OsStr { from(name: std::ffi::OsString) -> Self85 fn from(name: std::ffi::OsString) -> Self { 86 Self::from_string(name) 87 } 88 } 89 90 #[cfg(feature = "string")] 91 impl From<&'_ std::ffi::OsString> for OsStr { from(name: &'_ std::ffi::OsString) -> Self92 fn from(name: &'_ std::ffi::OsString) -> Self { 93 Self::from_ref(name.as_os_str()) 94 } 95 } 96 97 #[cfg(feature = "string")] 98 impl From<std::string::String> for OsStr { from(name: std::string::String) -> Self99 fn from(name: std::string::String) -> Self { 100 Self::from_string(name.into()) 101 } 102 } 103 104 #[cfg(feature = "string")] 105 impl From<&'_ std::string::String> for OsStr { from(name: &'_ std::string::String) -> Self106 fn from(name: &'_ std::string::String) -> Self { 107 Self::from_ref(name.as_str().as_ref()) 108 } 109 } 110 111 impl From<&'static std::ffi::OsStr> for OsStr { from(name: &'static std::ffi::OsStr) -> Self112 fn from(name: &'static std::ffi::OsStr) -> Self { 113 Self::from_static_ref(name) 114 } 115 } 116 117 impl From<&'_ &'static std::ffi::OsStr> for OsStr { from(name: &'_ &'static std::ffi::OsStr) -> Self118 fn from(name: &'_ &'static std::ffi::OsStr) -> Self { 119 Self::from_static_ref(name) 120 } 121 } 122 123 impl From<&'static str> for OsStr { from(name: &'static str) -> Self124 fn from(name: &'static str) -> Self { 125 Self::from_static_ref(name.as_ref()) 126 } 127 } 128 129 impl From<&'_ &'static str> for OsStr { from(name: &'_ &'static str) -> Self130 fn from(name: &'_ &'static str) -> Self { 131 Self::from_static_ref((*name).as_ref()) 132 } 133 } 134 135 impl From<OsStr> for std::ffi::OsString { from(name: OsStr) -> Self136 fn from(name: OsStr) -> Self { 137 name.name.into_os_string() 138 } 139 } 140 141 impl From<OsStr> for std::path::PathBuf { from(name: OsStr) -> Self142 fn from(name: OsStr) -> Self { 143 std::ffi::OsString::from(name).into() 144 } 145 } 146 147 impl std::fmt::Debug for OsStr { 148 #[inline] fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result149 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 150 std::fmt::Debug::fmt(self.as_os_str(), f) 151 } 152 } 153 154 impl std::ops::Deref for OsStr { 155 type Target = std::ffi::OsStr; 156 157 #[inline] deref(&self) -> &std::ffi::OsStr158 fn deref(&self) -> &std::ffi::OsStr { 159 self.as_os_str() 160 } 161 } 162 163 impl AsRef<std::ffi::OsStr> for OsStr { 164 #[inline] as_ref(&self) -> &std::ffi::OsStr165 fn as_ref(&self) -> &std::ffi::OsStr { 166 self.as_os_str() 167 } 168 } 169 170 impl AsRef<std::path::Path> for OsStr { 171 #[inline] as_ref(&self) -> &std::path::Path172 fn as_ref(&self) -> &std::path::Path { 173 std::path::Path::new(self) 174 } 175 } 176 177 impl std::borrow::Borrow<std::ffi::OsStr> for OsStr { 178 #[inline] borrow(&self) -> &std::ffi::OsStr179 fn borrow(&self) -> &std::ffi::OsStr { 180 self.as_os_str() 181 } 182 } 183 184 impl PartialEq<str> for OsStr { 185 #[inline] eq(&self, other: &str) -> bool186 fn eq(&self, other: &str) -> bool { 187 PartialEq::eq(self.as_os_str(), other) 188 } 189 } 190 impl PartialEq<OsStr> for str { 191 #[inline] eq(&self, other: &OsStr) -> bool192 fn eq(&self, other: &OsStr) -> bool { 193 PartialEq::eq(self, other.as_os_str()) 194 } 195 } 196 197 impl PartialEq<&'_ str> for OsStr { 198 #[inline] eq(&self, other: &&str) -> bool199 fn eq(&self, other: &&str) -> bool { 200 PartialEq::eq(self.as_os_str(), *other) 201 } 202 } 203 impl PartialEq<OsStr> for &'_ str { 204 #[inline] eq(&self, other: &OsStr) -> bool205 fn eq(&self, other: &OsStr) -> bool { 206 PartialEq::eq(*self, other.as_os_str()) 207 } 208 } 209 210 impl PartialEq<&'_ std::ffi::OsStr> for OsStr { 211 #[inline] eq(&self, other: &&std::ffi::OsStr) -> bool212 fn eq(&self, other: &&std::ffi::OsStr) -> bool { 213 PartialEq::eq(self.as_os_str(), *other) 214 } 215 } 216 impl PartialEq<OsStr> for &'_ std::ffi::OsStr { 217 #[inline] eq(&self, other: &OsStr) -> bool218 fn eq(&self, other: &OsStr) -> bool { 219 PartialEq::eq(*self, other.as_os_str()) 220 } 221 } 222 223 impl PartialEq<std::string::String> for OsStr { 224 #[inline] eq(&self, other: &std::string::String) -> bool225 fn eq(&self, other: &std::string::String) -> bool { 226 PartialEq::eq(self.as_os_str(), other.as_str()) 227 } 228 } 229 impl PartialEq<OsStr> for std::string::String { 230 #[inline] eq(&self, other: &OsStr) -> bool231 fn eq(&self, other: &OsStr) -> bool { 232 PartialEq::eq(self.as_str(), other.as_os_str()) 233 } 234 } 235 236 impl PartialEq<std::ffi::OsString> for OsStr { 237 #[inline] eq(&self, other: &std::ffi::OsString) -> bool238 fn eq(&self, other: &std::ffi::OsString) -> bool { 239 PartialEq::eq(self.as_os_str(), other.as_os_str()) 240 } 241 } 242 impl PartialEq<OsStr> for std::ffi::OsString { 243 #[inline] eq(&self, other: &OsStr) -> bool244 fn eq(&self, other: &OsStr) -> bool { 245 PartialEq::eq(self.as_os_str(), other.as_os_str()) 246 } 247 } 248 249 #[cfg(feature = "string")] 250 pub(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 { from_string(name: std::ffi::OsString) -> Self258 pub(crate) fn from_string(name: std::ffi::OsString) -> Self { 259 Self::Owned(name.into_boxed_os_str()) 260 } 261 from_ref(name: &std::ffi::OsStr) -> Self262 pub(crate) fn from_ref(name: &std::ffi::OsStr) -> Self { 263 Self::Owned(Box::from(name)) 264 } 265 from_static_ref(name: &'static std::ffi::OsStr) -> Self266 pub(crate) fn from_static_ref(name: &'static std::ffi::OsStr) -> Self { 267 Self::Static(name) 268 } 269 as_os_str(&self) -> &std::ffi::OsStr270 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 into_os_string(self) -> std::ffi::OsString277 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"))] 284 pub(crate) mod inner { 285 #[derive(Clone)] 286 pub(crate) struct Inner(&'static std::ffi::OsStr); 287 288 impl Inner { from_static_ref(name: &'static std::ffi::OsStr) -> Self289 pub(crate) fn from_static_ref(name: &'static std::ffi::OsStr) -> Self { 290 Self(name) 291 } 292 as_os_str(&self) -> &std::ffi::OsStr293 pub(crate) fn as_os_str(&self) -> &std::ffi::OsStr { 294 self.0 295 } 296 into_os_string(self) -> std::ffi::OsString297 pub(crate) fn into_os_string(self) -> std::ffi::OsString { 298 self.as_os_str().to_owned() 299 } 300 } 301 } 302 303 pub(crate) use inner::Inner; 304 305 impl Default for Inner { default() -> Self306 fn default() -> Self { 307 Self::from_static_ref(std::ffi::OsStr::new("")) 308 } 309 } 310 311 impl PartialEq for Inner { eq(&self, other: &Inner) -> bool312 fn eq(&self, other: &Inner) -> bool { 313 self.as_os_str() == other.as_os_str() 314 } 315 } 316 317 impl PartialOrd for Inner { partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering>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 323 impl Ord for Inner { cmp(&self, other: &Inner) -> std::cmp::Ordering324 fn cmp(&self, other: &Inner) -> std::cmp::Ordering { 325 self.as_os_str().cmp(other.as_os_str()) 326 } 327 } 328 329 impl Eq for Inner {} 330 331 impl std::hash::Hash for Inner { 332 #[inline] hash<H: std::hash::Hasher>(&self, state: &mut H)333 fn hash<H: std::hash::Hasher>(&self, state: &mut H) { 334 self.as_os_str().hash(state); 335 } 336 } 337