cheetah_string/
cheetah_str.rs1use alloc::borrow::Cow;
2use alloc::string::{ParseError, String, ToString};
3use alloc::sync::Arc;
4use core::borrow::Borrow;
5use core::cmp::Ordering;
6use core::fmt;
7use core::hash::{Hash, Hasher};
8use core::ops::Deref;
9use core::str::FromStr;
10
11use crate::inline::InlineStr;
12use crate::CheetahString;
13
14#[derive(Clone)]
21pub struct CheetahStr {
22 inner: Repr,
23}
24
25#[derive(Clone)]
26enum Repr {
27 Inline(InlineStr),
28 Static(&'static str),
29 Shared(Arc<str>),
30}
31
32impl CheetahStr {
33 #[inline]
35 pub const fn empty() -> Self {
36 Self {
37 inner: Repr::Inline(InlineStr::empty()),
38 }
39 }
40
41 #[inline]
43 pub fn new() -> Self {
44 Self::empty()
45 }
46
47 #[inline]
49 pub const fn from_static_str(s: &'static str) -> Self {
50 Self {
51 inner: Repr::Static(s),
52 }
53 }
54
55 #[inline]
57 pub fn from_slice(s: &str) -> Self {
58 if let Some(inline) = InlineStr::from_str(s) {
59 Self {
60 inner: Repr::Inline(inline),
61 }
62 } else {
63 Self {
64 inner: Repr::Shared(Arc::from(s)),
65 }
66 }
67 }
68
69 #[inline]
71 pub fn from_string(s: String) -> Self {
72 if let Some(inline) = InlineStr::from_str(&s) {
73 Self {
74 inner: Repr::Inline(inline),
75 }
76 } else {
77 Self {
78 inner: Repr::Shared(s.into_boxed_str().into()),
79 }
80 }
81 }
82
83 #[inline]
85 pub fn as_str(&self) -> &str {
86 match &self.inner {
87 Repr::Inline(inline) => inline.as_str(),
88 Repr::Static(s) => s,
89 Repr::Shared(s) => s.as_ref(),
90 }
91 }
92
93 #[inline]
95 pub fn as_bytes(&self) -> &[u8] {
96 self.as_str().as_bytes()
97 }
98
99 #[inline]
101 pub fn len(&self) -> usize {
102 self.as_str().len()
103 }
104
105 #[inline]
107 pub fn is_empty(&self) -> bool {
108 self.as_str().is_empty()
109 }
110}
111
112impl Default for CheetahStr {
113 #[inline]
114 fn default() -> Self {
115 Self::empty()
116 }
117}
118
119impl From<&str> for CheetahStr {
120 #[inline]
121 fn from(value: &str) -> Self {
122 Self::from_slice(value)
123 }
124}
125
126impl From<String> for CheetahStr {
127 #[inline]
128 fn from(value: String) -> Self {
129 Self::from_string(value)
130 }
131}
132
133impl From<Cow<'static, str>> for CheetahStr {
134 #[inline]
135 fn from(value: Cow<'static, str>) -> Self {
136 match value {
137 Cow::Borrowed(s) => Self::from_static_str(s),
138 Cow::Owned(s) => Self::from_string(s),
139 }
140 }
141}
142
143impl From<&CheetahString> for CheetahStr {
144 #[inline]
145 fn from(value: &CheetahString) -> Self {
146 Self::from_slice(value.as_str())
147 }
148}
149
150impl From<CheetahString> for CheetahStr {
151 #[inline]
152 fn from(value: CheetahString) -> Self {
153 Self::from_string(String::from(value))
154 }
155}
156
157impl From<CheetahStr> for String {
158 #[inline]
159 fn from(value: CheetahStr) -> Self {
160 value.as_str().to_string()
161 }
162}
163
164impl FromStr for CheetahStr {
165 type Err = ParseError;
166
167 #[inline]
168 fn from_str(s: &str) -> Result<Self, Self::Err> {
169 Ok(Self::from_slice(s))
170 }
171}
172
173impl Deref for CheetahStr {
174 type Target = str;
175
176 #[inline]
177 fn deref(&self) -> &Self::Target {
178 self.as_str()
179 }
180}
181
182impl AsRef<str> for CheetahStr {
183 #[inline]
184 fn as_ref(&self) -> &str {
185 self.as_str()
186 }
187}
188
189impl AsRef<[u8]> for CheetahStr {
190 #[inline]
191 fn as_ref(&self) -> &[u8] {
192 self.as_bytes()
193 }
194}
195
196impl Borrow<str> for CheetahStr {
197 #[inline]
198 fn borrow(&self) -> &str {
199 self.as_str()
200 }
201}
202
203impl fmt::Display for CheetahStr {
204 #[inline]
205 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
206 self.as_str().fmt(f)
207 }
208}
209
210impl fmt::Debug for CheetahStr {
211 #[inline]
212 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
213 fmt::Debug::fmt(self.as_str(), f)
214 }
215}
216
217impl Hash for CheetahStr {
218 #[inline]
219 fn hash<H: Hasher>(&self, state: &mut H) {
220 self.as_str().hash(state);
221 }
222}
223
224impl PartialEq for CheetahStr {
225 #[inline]
226 fn eq(&self, other: &Self) -> bool {
227 self.as_str() == other.as_str()
228 }
229}
230
231impl PartialEq<str> for CheetahStr {
232 #[inline]
233 fn eq(&self, other: &str) -> bool {
234 self.as_str() == other
235 }
236}
237
238impl PartialEq<&str> for CheetahStr {
239 #[inline]
240 fn eq(&self, other: &&str) -> bool {
241 self.as_str() == *other
242 }
243}
244
245impl PartialEq<CheetahStr> for str {
246 #[inline]
247 fn eq(&self, other: &CheetahStr) -> bool {
248 self == other.as_str()
249 }
250}
251
252impl PartialEq<CheetahStr> for &str {
253 #[inline]
254 fn eq(&self, other: &CheetahStr) -> bool {
255 *self == other.as_str()
256 }
257}
258
259impl Eq for CheetahStr {}
260
261impl PartialOrd for CheetahStr {
262 #[inline]
263 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
264 Some(self.cmp(other))
265 }
266}
267
268impl Ord for CheetahStr {
269 #[inline]
270 fn cmp(&self, other: &Self) -> Ordering {
271 self.as_str().cmp(other.as_str())
272 }
273}