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)] 6 pub struct Str { 7 name: Inner, 8 } 9 10 impl Str { 11 #[cfg(feature = "string")] from_string(name: std::string::String) -> Self12 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")] from_ref(name: &str) -> Self19 pub(crate) fn from_ref(name: &str) -> Self { 20 Self { 21 name: Inner::from_ref(name), 22 } 23 } 24 from_static_ref(name: &'static str) -> Self25 pub(crate) fn from_static_ref(name: &'static str) -> Self { 26 Self { 27 name: Inner::from_static_ref(name), 28 } 29 } 30 into_inner(self) -> Inner31 pub(crate) fn into_inner(self) -> Inner { 32 self.name 33 } 34 35 /// Get the raw string of the `Str` as_str(&self) -> &str36 pub fn as_str(&self) -> &str { 37 self.name.as_str() 38 } 39 } 40 41 impl From<&'_ Str> for Str { from(id: &'_ Str) -> Self42 fn from(id: &'_ Str) -> Self { 43 id.clone() 44 } 45 } 46 47 #[cfg(feature = "string")] 48 impl From<std::string::String> for Str { from(name: std::string::String) -> Self49 fn from(name: std::string::String) -> Self { 50 Self::from_string(name) 51 } 52 } 53 54 #[cfg(feature = "string")] 55 impl From<&'_ std::string::String> for Str { from(name: &'_ std::string::String) -> Self56 fn from(name: &'_ std::string::String) -> Self { 57 Self::from_ref(name.as_str()) 58 } 59 } 60 61 impl From<&'static str> for Str { from(name: &'static str) -> Self62 fn from(name: &'static str) -> Self { 63 Self::from_static_ref(name) 64 } 65 } 66 67 impl From<&'_ &'static str> for Str { from(name: &'_ &'static str) -> Self68 fn from(name: &'_ &'static str) -> Self { 69 Self::from_static_ref(name) 70 } 71 } 72 73 impl From<Str> for String { from(name: Str) -> Self74 fn from(name: Str) -> Self { 75 name.name.into_string() 76 } 77 } 78 79 impl From<Str> for Vec<u8> { from(name: Str) -> Self80 fn from(name: Str) -> Self { 81 String::from(name).into() 82 } 83 } 84 85 impl From<Str> for std::ffi::OsString { from(name: Str) -> Self86 fn from(name: Str) -> Self { 87 String::from(name).into() 88 } 89 } 90 91 impl From<Str> for std::path::PathBuf { from(name: Str) -> Self92 fn from(name: Str) -> Self { 93 String::from(name).into() 94 } 95 } 96 97 impl std::fmt::Display for Str { 98 #[inline] fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result99 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 100 std::fmt::Display::fmt(self.as_str(), f) 101 } 102 } 103 104 impl std::fmt::Debug for Str { 105 #[inline] fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result106 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 107 std::fmt::Debug::fmt(self.as_str(), f) 108 } 109 } 110 111 impl std::ops::Deref for Str { 112 type Target = str; 113 114 #[inline] deref(&self) -> &str115 fn deref(&self) -> &str { 116 self.as_str() 117 } 118 } 119 120 impl AsRef<str> for Str { 121 #[inline] as_ref(&self) -> &str122 fn as_ref(&self) -> &str { 123 self.as_str() 124 } 125 } 126 127 impl AsRef<[u8]> for Str { 128 #[inline] as_ref(&self) -> &[u8]129 fn as_ref(&self) -> &[u8] { 130 self.as_bytes() 131 } 132 } 133 134 impl AsRef<std::ffi::OsStr> for Str { 135 #[inline] as_ref(&self) -> &std::ffi::OsStr136 fn as_ref(&self) -> &std::ffi::OsStr { 137 (**self).as_ref() 138 } 139 } 140 141 impl AsRef<std::path::Path> for Str { 142 #[inline] as_ref(&self) -> &std::path::Path143 fn as_ref(&self) -> &std::path::Path { 144 std::path::Path::new(self) 145 } 146 } 147 148 impl std::borrow::Borrow<str> for Str { 149 #[inline] borrow(&self) -> &str150 fn borrow(&self) -> &str { 151 self.as_str() 152 } 153 } 154 155 impl PartialEq<str> for Str { 156 #[inline] eq(&self, other: &str) -> bool157 fn eq(&self, other: &str) -> bool { 158 PartialEq::eq(self.as_str(), other) 159 } 160 } 161 impl PartialEq<Str> for str { 162 #[inline] eq(&self, other: &Str) -> bool163 fn eq(&self, other: &Str) -> bool { 164 PartialEq::eq(self, other.as_str()) 165 } 166 } 167 168 impl PartialEq<&'_ str> for Str { 169 #[inline] eq(&self, other: &&str) -> bool170 fn eq(&self, other: &&str) -> bool { 171 PartialEq::eq(self.as_str(), *other) 172 } 173 } 174 impl PartialEq<Str> for &'_ str { 175 #[inline] eq(&self, other: &Str) -> bool176 fn eq(&self, other: &Str) -> bool { 177 PartialEq::eq(*self, other.as_str()) 178 } 179 } 180 181 impl PartialEq<std::ffi::OsStr> for Str { 182 #[inline] eq(&self, other: &std::ffi::OsStr) -> bool183 fn eq(&self, other: &std::ffi::OsStr) -> bool { 184 PartialEq::eq(self.as_str(), other) 185 } 186 } 187 impl PartialEq<Str> for std::ffi::OsStr { 188 #[inline] eq(&self, other: &Str) -> bool189 fn eq(&self, other: &Str) -> bool { 190 PartialEq::eq(self, other.as_str()) 191 } 192 } 193 194 impl PartialEq<&'_ std::ffi::OsStr> for Str { 195 #[inline] eq(&self, other: &&std::ffi::OsStr) -> bool196 fn eq(&self, other: &&std::ffi::OsStr) -> bool { 197 PartialEq::eq(self.as_str(), *other) 198 } 199 } 200 impl PartialEq<Str> for &'_ std::ffi::OsStr { 201 #[inline] eq(&self, other: &Str) -> bool202 fn eq(&self, other: &Str) -> bool { 203 PartialEq::eq(*self, other.as_str()) 204 } 205 } 206 207 impl PartialEq<std::string::String> for Str { 208 #[inline] eq(&self, other: &std::string::String) -> bool209 fn eq(&self, other: &std::string::String) -> bool { 210 PartialEq::eq(self.as_str(), other.as_str()) 211 } 212 } 213 impl PartialEq<Str> for std::string::String { 214 #[inline] eq(&self, other: &Str) -> bool215 fn eq(&self, other: &Str) -> bool { 216 PartialEq::eq(self.as_str(), other.as_str()) 217 } 218 } 219 220 #[cfg(feature = "string")] 221 pub(crate) mod inner { 222 #[derive(Clone)] 223 pub(crate) enum Inner { 224 Static(&'static str), 225 Owned(Box<str>), 226 } 227 228 impl Inner { from_string(name: std::string::String) -> Self229 pub(crate) fn from_string(name: std::string::String) -> Self { 230 Self::Owned(name.into_boxed_str()) 231 } 232 from_ref(name: &str) -> Self233 pub(crate) fn from_ref(name: &str) -> Self { 234 Self::Owned(Box::from(name)) 235 } 236 from_static_ref(name: &'static str) -> Self237 pub(crate) fn from_static_ref(name: &'static str) -> Self { 238 Self::Static(name) 239 } 240 as_str(&self) -> &str241 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 into_string(self) -> String248 pub(crate) fn into_string(self) -> String { 249 self.as_str().to_owned() 250 } 251 } 252 } 253 254 #[cfg(not(feature = "string"))] 255 pub(crate) mod inner { 256 #[derive(Clone)] 257 pub(crate) struct Inner(pub(crate) &'static str); 258 259 impl Inner { from_static_ref(name: &'static str) -> Self260 pub(crate) fn from_static_ref(name: &'static str) -> Self { 261 Self(name) 262 } 263 as_str(&self) -> &str264 pub(crate) fn as_str(&self) -> &str { 265 self.0 266 } 267 into_string(self) -> String268 pub(crate) fn into_string(self) -> String { 269 self.as_str().to_owned() 270 } 271 } 272 } 273 274 pub(crate) use inner::Inner; 275 276 impl Default for Inner { default() -> Self277 fn default() -> Self { 278 Self::from_static_ref("") 279 } 280 } 281 282 impl PartialEq for Inner { eq(&self, other: &Inner) -> bool283 fn eq(&self, other: &Inner) -> bool { 284 self.as_str() == other.as_str() 285 } 286 } 287 288 impl PartialOrd for Inner { partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering>289 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> { 290 self.as_str().partial_cmp(other.as_str()) 291 } 292 } 293 294 impl Ord for Inner { cmp(&self, other: &Inner) -> std::cmp::Ordering295 fn cmp(&self, other: &Inner) -> std::cmp::Ordering { 296 self.as_str().cmp(other.as_str()) 297 } 298 } 299 300 impl Eq for Inner {} 301 302 impl std::hash::Hash for Inner { 303 #[inline] hash<H: std::hash::Hasher>(&self, state: &mut H)304 fn hash<H: std::hash::Hasher>(&self, state: &mut H) { 305 self.as_str().hash(state); 306 } 307 } 308