Skip to main content

radiate_utils/
str.rs

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