thin_string/
lib.rs

1#![allow(clippy::missing_safety_doc)]
2#![cfg_attr(feature = "nightly", feature(pattern))]
3#![cfg_attr(feature = "nightly", feature(slice_range))]
4#![cfg_attr(feature = "nightly", feature(extend_one))]
5#![cfg_attr(feature = "nightly", feature(min_specialization))]
6#![cfg_attr(feature = "nightly", feature(fmt_internals))]
7
8use std::{
9    borrow::Cow,
10    char::{decode_utf16, REPLACEMENT_CHARACTER},
11    fmt, hash,
12    iter::{FromIterator, FusedIterator},
13    ops::{self, Add, AddAssign, Index, IndexMut, Range, RangeBounds},
14    ptr,
15    str::{from_utf8, from_utf8_unchecked, from_utf8_unchecked_mut, Chars, FromStr, Utf8Error},
16};
17#[cfg(feature = "nightly")]
18use std::{iter::from_fn, slice, str::pattern::Pattern};
19
20use thin_vec::ThinVec;
21
22#[derive(PartialOrd, Eq, Ord)]
23pub struct ThinString {
24    vec: ThinVec<u8>,
25}
26
27#[derive(Debug, PartialEq, Eq, Clone)]
28pub struct FromUtf8Error {
29    bytes: ThinVec<u8>,
30    error: Utf8Error,
31}
32
33pub struct FromUtf16Error(());
34
35impl ThinString {
36    #[inline]
37    pub fn new() -> ThinString {
38        ThinString {
39            vec: ThinVec::new(),
40        }
41    }
42
43    #[inline]
44    pub fn with_capacity(capacity: usize) -> ThinString {
45        ThinString {
46            vec: ThinVec::with_capacity(capacity),
47        }
48    }
49
50    #[inline]
51    pub fn from_utf8(vec: ThinVec<u8>) -> Result<ThinString, FromUtf8Error> {
52        match from_utf8(&vec) {
53            Ok(..) => Ok(ThinString { vec }),
54            Err(e) => Err(FromUtf8Error {
55                bytes: vec,
56                error: e,
57            }),
58        }
59    }
60
61    #[inline]
62    pub fn from_utf8_lossy(v: &[u8]) -> ThinString {
63        let mut iter = v.utf8_chunks();
64
65        let first_valid = if let Some(chunk) = iter.next() {
66            let valid = chunk.valid();
67            if chunk.invalid().is_empty() {
68                debug_assert_eq!(valid.len(), v.len());
69                return ThinString::from(valid);
70            }
71            valid
72        } else {
73            return ThinString::new();
74        };
75
76        const REPLACEMENT: &str = "\u{FFFD}";
77
78        let mut res = ThinString::with_capacity(v.len());
79        res.push_str(first_valid);
80        res.push_str(REPLACEMENT);
81
82        for chunk in iter {
83            res.push_str(chunk.valid());
84            if !chunk.invalid().is_empty() {
85                res.push_str(REPLACEMENT);
86            }
87        }
88
89        res
90    }
91
92    #[inline]
93    pub fn from_utf16(v: &[u16]) -> Result<ThinString, FromUtf16Error> {
94        let mut ret = ThinString::with_capacity(v.len());
95        for c in decode_utf16(v.iter().cloned()) {
96            if let Ok(c) = c {
97                ret.push(c);
98            } else {
99                return Err(FromUtf16Error(()));
100            }
101        }
102        Ok(ret)
103    }
104
105    #[inline]
106    pub fn from_utf16_lossy(v: &[u16]) -> ThinString {
107        decode_utf16(v.iter().cloned())
108            .map(|r| r.unwrap_or(REPLACEMENT_CHARACTER))
109            .collect()
110    }
111
112    #[inline]
113    pub unsafe fn from_utf8_unchecked(bytes: ThinVec<u8>) -> ThinString {
114        ThinString { vec: bytes }
115    }
116
117    #[inline]
118    pub fn into_bytes(self) -> ThinVec<u8> {
119        self.vec
120    }
121
122    #[inline]
123    pub fn as_str(&self) -> &str {
124        self
125    }
126
127    #[inline]
128    pub fn as_mut_str(&mut self) -> &mut str {
129        self
130    }
131
132    #[inline]
133    pub fn push_str(&mut self, string: &str) {
134        self.vec.extend_from_slice(string.as_bytes())
135    }
136
137    #[inline]
138    pub fn capacity(&self) -> usize {
139        self.vec.capacity()
140    }
141
142    #[inline]
143    pub fn reserve(&mut self, additional: usize) {
144        self.vec.reserve(additional)
145    }
146
147    #[inline]
148    pub fn reserve_exact(&mut self, additional: usize) {
149        self.vec.reserve_exact(additional)
150    }
151
152    #[inline]
153    pub fn shrink_to_fit(&mut self) {
154        self.vec.shrink_to_fit()
155    }
156
157    #[inline]
158    pub fn push(&mut self, ch: char) {
159        match ch.len_utf8() {
160            1 => self.vec.push(ch as u8),
161            _ => self
162                .vec
163                .extend_from_slice(ch.encode_utf8(&mut [0; 4]).as_bytes()),
164        }
165    }
166
167    #[inline]
168    pub fn as_bytes(&self) -> &[u8] {
169        &self.vec
170    }
171
172    #[inline]
173    pub fn truncate(&mut self, new_len: usize) {
174        if new_len <= self.len() {
175            assert!(self.is_char_boundary(new_len));
176            self.vec.truncate(new_len)
177        }
178    }
179
180    #[inline]
181    pub fn pop(&mut self) -> Option<char> {
182        let ch = self.chars().rev().next()?;
183        let newlen = self.len() - ch.len_utf8();
184        unsafe {
185            self.vec.set_len(newlen);
186        }
187        Some(ch)
188    }
189
190    #[inline]
191    pub fn remove(&mut self, idx: usize) -> char {
192        let ch = match self[idx..].chars().next() {
193            Some(ch) => ch,
194            None => panic!("cannot remove a char from the end of a string"),
195        };
196
197        let next = idx + ch.len_utf8();
198        let len = self.len();
199        unsafe {
200            ptr::copy(
201                self.vec.as_ptr().add(next),
202                self.vec.as_mut_ptr().add(idx),
203                len - next,
204            );
205            self.vec.set_len(len - (next - idx));
206        }
207        ch
208    }
209
210    #[cfg(feature = "nightly")]
211    pub fn remove_matches<P: Pattern>(&mut self, pat: P) {
212        use core::str::pattern::Searcher;
213
214        let rejections = {
215            let mut searcher = pat.into_searcher(self);
216            // Per Searcher::next:
217            //
218            // A Match result needs to contain the whole matched pattern,
219            // however Reject results may be split up into arbitrary many
220            // adjacent fragments. Both ranges may have zero length.
221            //
222            // In practice the implementation of Searcher::next_match tends to
223            // be more efficient, so we use it here and do some work to invert
224            // matches into rejections since that's what we want to copy below.
225            let mut front = 0;
226            let rejections: Vec<_> = from_fn(|| {
227                let (start, end) = searcher.next_match()?;
228                let prev_front = front;
229                front = end;
230                Some((prev_front, start))
231            })
232            .collect();
233            rejections
234                .into_iter()
235                .chain(core::iter::once((front, self.len())))
236        };
237
238        let mut len = 0;
239        let ptr = self.vec.as_mut_ptr();
240
241        for (start, end) in rejections {
242            let count = end - start;
243            if start != len {
244                // SAFETY: per Searcher::next:
245                //
246                // The stream of Match and Reject values up to a Done will
247                // contain index ranges that are adjacent, non-overlapping,
248                // covering the whole haystack, and laying on utf8
249                // boundaries.
250                unsafe {
251                    ptr::copy(ptr.add(start), ptr.add(len), count);
252                }
253            }
254            len += count;
255        }
256
257        unsafe {
258            self.vec.set_len(len);
259        }
260    }
261
262    #[inline]
263    pub fn retain<F>(&mut self, mut f: F)
264    where
265        F: FnMut(char) -> bool,
266    {
267        struct SetLenOnDrop<'a> {
268            s: &'a mut ThinString,
269            idx: usize,
270            del_bytes: usize,
271        }
272
273        impl<'a> Drop for SetLenOnDrop<'a> {
274            fn drop(&mut self) {
275                let new_len = self.idx - self.del_bytes;
276                debug_assert!(new_len <= self.s.len());
277                unsafe { self.s.vec.set_len(new_len) };
278            }
279        }
280
281        let len = self.len();
282        let mut guard = SetLenOnDrop {
283            s: self,
284            idx: 0,
285            del_bytes: 0,
286        };
287
288        while guard.idx < len {
289            let ch = unsafe {
290                guard
291                    .s
292                    .get_unchecked(guard.idx..len)
293                    .chars()
294                    .next()
295                    .unwrap()
296            };
297            let ch_len = ch.len_utf8();
298
299            if !f(ch) {
300                guard.del_bytes += ch_len;
301            } else if guard.del_bytes > 0 {
302                unsafe {
303                    ptr::copy(
304                        guard.s.vec.as_slice().as_ptr().add(guard.idx),
305                        guard
306                            .s
307                            .vec
308                            .as_mut_slice()
309                            .as_mut_ptr()
310                            .add(guard.idx - guard.del_bytes),
311                        ch_len,
312                    );
313                }
314            }
315
316            // Point idx to the next char
317            guard.idx += ch_len;
318        }
319
320        drop(guard);
321    }
322
323    #[inline]
324    pub fn insert(&mut self, idx: usize, ch: char) {
325        assert!(self.is_char_boundary(idx));
326        let mut bits = [0; 4];
327        let bits = ch.encode_utf8(&mut bits).as_bytes();
328
329        unsafe {
330            self.insert_bytes(idx, bits);
331        }
332    }
333
334    unsafe fn insert_bytes(&mut self, idx: usize, bytes: &[u8]) {
335        let len = self.len();
336        let amt = bytes.len();
337        self.vec.reserve(amt);
338
339        ptr::copy(
340            self.vec.as_slice().as_ptr().add(idx),
341            self.vec.as_mut_slice().as_mut_ptr().add(idx + amt),
342            len - idx,
343        );
344        ptr::copy_nonoverlapping(bytes.as_ptr(), self.vec.as_mut_ptr().add(idx), amt);
345        self.vec.set_len(len + amt);
346    }
347
348    #[inline]
349    pub fn insert_str(&mut self, idx: usize, string: &str) {
350        assert!(self.is_char_boundary(idx));
351
352        unsafe {
353            self.insert_bytes(idx, string.as_bytes());
354        }
355    }
356
357    #[inline]
358    pub unsafe fn as_mut_vec(&mut self) -> &mut ThinVec<u8> {
359        &mut self.vec
360    }
361
362    #[inline]
363    pub fn len(&self) -> usize {
364        self.vec.len()
365    }
366
367    #[inline]
368    pub fn is_empty(&self) -> bool {
369        self.len() == 0
370    }
371
372    #[inline]
373    #[must_use = "use `.truncate()` if you don't need the other half"]
374    pub fn split_off(&mut self, at: usize) -> ThinString {
375        assert!(self.is_char_boundary(at));
376        let other = self.vec.split_off(at);
377        unsafe { ThinString::from_utf8_unchecked(other) }
378    }
379
380    #[inline]
381    pub fn clear(&mut self) {
382        self.vec.clear()
383    }
384
385    #[inline]
386    pub fn drain<R>(&mut self, range: R) -> Drain<'_>
387    where
388        R: RangeBounds<usize>,
389    {
390        #[cfg(not(feature = "nightly"))]
391        /// `std::slice::range()`
392        #[track_caller]
393        #[must_use]
394        pub fn std_slice_range<R>(range: R, bounds: ops::RangeTo<usize>) -> ops::Range<usize>
395        where
396            R: ops::RangeBounds<usize>,
397        {
398            let len = bounds.end;
399
400            let start = match range.start_bound() {
401                ops::Bound::Included(&start) => start,
402                ops::Bound::Excluded(start) => start
403                    .checked_add(1)
404                    .unwrap_or_else(|| panic!("attempted to index slice from after maximum usize")),
405                ops::Bound::Unbounded => 0,
406            };
407
408            let end = match range.end_bound() {
409                ops::Bound::Included(end) => end
410                    .checked_add(1)
411                    .unwrap_or_else(|| panic!("attempted to index slice up to maximum usize")),
412                ops::Bound::Excluded(&end) => end,
413                ops::Bound::Unbounded => len,
414            };
415
416            if start > end {
417                panic!("slice index starts at {} but ends at {}", start, end);
418            }
419            if end > len {
420                panic!(
421                    "range end index {} out of range for slice of length {}",
422                    end, len
423                );
424            }
425
426            ops::Range { start, end }
427        }
428        #[cfg(feature = "nightly")]
429        use std::slice::range as std_slice_range;
430
431        // Memory safety
432        //
433        // The ThinString version of Drain does not have the memory safety issues
434        // of the vector version. The data is just plain bytes.
435        // Because the range removal happens in Drop, if the Drain iterator is leaked,
436        // the removal will not happen.
437        let Range { start, end } = std_slice_range(range, ..self.len());
438        assert!(self.is_char_boundary(start));
439        assert!(self.is_char_boundary(end));
440
441        // Take out two simultaneous borrows. The &mut ThinString won't be accessed
442        // until iteration is over, in Drop.
443        let self_ptr = self as *mut _;
444        // SAFETY: `slice::range` and `is_char_boundary` do the appropriate bounds checks.
445        let chars_iter = unsafe { self.get_unchecked(start..end) }.chars();
446
447        Drain {
448            start,
449            end,
450            iter: chars_iter,
451            string: self_ptr,
452        }
453    }
454}
455
456impl FromUtf8Error {
457    #[inline]
458    pub fn as_bytes(&self) -> &[u8] {
459        &self.bytes[..]
460    }
461
462    #[inline]
463    pub fn into_bytes(self) -> ThinVec<u8> {
464        self.bytes
465    }
466
467    #[inline]
468    pub fn utf8_error(&self) -> Utf8Error {
469        self.error
470    }
471}
472
473impl fmt::Display for FromUtf8Error {
474    #[inline]
475    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
476        fmt::Display::fmt(&self.error, f)
477    }
478}
479
480impl fmt::Display for FromUtf16Error {
481    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
482        fmt::Display::fmt("invalid utf-16: lone surrogate found", f)
483    }
484}
485
486impl Clone for ThinString {
487    fn clone(&self) -> Self {
488        ThinString {
489            vec: self.vec.clone(),
490        }
491    }
492
493    fn clone_from(&mut self, source: &Self) {
494        self.vec.clone_from(&source.vec);
495    }
496}
497
498impl FromIterator<char> for ThinString {
499    fn from_iter<I: IntoIterator<Item = char>>(iter: I) -> ThinString {
500        let mut buf = ThinString::new();
501        buf.extend(iter);
502        buf
503    }
504}
505
506impl<'a> FromIterator<&'a char> for ThinString {
507    fn from_iter<I: IntoIterator<Item = &'a char>>(iter: I) -> ThinString {
508        let mut buf = ThinString::new();
509        buf.extend(iter);
510        buf
511    }
512}
513
514impl<'a> FromIterator<&'a str> for ThinString {
515    fn from_iter<I: IntoIterator<Item = &'a str>>(iter: I) -> ThinString {
516        let mut buf = ThinString::new();
517        buf.extend(iter);
518        buf
519    }
520}
521
522impl FromIterator<ThinString> for ThinString {
523    fn from_iter<I: IntoIterator<Item = ThinString>>(iter: I) -> ThinString {
524        let mut iterator = iter.into_iter();
525
526        // Because we're iterating over `String`s, we can avoid at least
527        // one allocation by getting the first string from the iterator
528        // and appending to it all the subsequent strings.
529        match iterator.next() {
530            None => ThinString::new(),
531            Some(mut buf) => {
532                buf.extend(iterator);
533                buf
534            }
535        }
536    }
537}
538
539impl FromIterator<Box<str>> for ThinString {
540    fn from_iter<I: IntoIterator<Item = Box<str>>>(iter: I) -> ThinString {
541        let mut buf = ThinString::new();
542        buf.extend(iter);
543        buf
544    }
545}
546
547impl<'a> FromIterator<Cow<'a, str>> for ThinString {
548    fn from_iter<I: IntoIterator<Item = Cow<'a, str>>>(iter: I) -> ThinString {
549        let mut iterator = iter.into_iter();
550
551        // Because we're iterating over CoWs, we can (potentially) avoid at least
552        // one allocation by getting the first item and appending to it all the
553        // subsequent items.
554        match iterator.next() {
555            None => ThinString::new(),
556            Some(cow) => {
557                let mut buf = cow.to_thin_string();
558                buf.extend(iterator);
559                buf
560            }
561        }
562    }
563}
564
565impl Extend<char> for ThinString {
566    fn extend<I: IntoIterator<Item = char>>(&mut self, iter: I) {
567        let iterator = iter.into_iter();
568        let (lower_bound, _) = iterator.size_hint();
569        self.reserve(lower_bound);
570        iterator.for_each(move |c| self.push(c));
571    }
572
573    #[cfg(feature = "nightly")]
574    #[inline]
575    fn extend_one(&mut self, c: char) {
576        self.push(c);
577    }
578
579    #[cfg(feature = "nightly")]
580    #[inline]
581    fn extend_reserve(&mut self, additional: usize) {
582        self.reserve(additional);
583    }
584}
585
586impl<'a> Extend<&'a char> for ThinString {
587    fn extend<I: IntoIterator<Item = &'a char>>(&mut self, iter: I) {
588        self.extend(iter.into_iter().cloned());
589    }
590
591    #[cfg(feature = "nightly")]
592    #[inline]
593    fn extend_one(&mut self, &c: &'a char) {
594        self.push(c);
595    }
596
597    #[cfg(feature = "nightly")]
598    #[inline]
599    fn extend_reserve(&mut self, additional: usize) {
600        self.reserve(additional);
601    }
602}
603
604impl<'a> Extend<&'a str> for ThinString {
605    fn extend<I: IntoIterator<Item = &'a str>>(&mut self, iter: I) {
606        iter.into_iter().for_each(move |s| self.push_str(s));
607    }
608
609    #[cfg(feature = "nightly")]
610    #[inline]
611    fn extend_one(&mut self, s: &'a str) {
612        self.push_str(s);
613    }
614}
615
616impl Extend<Box<str>> for ThinString {
617    fn extend<I: IntoIterator<Item = Box<str>>>(&mut self, iter: I) {
618        iter.into_iter().for_each(move |s| self.push_str(&s));
619    }
620}
621
622impl Extend<ThinString> for ThinString {
623    fn extend<I: IntoIterator<Item = ThinString>>(&mut self, iter: I) {
624        iter.into_iter().for_each(move |s| self.push_str(&s));
625    }
626
627    #[cfg(feature = "nightly")]
628    #[inline]
629    fn extend_one(&mut self, s: ThinString) {
630        self.push_str(&s);
631    }
632}
633
634impl<'a> Extend<Cow<'a, str>> for ThinString {
635    fn extend<I: IntoIterator<Item = Cow<'a, str>>>(&mut self, iter: I) {
636        iter.into_iter().for_each(move |s| self.push_str(&s));
637    }
638
639    #[cfg(feature = "nightly")]
640    #[inline]
641    fn extend_one(&mut self, s: Cow<'a, str>) {
642        self.push_str(&s);
643    }
644}
645
646impl PartialEq for ThinString {
647    #[inline]
648    fn eq(&self, other: &ThinString) -> bool {
649        PartialEq::eq(&self[..], &other[..])
650    }
651    #[inline]
652    fn ne(&self, other: &ThinString) -> bool {
653        PartialEq::ne(&self[..], &other[..])
654    }
655}
656
657#[doc(hidden)]
658macro_rules! impl_eq {
659    ($lhs:ty, $rhs: ty) => {
660        #[allow(unused_lifetimes)]
661        impl<'a, 'b> PartialEq<$rhs> for $lhs {
662            #[inline]
663            fn eq(&self, other: &$rhs) -> bool {
664                PartialEq::eq(&self[..], &other[..])
665            }
666            #[inline]
667            fn ne(&self, other: &$rhs) -> bool {
668                PartialEq::ne(&self[..], &other[..])
669            }
670        }
671
672        #[allow(unused_lifetimes)]
673        impl<'a, 'b> PartialEq<$lhs> for $rhs {
674            #[inline]
675            fn eq(&self, other: &$lhs) -> bool {
676                PartialEq::eq(&self[..], &other[..])
677            }
678            #[inline]
679            fn ne(&self, other: &$lhs) -> bool {
680                PartialEq::ne(&self[..], &other[..])
681            }
682        }
683    };
684}
685
686impl_eq! { ThinString, str }
687impl_eq! { ThinString, &'a str }
688impl_eq! { Cow<'a, str>, ThinString }
689
690impl Default for ThinString {
691    /// Creates an empty `String`.
692    #[inline]
693    fn default() -> ThinString {
694        ThinString::new()
695    }
696}
697
698impl fmt::Display for ThinString {
699    #[inline]
700    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
701        fmt::Display::fmt(&**self, f)
702    }
703}
704
705impl fmt::Debug for ThinString {
706    #[inline]
707    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
708        fmt::Debug::fmt(&**self, f)
709    }
710}
711
712impl hash::Hash for ThinString {
713    #[inline]
714    fn hash<H: hash::Hasher>(&self, hasher: &mut H) {
715        (**self).hash(hasher)
716    }
717}
718
719impl Add<&str> for ThinString {
720    type Output = ThinString;
721
722    #[inline]
723    fn add(mut self, other: &str) -> ThinString {
724        self.push_str(other);
725        self
726    }
727}
728
729impl AddAssign<&str> for ThinString {
730    #[inline]
731    fn add_assign(&mut self, other: &str) {
732        self.push_str(other);
733    }
734}
735
736impl ops::Index<ops::Range<usize>> for ThinString {
737    type Output = str;
738
739    #[inline]
740    fn index(&self, index: ops::Range<usize>) -> &str {
741        &self[..][index]
742    }
743}
744
745impl ops::Index<ops::RangeTo<usize>> for ThinString {
746    type Output = str;
747
748    #[inline]
749    fn index(&self, index: ops::RangeTo<usize>) -> &str {
750        &self[..][index]
751    }
752}
753
754impl ops::Index<ops::RangeFrom<usize>> for ThinString {
755    type Output = str;
756
757    #[inline]
758    fn index(&self, index: ops::RangeFrom<usize>) -> &str {
759        &self[..][index]
760    }
761}
762
763impl ops::Index<ops::RangeFull> for ThinString {
764    type Output = str;
765
766    #[inline]
767    fn index(&self, _index: ops::RangeFull) -> &str {
768        unsafe { from_utf8_unchecked(&self.vec) }
769    }
770}
771
772impl ops::Index<ops::RangeInclusive<usize>> for ThinString {
773    type Output = str;
774
775    #[inline]
776    fn index(&self, index: ops::RangeInclusive<usize>) -> &str {
777        Index::index(&**self, index)
778    }
779}
780
781impl ops::Index<ops::RangeToInclusive<usize>> for ThinString {
782    type Output = str;
783
784    #[inline]
785    fn index(&self, index: ops::RangeToInclusive<usize>) -> &str {
786        Index::index(&**self, index)
787    }
788}
789
790impl ops::IndexMut<ops::Range<usize>> for ThinString {
791    #[inline]
792    fn index_mut(&mut self, index: ops::Range<usize>) -> &mut str {
793        &mut self[..][index]
794    }
795}
796
797impl ops::IndexMut<ops::RangeTo<usize>> for ThinString {
798    #[inline]
799    fn index_mut(&mut self, index: ops::RangeTo<usize>) -> &mut str {
800        &mut self[..][index]
801    }
802}
803
804impl ops::IndexMut<ops::RangeFrom<usize>> for ThinString {
805    #[inline]
806    fn index_mut(&mut self, index: ops::RangeFrom<usize>) -> &mut str {
807        &mut self[..][index]
808    }
809}
810
811impl ops::IndexMut<ops::RangeFull> for ThinString {
812    #[inline]
813    fn index_mut(&mut self, _index: ops::RangeFull) -> &mut str {
814        unsafe { from_utf8_unchecked_mut(&mut self.vec) }
815    }
816}
817
818impl ops::IndexMut<ops::RangeInclusive<usize>> for ThinString {
819    #[inline]
820    fn index_mut(&mut self, index: ops::RangeInclusive<usize>) -> &mut str {
821        IndexMut::index_mut(&mut **self, index)
822    }
823}
824
825impl ops::IndexMut<ops::RangeToInclusive<usize>> for ThinString {
826    #[inline]
827    fn index_mut(&mut self, index: ops::RangeToInclusive<usize>) -> &mut str {
828        IndexMut::index_mut(&mut **self, index)
829    }
830}
831
832impl ops::Deref for ThinString {
833    type Target = str;
834
835    #[inline]
836    fn deref(&self) -> &str {
837        unsafe { from_utf8_unchecked(&self.vec) }
838    }
839}
840
841impl ops::DerefMut for ThinString {
842    #[inline]
843    fn deref_mut(&mut self) -> &mut str {
844        unsafe { from_utf8_unchecked_mut(&mut self.vec) }
845    }
846}
847
848pub type ParseError = core::convert::Infallible;
849
850impl FromStr for ThinString {
851    type Err = core::convert::Infallible;
852    #[inline]
853    fn from_str(s: &str) -> Result<ThinString, Self::Err> {
854        Ok(ThinString::from(s))
855    }
856}
857
858impl From<String> for ThinString {
859    #[inline]
860    fn from(string: String) -> ThinString {
861        ThinString::from(string.as_str())
862    }
863}
864
865impl From<ThinString> for String {
866    #[inline]
867    fn from(string: ThinString) -> String {
868        string.to_string()
869    }
870}
871
872pub trait ToThinString {
873    fn to_thin_string(&self) -> ThinString;
874}
875
876#[cfg(not(feature = "nightly"))]
877impl<T: fmt::Display + ?Sized> ToThinString for T {
878    #[inline]
879    fn to_thin_string(&self) -> ThinString {
880        use fmt::Write as _;
881        let mut buf = ThinString::new();
882        write!(&mut buf, "{}", self)
883            .expect("a Display implementation returned an error unexpectedly");
884        buf
885    }
886}
887
888#[cfg(feature = "nightly")]
889impl<T: fmt::Display + ?Sized> ToThinString for T {
890    #[inline]
891    default fn to_thin_string(&self) -> ThinString {
892        let mut buf = ThinString::new();
893        let mut formatter = core::fmt::Formatter::new(&mut buf);
894        // Bypass format_args!() to avoid write_str with zero-length strs
895        fmt::Display::fmt(self, &mut formatter)
896            .expect("a Display implementation returned an error unexpectedly");
897        buf
898    }
899}
900
901#[cfg(feature = "nightly")]
902impl ToThinString for char {
903    #[inline]
904    fn to_thin_string(&self) -> ThinString {
905        ThinString::from(self.encode_utf8(&mut [0; 4]))
906    }
907}
908
909#[cfg(feature = "nightly")]
910impl ToThinString for u8 {
911    #[inline]
912    fn to_thin_string(&self) -> ThinString {
913        let mut buf = ThinString::with_capacity(3);
914        let mut n = *self;
915        if n >= 10 {
916            if n >= 100 {
917                buf.push((b'0' + n / 100) as char);
918                n %= 100;
919            }
920            buf.push((b'0' + n / 10) as char);
921            n %= 10;
922        }
923        buf.push((b'0' + n) as char);
924        buf
925    }
926}
927
928#[cfg(feature = "nightly")]
929impl ToThinString for i8 {
930    #[inline]
931    fn to_thin_string(&self) -> ThinString {
932        let mut buf = ThinString::with_capacity(4);
933        if self.is_negative() {
934            buf.push('-');
935        }
936        let mut n = self.unsigned_abs();
937        if n >= 10 {
938            if n >= 100 {
939                buf.push('1');
940                n -= 100;
941            }
942            buf.push((b'0' + n / 10) as char);
943            n %= 10;
944        }
945        buf.push((b'0' + n) as char);
946        buf
947    }
948}
949
950#[cfg(feature = "nightly")]
951impl ToThinString for str {
952    #[inline]
953    fn to_thin_string(&self) -> ThinString {
954        ThinString::from(self)
955    }
956}
957
958#[cfg(feature = "nightly")]
959impl ToThinString for Cow<'_, str> {
960    #[inline]
961    fn to_thin_string(&self) -> ThinString {
962        self[..].to_thin_string()
963    }
964}
965
966#[cfg(feature = "nightly")]
967impl ToThinString for ThinString {
968    #[inline]
969    fn to_thin_string(&self) -> ThinString {
970        self.to_owned()
971    }
972}
973
974impl AsRef<str> for ThinString {
975    #[inline]
976    fn as_ref(&self) -> &str {
977        self
978    }
979}
980
981impl AsMut<str> for ThinString {
982    #[inline]
983    fn as_mut(&mut self) -> &mut str {
984        self
985    }
986}
987
988impl AsRef<[u8]> for ThinString {
989    #[inline]
990    fn as_ref(&self) -> &[u8] {
991        self.as_bytes()
992    }
993}
994
995impl From<&str> for ThinString {
996    fn from(s: &str) -> ThinString {
997        let mut vec = ThinVec::with_capacity(s.bytes().len());
998        vec.extend_from_slice(s.as_bytes());
999        ThinString { vec }
1000    }
1001}
1002
1003impl From<&mut str> for ThinString {
1004    #[inline]
1005    fn from(s: &mut str) -> ThinString {
1006        let mut vec = ThinVec::with_capacity(s.bytes().len());
1007        vec.extend_from_slice(s.as_bytes());
1008        ThinString { vec }
1009    }
1010}
1011
1012impl From<&ThinString> for ThinString {
1013    #[inline]
1014    fn from(s: &ThinString) -> ThinString {
1015        s.clone()
1016    }
1017}
1018
1019impl<'a> From<Cow<'a, str>> for ThinString {
1020    fn from(s: Cow<'a, str>) -> ThinString {
1021        s.to_thin_string()
1022    }
1023}
1024
1025impl<'a> From<&'a ThinString> for Cow<'a, str> {
1026    #[inline]
1027    fn from(s: &'a ThinString) -> Cow<'a, str> {
1028        Cow::Borrowed(s.as_str())
1029    }
1030}
1031
1032impl From<ThinString> for ThinVec<u8> {
1033    fn from(string: ThinString) -> ThinVec<u8> {
1034        string.into_bytes()
1035    }
1036}
1037
1038impl fmt::Write for ThinString {
1039    #[inline]
1040    fn write_str(&mut self, s: &str) -> fmt::Result {
1041        self.push_str(s);
1042        Ok(())
1043    }
1044
1045    #[inline]
1046    fn write_char(&mut self, c: char) -> fmt::Result {
1047        self.push(c);
1048        Ok(())
1049    }
1050}
1051
1052pub struct Drain<'a> {
1053    /// Will be used as &'a mut ThinString in the destructor
1054    string: *mut ThinString,
1055    /// Start of part to remove
1056    start: usize,
1057    /// End of part to remove
1058    end: usize,
1059    /// Current remaining range to remove
1060    iter: Chars<'a>,
1061}
1062
1063impl fmt::Debug for Drain<'_> {
1064    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1065        f.debug_tuple("Drain").field(&self.as_str()).finish()
1066    }
1067}
1068
1069unsafe impl Sync for Drain<'_> {}
1070unsafe impl Send for Drain<'_> {}
1071
1072impl Drop for Drain<'_> {
1073    #[inline]
1074    fn drop(&mut self) {
1075        unsafe {
1076            // Use ThinVec::drain. "Reaffirm" the bounds checks to avoid
1077            // panic code being inserted again.
1078            let self_vec = (*self.string).as_mut_vec();
1079            if self.start <= self.end && self.end <= self_vec.len() {
1080                self_vec.drain(self.start..self.end);
1081            }
1082        }
1083    }
1084}
1085
1086impl<'a> Drain<'a> {
1087    #[inline]
1088    pub fn as_str(&self) -> &str {
1089        self.iter.as_str()
1090    }
1091}
1092
1093impl Iterator for Drain<'_> {
1094    type Item = char;
1095
1096    #[inline]
1097    fn next(&mut self) -> Option<char> {
1098        self.iter.next()
1099    }
1100
1101    fn size_hint(&self) -> (usize, Option<usize>) {
1102        self.iter.size_hint()
1103    }
1104
1105    #[inline]
1106    fn last(mut self) -> Option<char> {
1107        self.next_back()
1108    }
1109}
1110
1111impl DoubleEndedIterator for Drain<'_> {
1112    #[inline]
1113    fn next_back(&mut self) -> Option<char> {
1114        self.iter.next_back()
1115    }
1116}
1117
1118impl FusedIterator for Drain<'_> {}
1119
1120impl From<char> for ThinString {
1121    #[inline]
1122    fn from(c: char) -> Self {
1123        c.to_thin_string()
1124    }
1125}
1126
1127#[cfg(feature = "serde")]
1128impl serde::Serialize for ThinString {
1129    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1130    where
1131        S: serde::Serializer,
1132    {
1133        serializer.serialize_str(self.as_str())
1134    }
1135}
1136
1137#[cfg(feature = "serde")]
1138impl<'de> serde::Deserialize<'de> for ThinString {
1139    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1140    where
1141        D: serde::Deserializer<'de>,
1142    {
1143        use serde::de::{Error, Unexpected, Visitor};
1144
1145        struct ThinStringVisitor;
1146
1147        impl<'de> Visitor<'de> for ThinStringVisitor {
1148            type Value = ThinString;
1149
1150            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
1151                write!(formatter, "a string")
1152            }
1153
1154            fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
1155            where
1156                E: serde::de::Error,
1157            {
1158                Ok(v.into())
1159            }
1160
1161            fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
1162            where
1163                E: serde::de::Error,
1164            {
1165                match from_utf8(v) {
1166                    Ok(u) => Ok(u.into()),
1167                    Err(_) => Err(Error::invalid_value(Unexpected::Bytes(v), &self)),
1168                }
1169            }
1170        }
1171
1172        deserializer.deserialize_str(ThinStringVisitor)
1173    }
1174}