1 /// A UTF-8-encoded fixed string 2 /// 3 /// **NOTE:** To support dynamic values (i.e. `String`), enable the `string` 4 /// feature 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 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"))] 258 pub(crate) mod inner { 259 #[derive(Clone)] 260 pub(crate) struct Inner(pub(crate) &'static str); 261 262 impl Inner { from_static_ref(name: &'static str) -> Self263 pub(crate) fn from_static_ref(name: &'static str) -> Self { 264 Self(name) 265 } 266 as_str(&self) -> &str267 pub(crate) fn as_str(&self) -> &str { 268 self.0 269 } 270 into_string(self) -> String271 pub(crate) fn into_string(self) -> String { 272 self.as_str().to_owned() 273 } 274 } 275 } 276 277 pub(crate) use inner::Inner; 278 279 impl Default for Inner { default() -> Self280 fn default() -> Self { 281 Self::from_static_ref("") 282 } 283 } 284 285 impl PartialEq for Inner { eq(&self, other: &Inner) -> bool286 fn eq(&self, other: &Inner) -> bool { 287 self.as_str() == other.as_str() 288 } 289 } 290 291 impl PartialOrd for Inner { partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering>292 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> { 293 Some(self.cmp(other)) 294 } 295 } 296 297 impl Ord for Inner { cmp(&self, other: &Inner) -> std::cmp::Ordering298 fn cmp(&self, other: &Inner) -> std::cmp::Ordering { 299 self.as_str().cmp(other.as_str()) 300 } 301 } 302 303 impl Eq for Inner {} 304 305 impl std::hash::Hash for Inner { 306 #[inline] hash<H: std::hash::Hasher>(&self, state: &mut H)307 fn hash<H: std::hash::Hasher>(&self, state: &mut H) { 308 self.as_str().hash(state); 309 } 310 } 311