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