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
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
63// AsRef, Borrow, Deref impls
64
65impl 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
95// AsRef impls
96
97impl 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
118// From impls
119
120impl 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
169// FromIterator impls
170
171impl 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
227// PartialEq impls
228
229impl<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
253// Write
254
255impl 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
272// Debug, Display
273
274impl 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}