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