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