1use crate::ToSnakeCase;
2use std::borrow::Cow;
3
4type Inner = compact_str::CompactString;
5
6#[derive(Clone, Eq, Hash, PartialOrd, Ord)]
7#[cfg_attr(
8 feature = "serde",
9 derive(serde::Serialize, serde::Deserialize),
10 serde(transparent)
11)]
12#[repr(transparent)]
13pub struct SmallStr(Inner);
14
15impl SmallStr {
16 pub const EMPTY: Self = Self::from_static("");
17 pub const EMPTY_REF: &'static Self = &Self::from_static("");
18
19 #[inline(always)]
20 pub const fn from_static(s: &'static str) -> Self {
21 Self(Inner::const_new(s))
22 }
23
24 #[inline(always)]
25 pub fn from_string(s: String) -> Self {
26 Self(Inner::from(s))
27 }
28
29 #[inline(always)]
30 pub fn as_str(&self) -> &str {
31 self.0.as_str()
32 }
33
34 #[inline(always)]
35 pub fn as_mut_str(&mut self) -> &mut str {
36 self.0.as_mut_str()
37 }
38
39 #[inline(always)]
40 #[allow(clippy::inherent_to_string_shadow_display)] pub fn to_string(&self) -> String {
42 self.0.as_str().to_owned()
43 }
44
45 #[inline(always)]
46 pub fn into_string(self) -> String {
47 self.0.into_string()
48 }
49
50 #[inline(always)]
51 pub fn contains(&self, pat: impl AsRef<str>) -> bool {
52 self.as_str().contains(pat.as_ref())
53 }
54}
55
56impl Default for SmallStr {
57 #[inline(always)]
58 fn default() -> Self {
59 Self::EMPTY
60 }
61}
62
63impl ToSnakeCase<SmallStr> for SmallStr {
64 fn to_snake_case(&self) -> SmallStr {
65 self.as_str().to_snake_case().into()
66 }
67}
68
69impl AsRef<str> for SmallStr {
72 #[inline(always)]
73 fn as_ref(&self) -> &str {
74 self.as_str()
75 }
76}
77
78impl core::ops::Deref for SmallStr {
79 type Target = str;
80
81 #[inline(always)]
82 fn deref(&self) -> &Self::Target {
83 self.as_str()
84 }
85}
86
87impl core::ops::DerefMut for SmallStr {
88 #[inline(always)]
89 fn deref_mut(&mut self) -> &mut Self::Target {
90 self.as_mut_str()
91 }
92}
93
94impl core::borrow::Borrow<str> for SmallStr {
95 #[inline(always)]
96 fn borrow(&self) -> &str {
97 self.as_str()
98 }
99}
100
101impl AsRef<std::path::Path> for SmallStr {
104 #[inline(always)]
105 fn as_ref(&self) -> &std::path::Path {
106 self.as_str().as_ref()
107 }
108}
109
110impl AsRef<[u8]> for SmallStr {
111 #[inline(always)]
112 fn as_ref(&self) -> &[u8] {
113 self.as_str().as_bytes()
114 }
115}
116
117impl AsRef<std::ffi::OsStr> for SmallStr {
118 #[inline(always)]
119 fn as_ref(&self) -> &std::ffi::OsStr {
120 self.as_str().as_ref()
121 }
122}
123
124impl From<&str> for SmallStr {
127 #[inline(always)]
128 fn from(value: &str) -> Self {
129 Self(Inner::from(value))
130 }
131}
132
133impl From<&&str> for SmallStr {
134 #[inline(always)]
135 fn from(value: &&str) -> Self {
136 Self(Inner::from(*value))
137 }
138}
139
140impl From<String> for SmallStr {
141 #[inline(always)]
142 fn from(value: String) -> Self {
143 Self::from_string(value)
144 }
145}
146
147impl From<SmallStr> for String {
148 #[inline(always)]
149 fn from(value: SmallStr) -> Self {
150 value.to_string()
151 }
152}
153
154impl From<Cow<'_, str>> for SmallStr {
155 #[inline(always)]
156 fn from(value: Cow<str>) -> Self {
157 Self(Inner::from(value))
158 }
159}
160
161impl From<&String> for SmallStr {
162 #[inline(always)]
163 fn from(value: &String) -> Self {
164 Self(Inner::from(value.as_str()))
165 }
166}
167
168impl From<Inner> for SmallStr {
169 #[inline(always)]
170 fn from(value: Inner) -> Self {
171 Self(value)
172 }
173}
174
175impl FromIterator<SmallStr> for SmallStr {
178 #[inline(always)]
179 fn from_iter<T: IntoIterator<Item = SmallStr>>(iter: T) -> Self {
180 Self(Inner::from_iter(iter.into_iter().map(|x| x.0)))
181 }
182}
183
184impl<'a> FromIterator<&'a SmallStr> for SmallStr {
185 #[inline(always)]
186 fn from_iter<T: IntoIterator<Item = &'a SmallStr>>(iter: T) -> Self {
187 Self(Inner::from_iter(iter.into_iter().map(|x| x.as_str())))
188 }
189}
190
191impl FromIterator<char> for SmallStr {
192 #[inline(always)]
193 fn from_iter<I: IntoIterator<Item = char>>(iter: I) -> SmallStr {
194 Self(Inner::from_iter(iter))
195 }
196}
197
198impl<'a> FromIterator<&'a char> for SmallStr {
199 #[inline(always)]
200 fn from_iter<I: IntoIterator<Item = &'a char>>(iter: I) -> SmallStr {
201 Self(Inner::from_iter(iter))
202 }
203}
204
205impl<'a> FromIterator<&'a str> for SmallStr {
206 #[inline(always)]
207 fn from_iter<I: IntoIterator<Item = &'a str>>(iter: I) -> SmallStr {
208 Self(Inner::from_iter(iter))
209 }
210}
211
212impl FromIterator<String> for SmallStr {
213 #[inline(always)]
214 fn from_iter<I: IntoIterator<Item = String>>(iter: I) -> SmallStr {
215 Self(Inner::from_iter(iter))
216 }
217}
218
219impl FromIterator<Box<str>> for SmallStr {
220 #[inline(always)]
221 fn from_iter<I: IntoIterator<Item = Box<str>>>(iter: I) -> SmallStr {
222 Self(Inner::from_iter(iter))
223 }
224}
225
226impl<'a> FromIterator<std::borrow::Cow<'a, str>> for SmallStr {
227 #[inline(always)]
228 fn from_iter<I: IntoIterator<Item = std::borrow::Cow<'a, str>>>(iter: I) -> SmallStr {
229 Self(Inner::from_iter(iter))
230 }
231}
232
233impl<T> PartialEq<T> for SmallStr
236where
237 T: AsRef<str> + ?Sized,
238{
239 #[inline(always)]
240 fn eq(&self, other: &T) -> bool {
241 self.as_str() == other.as_ref()
242 }
243}
244
245impl PartialEq<SmallStr> for &str {
246 #[inline(always)]
247 fn eq(&self, other: &SmallStr) -> bool {
248 *self == other.as_str()
249 }
250}
251
252impl PartialEq<SmallStr> for String {
253 #[inline(always)]
254 fn eq(&self, other: &SmallStr) -> bool {
255 self.as_str() == other.as_str()
256 }
257}
258
259impl core::fmt::Write for SmallStr {
262 #[inline(always)]
263 fn write_char(&mut self, c: char) -> std::fmt::Result {
264 self.0.write_char(c)
265 }
266
267 #[inline(always)]
268 fn write_fmt(&mut self, args: std::fmt::Arguments<'_>) -> std::fmt::Result {
269 self.0.write_fmt(args)
270 }
271
272 #[inline(always)]
273 fn write_str(&mut self, s: &str) -> std::fmt::Result {
274 self.0.write_str(s)
275 }
276}
277
278impl core::fmt::Debug for SmallStr {
281 #[inline(always)]
282 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
283 self.as_str().fmt(f)
284 }
285}
286
287impl core::fmt::Display for SmallStr {
288 #[inline(always)]
289 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
290 self.as_str().fmt(f)
291 }
292}