case_insensitive_string/
lib.rs1#[cfg(feature = "serde")]
2pub extern crate serde;
3
4#[cfg(feature = "compact")]
5pub extern crate compact_str;
6
7pub mod features;
8
9#[cfg(feature = "compact")]
10use compact_str::CompactString;
11#[cfg(not(feature = "compact"))]
13#[derive(Debug, Clone, Default)]
14#[repr(transparent)]
15pub struct CaseInsensitiveString(String);
16
17#[cfg(feature = "compact")]
19#[derive(Debug, Clone, Default)]
20#[repr(transparent)]
21pub struct CaseInsensitiveString(CompactString);
22
23impl CaseInsensitiveString {
24 #[inline]
42 pub fn new<'a, B: ?Sized + AsRef<[u8]>>(bytes: &'a B) -> CaseInsensitiveString {
43 CaseInsensitiveString::from(bytes.as_ref())
44 }
45
46 #[inline]
47 pub fn as_bytes(&self) -> &[u8] {
48 &self.0.as_bytes()
49 }
50
51 #[cfg(not(feature = "compact"))]
52 #[inline]
53 pub fn inner(&self) -> &String {
54 &self.0
55 }
56
57 #[cfg(feature = "compact")]
58 #[inline]
59 pub fn inner(&self) -> &CompactString {
60 &self.0
61 }
62
63 pub fn push(&mut self, ch: char) {
77 self.push_str(ch.encode_utf8(&mut [0; 4]));
78 }
79
80 #[inline]
92 pub fn push_str(&mut self, s: &str) {
93 self.0.push_str(s)
94 }
95
96 pub fn into_string(self) -> String {
99 self.0.into()
100 }
101
102 #[inline]
143 pub fn remove(&mut self, idx: usize) -> char {
144 self.0.remove(idx)
145 }
146
147 #[inline]
163 pub fn len(&self) -> usize {
164 self.0.len()
165 }
166
167 #[inline]
180 pub fn is_empty(&self) -> bool {
181 self.len() == 0
182 }
183}
184
185impl Eq for CaseInsensitiveString {}
186
187impl std::hash::Hash for CaseInsensitiveString {
188 #[inline]
189 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
190 self.0.to_ascii_lowercase().hash(state)
191 }
192}
193
194impl From<&str> for CaseInsensitiveString {
195 #[inline]
196 fn from(s: &str) -> Self {
197 CaseInsensitiveString { 0: s.into() }
198 }
199}
200
201#[cfg(feature = "compact")]
202impl From<CompactString> for CaseInsensitiveString {
203 #[inline]
204 fn from(s: CompactString) -> Self {
205 CaseInsensitiveString { 0: s.into() }
206 }
207}
208
209impl From<String> for CaseInsensitiveString {
210 fn from(s: String) -> Self {
211 CaseInsensitiveString { 0: s.into() }
212 }
213}
214
215impl From<&[u8]> for CaseInsensitiveString {
216 fn from(s: &[u8]) -> Self {
217 CaseInsensitiveString {
218 0: String::from_utf8_lossy(s).into(),
219 }
220 }
221}
222
223impl From<CaseInsensitiveString> for String {
224 #[inline]
225 fn from(s: CaseInsensitiveString) -> Self {
226 s.into_string()
227 }
228}
229
230impl From<&CaseInsensitiveString> for String {
231 #[inline]
232 fn from(s: &CaseInsensitiveString) -> Self {
233 s.0.to_string()
234 }
235}
236
237impl From<&CaseInsensitiveString> for CaseInsensitiveString {
238 #[inline]
239 fn from(s: &CaseInsensitiveString) -> Self {
240 s.clone()
241 }
242}
243
244impl AsRef<str> for CaseInsensitiveString {
245 #[inline]
246 fn as_ref(&self) -> &str {
247 &self.0
248 }
249}
250
251impl core::fmt::Display for CaseInsensitiveString {
252 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
253 write!(f, "{}", self.0)
254 }
255}
256
257impl std::ops::Deref for CaseInsensitiveString {
258 type Target = str;
259
260 #[inline]
261 fn deref(&self) -> &str {
262 &self.0.as_str()
263 }
264}
265
266impl std::ops::DerefMut for CaseInsensitiveString {
267 #[inline]
268 fn deref_mut(&mut self) -> &mut str {
269 self.0.as_mut_str()
270 }
271}
272
273impl std::borrow::Borrow<str> for CaseInsensitiveString {
274 #[inline]
275 fn borrow(&self) -> &str {
276 &self.0.as_str()
277 }
278}
279
280impl PartialEq for CaseInsensitiveString {
281 #[inline]
282 fn eq(&self, other: &Self) -> bool {
283 self.0.eq_ignore_ascii_case(&other.0)
284 }
285}
286
287#[cfg(feature = "compact")]
288impl PartialEq<CaseInsensitiveString> for &CompactString {
289 fn eq(&self, other: &CaseInsensitiveString) -> bool {
290 self.eq_ignore_ascii_case(&other.as_ref())
291 }
292}
293
294impl PartialEq<CaseInsensitiveString> for String {
295 fn eq(&self, other: &CaseInsensitiveString) -> bool {
296 self.eq_ignore_ascii_case(&other.as_ref())
297 }
298}
299
300impl<'a> PartialEq<&'a CaseInsensitiveString> for String {
301 fn eq(&self, other: &&CaseInsensitiveString) -> bool {
302 self.eq_ignore_ascii_case(&other.as_ref())
303 }
304}
305
306impl PartialEq<CaseInsensitiveString> for &String {
307 fn eq(&self, other: &CaseInsensitiveString) -> bool {
308 self.eq_ignore_ascii_case(&other.as_ref())
309 }
310}
311
312impl PartialEq<CaseInsensitiveString> for str {
313 fn eq(&self, other: &CaseInsensitiveString) -> bool {
314 self.eq_ignore_ascii_case(&other.as_ref())
315 }
316}
317
318impl<'a> PartialEq<&'a CaseInsensitiveString> for str {
319 fn eq(&self, other: &&CaseInsensitiveString) -> bool {
320 self.eq_ignore_ascii_case(&other.as_ref())
321 }
322}
323
324impl PartialEq<CaseInsensitiveString> for &str {
325 fn eq(&self, other: &CaseInsensitiveString) -> bool {
326 self.eq_ignore_ascii_case(&other.as_ref())
327 }
328}
329
330impl PartialEq<CaseInsensitiveString> for &&str {
331 fn eq(&self, other: &CaseInsensitiveString) -> bool {
332 self.eq_ignore_ascii_case(&other.as_ref())
333 }
334}
335
336impl<'a> PartialEq<CaseInsensitiveString> for std::borrow::Cow<'a, str> {
337 fn eq(&self, other: &CaseInsensitiveString) -> bool {
338 self.eq_ignore_ascii_case(&other.as_ref())
339 }
340}
341
342impl<'a> PartialEq<CaseInsensitiveString> for &std::borrow::Cow<'a, str> {
343 fn eq(&self, other: &CaseInsensitiveString) -> bool {
344 self.eq_ignore_ascii_case(&other.as_ref())
345 }
346}
347
348impl PartialEq<String> for &CaseInsensitiveString {
349 fn eq(&self, other: &String) -> bool {
350 self.eq_ignore_ascii_case(&other.as_ref())
351 }
352}
353
354impl<'a> PartialEq<std::borrow::Cow<'a, str>> for &CaseInsensitiveString {
355 fn eq(&self, other: &std::borrow::Cow<'a, str>) -> bool {
356 self.eq_ignore_ascii_case(&other.as_ref())
357 }
358}
359
360impl PartialOrd for CaseInsensitiveString {
361 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
362 Some(self.cmp(&other))
363 }
364}
365
366impl Ord for CaseInsensitiveString {
367 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
377 self.0.to_ascii_lowercase().cmp(&other.0.to_ascii_lowercase())
378 }
379}