Skip to main content

compact_str/
lib.rs

1#![doc = include_str!("../README.md")]
2#![cfg_attr(docsrs, feature(doc_cfg))]
3#![no_std]
4
5#[cfg(feature = "std")]
6#[macro_use]
7extern crate std;
8
9#[cfg_attr(test, macro_use)]
10extern crate alloc;
11
12use alloc::borrow::Cow;
13use alloc::boxed::Box;
14use alloc::string::String;
15use castaway::match_type;
16#[doc(hidden)] // Referenced in macros.
17pub use core;
18use core::borrow::{Borrow, BorrowMut};
19use core::cmp::Ordering;
20use core::hash::{Hash, Hasher};
21use core::iter::FusedIterator;
22use core::ops::{Add, AddAssign, Bound, Deref, DerefMut, RangeBounds};
23use core::str::{FromStr, Utf8Error};
24use core::{fmt, mem, slice};
25#[cfg(feature = "std")]
26use std::ffi::OsStr;
27
28mod features;
29mod macros;
30mod unicode_data;
31
32mod repr;
33use repr::Repr;
34
35mod traits;
36pub use traits::{CompactStringExt, ToCompactString};
37
38#[cfg(test)]
39mod tests;
40
41/// A [`CompactString`] is a compact string type that can be used almost anywhere a
42/// [`String`] or [`str`] can be used.
43///
44/// ## Using `CompactString`
45/// ```
46/// use compact_str::CompactString;
47/// # use std::collections::HashMap;
48///
49/// // CompactString auto derefs into a str so you can use all methods from `str`
50/// // that take a `&self`
51/// if CompactString::new("hello world!").is_ascii() {
52///     println!("we're all ASCII")
53/// }
54///
55/// // You can use a CompactString in collections like you would a String or &str
56/// let mut map: HashMap<CompactString, CompactString> = HashMap::new();
57///
58/// // directly construct a new `CompactString`
59/// map.insert(CompactString::new("nyc"), CompactString::new("empire state building"));
60/// // create a `CompactString` from a `&str`
61/// map.insert("sf".into(), "transamerica pyramid".into());
62/// // create a `CompactString` from a `String`
63/// map.insert(String::from("sea").into(), String::from("space needle").into());
64///
65/// fn wrapped_print<T: AsRef<str>>(text: T) {
66///     println!("{}", text.as_ref());
67/// }
68///
69/// // CompactString impls AsRef<str> and Borrow<str>, so it can be used anywhere
70/// // that expects a generic string
71/// if let Some(building) = map.get("nyc") {
72///     wrapped_print(building);
73/// }
74///
75/// // CompactString can also be directly compared to a String or &str
76/// assert_eq!(CompactString::new("chicago"), "chicago");
77/// assert_eq!(CompactString::new("houston"), String::from("houston"));
78/// ```
79///
80/// # Converting from a `String`
81/// It's important that a `CompactString` interops well with `String`, so you can easily use both in
82/// your code base.
83///
84/// `CompactString` implements `From<String>` and operates in the following manner:
85/// - Eagerly inlines the string, possibly dropping excess capacity
86/// - Otherwise re-uses the same underlying buffer from `String`
87///
88/// ```
89/// use compact_str::CompactString;
90///
91/// // eagerly inlining
92/// let short = String::from("hello world");
93/// let short_c = CompactString::from(short);
94/// assert!(!short_c.is_heap_allocated());
95///
96/// // dropping excess capacity
97/// let mut excess = String::with_capacity(256);
98/// excess.push_str("abc");
99///
100/// let excess_c = CompactString::from(excess);
101/// assert!(!excess_c.is_heap_allocated());
102/// assert!(excess_c.capacity() < 256);
103///
104/// // re-using the same buffer
105/// let long = String::from("this is a longer string that will be heap allocated");
106///
107/// let long_ptr = long.as_ptr();
108/// let long_len = long.len();
109/// let long_cap = long.capacity();
110///
111/// let mut long_c = CompactString::from(long);
112/// assert!(long_c.is_heap_allocated());
113///
114/// let cpt_ptr = long_c.as_ptr();
115/// let cpt_len = long_c.len();
116/// let cpt_cap = long_c.capacity();
117///
118/// // the original String and the CompactString point to the same place in memory, buffer re-use!
119/// assert_eq!(cpt_ptr, long_ptr);
120/// assert_eq!(cpt_len, long_len);
121/// assert_eq!(cpt_cap, long_cap);
122/// ```
123///
124/// ### Prevent Eagerly Inlining
125/// A consequence of eagerly inlining is you then need to de-allocate the existing buffer, which
126/// might not always be desirable if you're converting a very large amount of `String`s. If your
127/// code is very sensitive to allocations, consider the [`CompactString::from_string_buffer`] API.
128#[repr(transparent)]
129pub struct CompactString(Repr);
130
131impl CompactString {
132    /// Creates a new [`CompactString`] from any type that implements `AsRef<str>`.
133    /// If the string is short enough, then it will be inlined on the stack! When `text` is an owned
134    /// [`String`] that does not fit inline, its existing allocation is reused.
135    ///
136    /// In a `static` or `const` context you can use the method [`CompactString::const_new()`].
137    ///
138    /// # Examples
139    ///
140    /// ### Inlined
141    /// ```
142    /// # use compact_str::CompactString;
143    /// // We can inline strings up to 12 characters long on 32-bit architectures...
144    /// #[cfg(target_pointer_width = "32")]
145    /// let s = "i'm 12 chars";
146    /// // ...and up to 24 characters on 64-bit architectures!
147    /// #[cfg(target_pointer_width = "64")]
148    /// let s = "i am 24 characters long!";
149    ///
150    /// let compact = CompactString::new(&s);
151    ///
152    /// assert_eq!(compact, s);
153    /// // we are not allocated on the heap!
154    /// assert!(!compact.is_heap_allocated());
155    /// ```
156    ///
157    /// ### Heap
158    /// ```
159    /// # use compact_str::CompactString;
160    /// // For longer strings though, we get allocated on the heap
161    /// let long = "I am a longer string that will be allocated on the heap";
162    /// let compact = CompactString::new(long);
163    ///
164    /// assert_eq!(compact, long);
165    /// // we are allocated on the heap!
166    /// assert!(compact.is_heap_allocated());
167    /// ```
168    ///
169    /// ### Creation
170    /// ```
171    /// use compact_str::CompactString;
172    ///
173    /// // Using a `&'static str`
174    /// let s = "hello world!";
175    /// let hello = CompactString::new(&s);
176    ///
177    /// // Using a `String`
178    /// let u = String::from("🦄🌈");
179    /// let unicorn = CompactString::new(u);
180    ///
181    /// // Using a `Box<str>`
182    /// let b: Box<str> = String::from("📦📦📦").into_boxed_str();
183    /// let boxed = CompactString::new(&b);
184    /// ```
185    #[inline]
186    #[track_caller]
187    pub fn new<T: AsRef<str>>(text: T) -> Self {
188        // Route `&str` through the infallible `new_panic` so the hot inline path avoids the
189        // `Result` machinery, while still reusing an owned `String`'s allocation via `from_string`.
190        let repr = match_type!(text, {
191            String as text => Repr::from_string(text, true).unwrap_with_msg(),
192            text => Repr::new_panic(text.as_ref()),
193        });
194
195        CompactString(repr)
196    }
197
198    /// Fallible version of [`CompactString::new()`]
199    ///
200    /// This method won't panic if the system is out-of-memory, but return an [`ReserveError`].
201    /// Otherwise it behaves the same as [`CompactString::new()`].
202    #[inline]
203    pub fn try_new<T: AsRef<str>>(text: T) -> Result<Self, ReserveError> {
204        let repr = match_type!(text, {
205            String as text => Repr::from_string(text, true)?,
206            text => Repr::new(text.as_ref())?,
207        });
208
209        Ok(CompactString(repr))
210    }
211
212    /// Creates a new inline [`CompactString`] from `&'static str` at compile time.
213    /// Complexity: O(1). As an optimization, short strings get inlined.
214    ///
215    /// In a dynamic context you can use the method [`CompactString::new()`].
216    ///
217    /// # Examples
218    /// ```
219    /// use compact_str::CompactString;
220    ///
221    /// const DEFAULT_NAME: CompactString = CompactString::const_new("untitled");
222    /// ```
223    #[inline]
224    pub const fn const_new(text: &'static str) -> Self {
225        CompactString(Repr::const_new(text))
226    }
227
228    /// Get back the `&'static str` constructed by [`CompactString::const_new`].
229    ///
230    /// If the string was short enough that it could be inlined, then it was inline, and
231    /// this method will return `None`.
232    ///
233    /// # Examples
234    /// ```
235    /// use compact_str::CompactString;
236    ///
237    /// const DEFAULT_NAME: CompactString =
238    ///     CompactString::const_new("That is not dead which can eternal lie.");
239    /// assert_eq!(
240    ///     DEFAULT_NAME.as_static_str().unwrap(),
241    ///     "That is not dead which can eternal lie.",
242    /// );
243    /// ```
244    #[inline]
245    pub const fn as_static_str(&self) -> Option<&'static str> {
246        self.0.as_static_str()
247    }
248
249    /// Creates a new empty [`CompactString`] with the capacity to fit at least `capacity` bytes.
250    ///
251    /// A `CompactString` will inline strings on the stack, if they're small enough. Specifically,
252    /// if the string has a length less than or equal to `std::mem::size_of::<String>` bytes
253    /// then it will be inlined. This also means that `CompactString`s have a minimum capacity
254    /// of `std::mem::size_of::<String>`.
255    ///
256    /// # Panics
257    ///
258    /// This method panics if the system is out-of-memory.
259    /// Use [`CompactString::try_with_capacity()`] if you want to handle such a problem manually.
260    ///
261    /// # Examples
262    ///
263    /// ### "zero" Capacity
264    /// ```
265    /// # use compact_str::CompactString;
266    /// // Creating a CompactString with a capacity of 0 will create
267    /// // one with capacity of std::mem::size_of::<String>();
268    /// let empty = CompactString::with_capacity(0);
269    /// let min_size = std::mem::size_of::<String>();
270    ///
271    /// assert_eq!(empty.capacity(), min_size);
272    /// assert_ne!(0, min_size);
273    /// assert!(!empty.is_heap_allocated());
274    /// ```
275    ///
276    /// ### Max Inline Size
277    /// ```
278    /// # use compact_str::CompactString;
279    /// // Creating a CompactString with a capacity of std::mem::size_of::<String>()
280    /// // will not heap allocate.
281    /// let str_size = std::mem::size_of::<String>();
282    /// let empty = CompactString::with_capacity(str_size);
283    ///
284    /// assert_eq!(empty.capacity(), str_size);
285    /// assert!(!empty.is_heap_allocated());
286    /// ```
287    ///
288    /// ### Heap Allocating
289    /// ```
290    /// # use compact_str::CompactString;
291    /// // If you create a `CompactString` with a capacity greater than
292    /// // `std::mem::size_of::<String>`, it will heap allocated. For heap
293    /// // allocated strings we have a minimum capacity
294    ///
295    /// const MIN_HEAP_CAPACITY: usize = std::mem::size_of::<usize>() * 4;
296    ///
297    /// let heap_size = std::mem::size_of::<String>() + 1;
298    /// let empty = CompactString::with_capacity(heap_size);
299    ///
300    /// assert_eq!(empty.capacity(), MIN_HEAP_CAPACITY);
301    /// assert!(empty.is_heap_allocated());
302    /// ```
303    #[inline]
304    #[track_caller]
305    pub fn with_capacity(capacity: usize) -> Self {
306        Self::try_with_capacity(capacity).unwrap_with_msg()
307    }
308
309    /// Fallible version of [`CompactString::with_capacity()`]
310    ///
311    /// This method won't panic if the system is out-of-memory, but return an [`ReserveError`].
312    /// Otherwise it behaves the same as [`CompactString::with_capacity()`].
313    #[inline]
314    pub fn try_with_capacity(capacity: usize) -> Result<Self, ReserveError> {
315        Repr::with_capacity(capacity).map(CompactString)
316    }
317
318    /// Convert a slice of bytes into a [`CompactString`].
319    ///
320    /// A [`CompactString`] is a contiguous collection of bytes (`u8`s) that is valid [`UTF-8`](https://en.wikipedia.org/wiki/UTF-8).
321    /// This method converts from an arbitrary contiguous collection of bytes into a
322    /// [`CompactString`], failing if the provided bytes are not `UTF-8`.
323    ///
324    /// Note: If you want to create a [`CompactString`] from a non-contiguous collection of bytes,
325    /// enable the `bytes` feature of this crate, and see `CompactString::from_utf8_buf`
326    ///
327    /// # Examples
328    /// ### Valid UTF-8
329    /// ```
330    /// # use compact_str::CompactString;
331    /// let bytes = vec![240, 159, 166, 128, 240, 159, 146, 175];
332    /// let compact = CompactString::from_utf8(bytes).expect("valid UTF-8");
333    ///
334    /// assert_eq!(compact, "🦀💯");
335    /// ```
336    ///
337    /// ### Invalid UTF-8
338    /// ```
339    /// # use compact_str::CompactString;
340    /// let bytes = vec![255, 255, 255];
341    /// let result = CompactString::from_utf8(bytes);
342    ///
343    /// assert!(result.is_err());
344    /// ```
345    #[inline]
346    pub fn from_utf8<B: AsRef<[u8]>>(buf: B) -> Result<Self, Utf8Error> {
347        Repr::from_utf8(buf).map(CompactString)
348    }
349
350    /// Converts a vector of bytes to a [`CompactString`] without checking that the string contains
351    /// valid UTF-8.
352    ///
353    /// See the safe version, [`CompactString::from_utf8`], for more details.
354    ///
355    /// # Safety
356    ///
357    /// * The contents pased to this method must be valid UTF-8.
358    ///
359    /// It's very important that this constraint is upheld because the internals of a
360    /// [`CompactString`] (e.g. determing an inline string versus a heap allocated string) rely on
361    /// the [`CompactString`] containing valid UTF-8. If this constraint is violated any further
362    /// use of the returned [`CompactString`] (including dropping it) can cause undefined behavior.
363    ///
364    /// # Examples
365    ///
366    /// Basic usage:
367    ///
368    /// ```
369    /// # use compact_str::CompactString;
370    /// // some bytes, in a vector
371    /// let sparkle_heart = vec![240, 159, 146, 150];
372    ///
373    /// let sparkle_heart = unsafe {
374    ///     CompactString::from_utf8_unchecked(sparkle_heart)
375    /// };
376    ///
377    /// assert_eq!("💖", sparkle_heart);
378    /// ```
379    #[inline]
380    #[must_use]
381    #[track_caller]
382    pub unsafe fn from_utf8_unchecked<B: AsRef<[u8]>>(buf: B) -> Self {
383        Repr::from_utf8_unchecked(buf)
384            .map(CompactString)
385            .unwrap_with_msg()
386    }
387
388    /// Decode a [`UTF-16`](https://en.wikipedia.org/wiki/UTF-16) slice of bytes into a
389    /// [`CompactString`], returning an [`Err`] if the slice contains any invalid data.
390    ///
391    /// # Examples
392    /// ### Valid UTF-16
393    /// ```
394    /// # use compact_str::CompactString;
395    /// let buf: &[u16] = &[0xD834, 0xDD1E, 0x006d, 0x0075, 0x0073, 0x0069, 0x0063];
396    /// let compact = CompactString::from_utf16(buf).unwrap();
397    ///
398    /// assert_eq!(compact, "𝄞music");
399    /// ```
400    ///
401    /// ### Invalid UTF-16
402    /// ```
403    /// # use compact_str::CompactString;
404    /// let buf: &[u16] = &[0xD834, 0xDD1E, 0x006d, 0x0075, 0xD800, 0x0069, 0x0063];
405    /// let res = CompactString::from_utf16(buf);
406    ///
407    /// assert!(res.is_err());
408    /// ```
409    #[inline]
410    pub fn from_utf16<B: AsRef<[u16]>>(buf: B) -> Result<Self, Utf16Error> {
411        // Note: we don't use collect::<Result<_, _>>() because that fails to pre-allocate a buffer,
412        // even though the size of our iterator, `buf`, is known ahead of time.
413        //
414        // rustlang issue #48994 is tracking the fix
415
416        let buf = buf.as_ref();
417        let mut ret = CompactString::with_capacity(buf.len());
418        for c in core::char::decode_utf16(buf.iter().copied()) {
419            if let Ok(c) = c {
420                ret.push(c);
421            } else {
422                return Err(Utf16Error(()));
423            }
424        }
425        Ok(ret)
426    }
427
428    /// Decode a UTF-16–encoded slice `v` into a `CompactString`, replacing invalid data with
429    /// the replacement character (`U+FFFD`), �.
430    ///
431    /// # Examples
432    ///
433    /// Basic usage:
434    ///
435    /// ```
436    /// # use compact_str::CompactString;
437    /// // 𝄞mus<invalid>ic<invalid>
438    /// let v = &[0xD834, 0xDD1E, 0x006d, 0x0075,
439    ///           0x0073, 0xDD1E, 0x0069, 0x0063,
440    ///           0xD834];
441    ///
442    /// assert_eq!(CompactString::from("𝄞mus\u{FFFD}ic\u{FFFD}"),
443    ///            CompactString::from_utf16_lossy(v));
444    /// ```
445    #[inline]
446    pub fn from_utf16_lossy<B: AsRef<[u16]>>(buf: B) -> Self {
447        let buf = buf.as_ref();
448        let mut ret = CompactString::with_capacity(buf.len());
449        for c in core::char::decode_utf16(buf.iter().copied()) {
450            match c {
451                Ok(c) => ret.push(c),
452                Err(_) => ret.push_str("�"),
453            }
454        }
455        ret
456    }
457
458    /// Returns the length of the [`CompactString`] in `bytes`, not [`char`]s or graphemes.
459    ///
460    /// When using `UTF-8` encoding (which all strings in Rust do) a single character will be 1 to 4
461    /// bytes long, therefore the return value of this method might not be what a human considers
462    /// the length of the string.
463    ///
464    /// # Examples
465    /// ```
466    /// # use compact_str::CompactString;
467    /// let ascii = CompactString::new("hello world");
468    /// assert_eq!(ascii.len(), 11);
469    ///
470    /// let emoji = CompactString::new("👱");
471    /// assert_eq!(emoji.len(), 4);
472    /// ```
473    #[inline]
474    pub fn len(&self) -> usize {
475        self.0.len()
476    }
477
478    /// Returns `true` if the [`CompactString`] has a length of 0, `false` otherwise
479    ///
480    /// # Examples
481    /// ```
482    /// # use compact_str::CompactString;
483    /// let mut msg = CompactString::new("");
484    /// assert!(msg.is_empty());
485    ///
486    /// // add some characters
487    /// msg.push_str("hello reader!");
488    /// assert!(!msg.is_empty());
489    /// ```
490    #[inline]
491    pub fn is_empty(&self) -> bool {
492        self.0.is_empty()
493    }
494
495    /// Returns the capacity of the [`CompactString`], in bytes.
496    ///
497    /// # Note
498    /// * A `CompactString` will always have a capacity of at least `std::mem::size_of::<String>()`
499    ///
500    /// # Examples
501    /// ### Minimum Size
502    /// ```
503    /// # use compact_str::CompactString;
504    /// let min_size = std::mem::size_of::<String>();
505    /// let compact = CompactString::new("");
506    ///
507    /// assert!(compact.capacity() >= min_size);
508    /// ```
509    ///
510    /// ### Heap Allocated
511    /// ```
512    /// # use compact_str::CompactString;
513    /// let compact = CompactString::with_capacity(128);
514    /// assert_eq!(compact.capacity(), 128);
515    /// ```
516    #[inline]
517    pub fn capacity(&self) -> usize {
518        self.0.capacity()
519    }
520
521    /// Ensures that this [`CompactString`]'s capacity is at least `additional` bytes longer than
522    /// its length. The capacity may be increased by more than `additional` bytes if it chooses,
523    /// to prevent frequent reallocations.
524    ///
525    /// # Note
526    /// * A `CompactString` will always have at least a capacity of `std::mem::size_of::<String>()`
527    /// * Reserving additional bytes may cause the `CompactString` to become heap allocated
528    ///
529    /// # Panics
530    /// This method panics if the new capacity overflows `usize` or if the system is out-of-memory.
531    /// Use [`CompactString::try_reserve()`] if you want to handle such a problem manually.
532    ///
533    /// # Examples
534    /// ```
535    /// # use compact_str::CompactString;
536    ///
537    /// const WORD: usize = std::mem::size_of::<usize>();
538    /// let mut compact = CompactString::default();
539    /// assert!(compact.capacity() >= (WORD * 3) - 1);
540    ///
541    /// compact.reserve(200);
542    /// assert!(compact.is_heap_allocated());
543    /// assert!(compact.capacity() >= 200);
544    /// ```
545    #[inline]
546    #[track_caller]
547    pub fn reserve(&mut self, additional: usize) {
548        self.try_reserve(additional).unwrap_with_msg()
549    }
550
551    /// Fallible version of [`CompactString::reserve()`]
552    ///
553    /// This method won't panic if the system is out-of-memory, but return an [`ReserveError`]
554    /// Otherwise it behaves the same as [`CompactString::reserve()`].
555    #[inline]
556    pub fn try_reserve(&mut self, additional: usize) -> Result<(), ReserveError> {
557        self.0.reserve(additional)
558    }
559
560    /// Returns a string slice containing the entire [`CompactString`].
561    ///
562    /// # Examples
563    /// ```
564    /// # use compact_str::CompactString;
565    /// let s = CompactString::new("hello");
566    ///
567    /// assert_eq!(s.as_str(), "hello");
568    /// ```
569    #[inline]
570    pub fn as_str(&self) -> &str {
571        self.0.as_str()
572    }
573
574    /// Returns a mutable string slice containing the entire [`CompactString`].
575    ///
576    /// # Examples
577    /// ```
578    /// # use compact_str::CompactString;
579    /// let mut s = CompactString::new("hello");
580    /// s.as_mut_str().make_ascii_uppercase();
581    ///
582    /// assert_eq!(s.as_str(), "HELLO");
583    /// ```
584    #[inline]
585    pub fn as_mut_str(&mut self) -> &mut str {
586        let len = self.len();
587        let ptr = self.0.as_mut_ptr();
588        // SAFETY: The first `len` bytes of a `CompactString` are initialized and valid UTF-8.
589        let bytes = unsafe { slice::from_raw_parts_mut(ptr, len) };
590        // SAFETY: The bytes came from a valid `CompactString`.
591        unsafe { core::str::from_utf8_unchecked_mut(bytes) }
592    }
593
594    /// Returns the remaining spare capacity of this [`CompactString`] as a slice of
595    /// [`MaybeUninit`](mem::MaybeUninit) bytes.
596    ///
597    /// The returned slice covers the range `len()..capacity()`. After initializing a prefix of the
598    /// slice, use [`CompactString::set_len`] to include those bytes in the string.
599    ///
600    /// # Safety
601    ///
602    /// * Before increasing the length, the caller must initialize every newly included byte and
603    ///   ensure the resulting string is valid UTF-8.
604    /// * For an inline string, the final byte of the spare capacity also stores the representation
605    ///   tag. It may only be overwritten as the final byte of a completely initialized, valid
606    ///   UTF-8 string that fills the inline capacity.
607    ///
608    /// # Examples
609    ///
610    /// ```
611    /// # use compact_str::CompactString;
612    /// let mut s = CompactString::new("hello");
613    /// let suffix = b" world";
614    ///
615    /// let spare = unsafe { s.spare_capacity_mut() };
616    /// for (slot, byte) in spare.iter_mut().zip(suffix) {
617    ///     slot.write(*byte);
618    /// }
619    /// // SAFETY: We initialized the appended bytes, and the result is valid UTF-8.
620    /// unsafe { s.set_len(s.len() + suffix.len()) };
621    ///
622    /// assert_eq!(s, "hello world");
623    /// ```
624    #[inline]
625    pub unsafe fn spare_capacity_mut(&mut self) -> &mut [mem::MaybeUninit<u8>] {
626        let len = self.len();
627        let ptr = self.0.as_mut_ptr();
628        let cap = self.capacity();
629
630        // SAFETY: The buffer is valid for `cap` bytes, and `len <= cap`. `MaybeUninit<u8>` does
631        // not require the spare bytes to be initialized.
632        unsafe { slice::from_raw_parts_mut(ptr.add(len) as *mut mem::MaybeUninit<u8>, cap - len) }
633    }
634
635    /// Returns a byte slice of the [`CompactString`]'s contents.
636    ///
637    /// # Examples
638    /// ```
639    /// # use compact_str::CompactString;
640    /// let s = CompactString::new("hello");
641    ///
642    /// assert_eq!(&[104, 101, 108, 108, 111], s.as_bytes());
643    /// ```
644    #[inline]
645    pub fn as_bytes(&self) -> &[u8] {
646        self.0.as_slice()
647    }
648
649    // TODO: Implement a `try_as_mut_slice(...)` that will fail if it results in cloning?
650    //
651    /// Provides a mutable reference to the initialized bytes in this [`CompactString`].
652    ///
653    /// The returned slice has length [`CompactString::len()`]. To write into the remaining
654    /// capacity, use [`CompactString::spare_capacity_mut`].
655    ///
656    /// # Safety
657    /// * All Rust strings, including `CompactString`, must be valid UTF-8. The caller must
658    ///   guarantee that any modifications made to the underlying buffer are valid UTF-8.
659    ///
660    /// # Examples
661    /// ```
662    /// # use compact_str::CompactString;
663    /// let mut s = CompactString::new("hello");
664    ///
665    /// let bytes = unsafe { s.as_mut_bytes() };
666    /// bytes[0] = b'H';
667    ///
668    /// assert_eq!(s, "Hello");
669    /// ```
670    #[inline]
671    pub unsafe fn as_mut_bytes(&mut self) -> &mut [u8] {
672        let len = self.len();
673        let ptr = self.0.as_mut_ptr();
674
675        // SAFETY: The first `len` bytes of a `CompactString` are initialized.
676        unsafe { slice::from_raw_parts_mut(ptr, len) }
677    }
678
679    /// Appends the given [`char`] to the end of this [`CompactString`].
680    ///
681    /// # Examples
682    /// ```
683    /// # use compact_str::CompactString;
684    /// let mut s = CompactString::new("foo");
685    ///
686    /// s.push('b');
687    /// s.push('a');
688    /// s.push('r');
689    ///
690    /// assert_eq!("foobar", s);
691    /// ```
692    pub fn push(&mut self, ch: char) {
693        self.push_str(ch.encode_utf8(&mut [0; 4]));
694    }
695
696    /// Removes the last character from the [`CompactString`] and returns it.
697    /// Returns `None` if this [`CompactString`] is empty.
698    ///
699    /// # Examples
700    /// ```
701    /// # use compact_str::CompactString;
702    /// let mut s = CompactString::new("abc");
703    ///
704    /// assert_eq!(s.pop(), Some('c'));
705    /// assert_eq!(s.pop(), Some('b'));
706    /// assert_eq!(s.pop(), Some('a'));
707    ///
708    /// assert_eq!(s.pop(), None);
709    /// ```
710    #[inline]
711    pub fn pop(&mut self) -> Option<char> {
712        self.0.pop()
713    }
714
715    /// Appends a given string slice onto the end of this [`CompactString`]
716    ///
717    /// # Examples
718    /// ```
719    /// # use compact_str::CompactString;
720    /// let mut s = CompactString::new("abc");
721    ///
722    /// s.push_str("123");
723    ///
724    /// assert_eq!("abc123", s);
725    /// ```
726    #[inline]
727    pub fn push_str(&mut self, s: &str) {
728        self.0.push_str(s)
729    }
730
731    /// Removes a [`char`] from this [`CompactString`] at a byte position and returns it.
732    ///
733    /// This is an *O*(*n*) operation, as it requires copying every element in the
734    /// buffer.
735    ///
736    /// # Panics
737    ///
738    /// Panics if `idx` is larger than or equal to the [`CompactString`]'s length,
739    /// or if it does not lie on a [`char`] boundary.
740    ///
741    /// # Examples
742    ///
743    /// ### Basic usage:
744    ///
745    /// ```
746    /// # use compact_str::CompactString;
747    /// let mut c = CompactString::from("hello world");
748    ///
749    /// assert_eq!(c.remove(0), 'h');
750    /// assert_eq!(c, "ello world");
751    ///
752    /// assert_eq!(c.remove(5), 'w');
753    /// assert_eq!(c, "ello orld");
754    /// ```
755    ///
756    /// ### Past total length:
757    ///
758    /// ```should_panic
759    /// # use compact_str::CompactString;
760    /// let mut c = CompactString::from("hello there!");
761    /// c.remove(100);
762    /// ```
763    ///
764    /// ### Not on char boundary:
765    ///
766    /// ```should_panic
767    /// # use compact_str::CompactString;
768    /// let mut c = CompactString::from("🦄");
769    /// c.remove(1);
770    /// ```
771    #[inline]
772    pub fn remove(&mut self, idx: usize) -> char {
773        let len = self.len();
774        let substr = &mut self.as_mut_str()[idx..];
775
776        // get the char we want to remove
777        let ch = substr
778            .chars()
779            .next()
780            .expect("cannot remove a char from the end of a string");
781        let ch_len = ch.len_utf8();
782
783        // shift everything back one character
784        let num_bytes = substr.len() - ch_len;
785        let ptr = substr.as_mut_ptr();
786
787        // SAFETY: Both src and dest are valid for reads of `num_bytes` amount of bytes,
788        // and are properly aligned
789        unsafe {
790            core::ptr::copy(ptr.add(ch_len) as *const u8, ptr, num_bytes);
791            self.set_len(len - ch_len);
792        }
793
794        ch
795    }
796
797    /// Forces the length of the [`CompactString`] to `new_len`.
798    ///
799    /// This is a low-level operation that maintains none of the normal invariants for
800    /// `CompactString`. If you want to modify the `CompactString` you should use methods like
801    /// `push`, `push_str` or `pop`.
802    ///
803    /// # Safety
804    /// * `new_len` must be less than or equal to `capacity()`
805    /// * The elements at `old_len..new_len` must be initialized
806    #[inline]
807    pub unsafe fn set_len(&mut self, new_len: usize) {
808        self.0.set_len(new_len)
809    }
810
811    /// Returns whether or not the [`CompactString`] is heap allocated.
812    ///
813    /// # Examples
814    /// ### Inlined
815    /// ```
816    /// # use compact_str::CompactString;
817    /// let hello = CompactString::new("hello world");
818    ///
819    /// assert!(!hello.is_heap_allocated());
820    /// ```
821    ///
822    /// ### Heap Allocated
823    /// ```
824    /// # use compact_str::CompactString;
825    /// let msg = CompactString::new("this message will self destruct in 5, 4, 3, 2, 1 💥");
826    ///
827    /// assert!(msg.is_heap_allocated());
828    /// ```
829    #[inline]
830    pub fn is_heap_allocated(&self) -> bool {
831        self.0.is_heap_allocated()
832    }
833
834    /// Ensure that the given range is inside the set data, and that no codepoints are split.
835    ///
836    /// Returns the range `start..end` as a tuple.
837    #[inline]
838    fn ensure_range(&self, range: impl RangeBounds<usize>) -> (usize, usize) {
839        #[cold]
840        #[inline(never)]
841        fn illegal_range() -> ! {
842            panic!("illegal range");
843        }
844
845        let start = match range.start_bound() {
846            Bound::Included(&n) => n,
847            Bound::Excluded(&n) => match n.checked_add(1) {
848                Some(n) => n,
849                None => illegal_range(),
850            },
851            Bound::Unbounded => 0,
852        };
853        let end = match range.end_bound() {
854            Bound::Included(&n) => match n.checked_add(1) {
855                Some(n) => n,
856                None => illegal_range(),
857            },
858            Bound::Excluded(&n) => n,
859            Bound::Unbounded => self.len(),
860        };
861        if end < start {
862            illegal_range();
863        }
864
865        let s = self.as_str();
866        if !s.is_char_boundary(start) || !s.is_char_boundary(end) {
867            illegal_range();
868        }
869
870        (start, end)
871    }
872
873    /// Removes the specified range in the [`CompactString`],
874    /// and replaces it with the given string.
875    /// The given string doesn't need to be the same length as the range.
876    ///
877    /// # Panics
878    ///
879    /// Panics if the starting point or end point do not lie on a [`char`]
880    /// boundary, or if they're out of bounds.
881    ///
882    /// # Examples
883    ///
884    /// Basic usage:
885    ///
886    /// ```
887    /// # use compact_str::CompactString;
888    /// let mut s = CompactString::new("Hello, world!");
889    ///
890    /// s.replace_range(7..12, "WORLD");
891    /// assert_eq!(s, "Hello, WORLD!");
892    ///
893    /// s.replace_range(7..=11, "you");
894    /// assert_eq!(s, "Hello, you!");
895    ///
896    /// s.replace_range(5.., "! Is it me you're looking for?");
897    /// assert_eq!(s, "Hello! Is it me you're looking for?");
898    /// ```
899    #[inline]
900    pub fn replace_range(&mut self, range: impl RangeBounds<usize>, replace_with: &str) {
901        let (start, end) = self.ensure_range(range);
902        let dest_len = end - start;
903        match dest_len.cmp(&replace_with.len()) {
904            Ordering::Equal => unsafe { self.replace_range_same_size(start, end, replace_with) },
905            Ordering::Greater => unsafe { self.replace_range_shrink(start, end, replace_with) },
906            Ordering::Less => unsafe { self.replace_range_grow(start, end, replace_with) },
907        }
908    }
909
910    /// Replace into the same size.
911    unsafe fn replace_range_same_size(&mut self, start: usize, end: usize, replace_with: &str) {
912        core::ptr::copy_nonoverlapping(
913            replace_with.as_ptr(),
914            self.as_mut_ptr().add(start),
915            end - start,
916        );
917    }
918
919    /// Replace, so self.len() gets smaller.
920    unsafe fn replace_range_shrink(&mut self, start: usize, end: usize, replace_with: &str) {
921        let total_len = self.len();
922        let dest_len = end - start;
923        let new_len = total_len - (dest_len - replace_with.len());
924        let amount = total_len - end;
925        let data = self.as_mut_ptr();
926        // first insert the replacement string, overwriting the current content
927        core::ptr::copy_nonoverlapping(replace_with.as_ptr(), data.add(start), replace_with.len());
928        // then move the tail of the CompactString forward to its new place, filling the gap
929        core::ptr::copy(
930            data.add(total_len - amount),
931            data.add(new_len - amount),
932            amount,
933        );
934        // and lastly we set the new length
935        self.set_len(new_len);
936    }
937
938    /// Replace, so self.len() gets bigger.
939    unsafe fn replace_range_grow(&mut self, start: usize, end: usize, replace_with: &str) {
940        let dest_len = end - start;
941        self.reserve(replace_with.len() - dest_len);
942        let total_len = self.len();
943        let new_len = total_len + (replace_with.len() - dest_len);
944        let amount = total_len - end;
945        // first grow the string, so MIRI knows that the full range is usable
946        self.set_len(new_len);
947        let data = self.as_mut_ptr();
948        // then move the tail of the CompactString back to its new place
949        core::ptr::copy(
950            data.add(total_len - amount),
951            data.add(new_len - amount),
952            amount,
953        );
954        // and lastly insert the replacement string
955        core::ptr::copy_nonoverlapping(replace_with.as_ptr(), data.add(start), replace_with.len());
956    }
957
958    /// Creates a new [`CompactString`] by repeating a string `n` times.
959    ///
960    /// # Panics
961    ///
962    /// This function will panic if the capacity would overflow.
963    ///
964    /// # Examples
965    ///
966    /// Basic usage:
967    ///
968    /// ```
969    /// use compact_str::CompactString;
970    /// assert_eq!(CompactString::new("abc").repeat(4), CompactString::new("abcabcabcabc"));
971    /// ```
972    ///
973    /// A panic upon overflow:
974    ///
975    /// ```should_panic
976    /// use compact_str::CompactString;
977    ///
978    /// // this will panic at runtime
979    /// let huge = CompactString::new("0123456789abcdef").repeat(usize::MAX);
980    /// ```
981    #[must_use]
982    pub fn repeat(&self, n: usize) -> Self {
983        if n == 0 || self.is_empty() {
984            Self::const_new("")
985        } else if n == 1 {
986            self.clone()
987        } else {
988            let cap = self.len().checked_mul(n).expect("capacity overflow");
989            let mut out = Self::with_capacity(cap);
990            (0..n).for_each(|_| out.push_str(self));
991            out
992        }
993    }
994
995    /// Truncate the [`CompactString`] to a shorter length.
996    ///
997    /// If the length of the [`CompactString`] is less or equal to `new_len`, the call is a no-op.
998    ///
999    /// Calling this function does not change the capacity of the [`CompactString`], unless the
1000    /// [`CompactString`] is backed by a `&'static str`.
1001    ///
1002    /// # Panics
1003    ///
1004    /// Panics if the new end of the string does not lie on a [`char`] boundary.
1005    ///
1006    /// # Examples
1007    ///
1008    /// Basic usage:
1009    ///
1010    /// ```
1011    /// # use compact_str::CompactString;
1012    /// let mut s = CompactString::new("Hello, world!");
1013    /// s.truncate(5);
1014    /// assert_eq!(s, "Hello");
1015    /// ```
1016    pub fn truncate(&mut self, new_len: usize) {
1017        let s = self.as_str();
1018        if new_len >= s.len() {
1019            return;
1020        }
1021
1022        assert!(
1023            s.is_char_boundary(new_len),
1024            "new_len must lie on char boundary",
1025        );
1026        unsafe { self.set_len(new_len) };
1027    }
1028
1029    /// Converts a [`CompactString`] to a raw pointer.
1030    #[inline]
1031    pub fn as_ptr(&self) -> *const u8 {
1032        self.0.as_slice().as_ptr()
1033    }
1034
1035    /// Converts a mutable [`CompactString`] to a raw pointer.
1036    #[inline]
1037    pub fn as_mut_ptr(&mut self) -> *mut u8 {
1038        self.0.as_mut_ptr()
1039    }
1040
1041    /// Insert string character at an index.
1042    ///
1043    /// # Examples
1044    ///
1045    /// Basic usage:
1046    ///
1047    /// ```
1048    /// # use compact_str::CompactString;
1049    /// let mut s = CompactString::new("Hello!");
1050    /// s.insert_str(5, ", world");
1051    /// assert_eq!(s, "Hello, world!");
1052    /// ```
1053    pub fn insert_str(&mut self, idx: usize, string: &str) {
1054        assert!(self.is_char_boundary(idx), "idx must lie on char boundary");
1055
1056        let new_len = self.len() + string.len();
1057        self.reserve(string.len());
1058
1059        // SAFETY: We just checked that we may split self at idx.
1060        //         We set the length only after reserving the memory.
1061        //         We fill the gap with valid UTF-8 data.
1062        unsafe {
1063            // first move the tail to the new back
1064            let data = self.as_mut_ptr();
1065            core::ptr::copy(
1066                data.add(idx),
1067                data.add(idx + string.len()),
1068                new_len - idx - string.len(),
1069            );
1070
1071            // then insert the new bytes
1072            core::ptr::copy_nonoverlapping(string.as_ptr(), data.add(idx), string.len());
1073
1074            // and lastly resize the string
1075            self.set_len(new_len);
1076        }
1077    }
1078
1079    /// Insert a character at an index.
1080    ///
1081    /// # Examples
1082    ///
1083    /// Basic usage:
1084    ///
1085    /// ```
1086    /// # use compact_str::CompactString;
1087    /// let mut s = CompactString::new("Hello world!");
1088    /// s.insert(5, ',');
1089    /// assert_eq!(s, "Hello, world!");
1090    /// ```
1091    pub fn insert(&mut self, idx: usize, ch: char) {
1092        self.insert_str(idx, ch.encode_utf8(&mut [0; 4]));
1093    }
1094
1095    /// Reduces the length of the [`CompactString`] to zero.
1096    ///
1097    /// Calling this function does not change the capacity of the [`CompactString`], unless the
1098    /// [`CompactString`] is backed by a `&'static str`.
1099    ///
1100    /// ```
1101    /// # use compact_str::CompactString;
1102    /// let mut s = CompactString::new("Rust is the most loved language on Stackoverflow!");
1103    /// assert_eq!(s.capacity(), 49);
1104    ///
1105    /// s.clear();
1106    ///
1107    /// assert_eq!(s, "");
1108    /// assert_eq!(s.capacity(), 49);
1109    /// ```
1110    pub fn clear(&mut self) {
1111        unsafe { self.set_len(0) };
1112    }
1113
1114    /// Split the [`CompactString`] into at the given byte index.
1115    ///
1116    /// Calling this function does not change the capacity of the [`CompactString`], unless the
1117    /// [`CompactString`] is backed by a `&'static str`.
1118    ///
1119    /// # Panics
1120    ///
1121    /// Panics if `at` does not lie on a [`char`] boundary.
1122    ///
1123    /// Basic usage:
1124    ///
1125    /// ```
1126    /// # use compact_str::CompactString;
1127    /// let mut s = CompactString::const_new("Hello, world!");
1128    /// let w = s.split_off(5);
1129    ///
1130    /// assert_eq!(w, ", world!");
1131    /// assert_eq!(s, "Hello");
1132    /// ```
1133    pub fn split_off(&mut self, at: usize) -> Self {
1134        if let Some(s) = self.as_static_str() {
1135            let result = Self::const_new(&s[at..]);
1136            // SAFETY: the previous line `self[at...]` would have panicked if `at` was invalid
1137            unsafe { self.set_len(at) };
1138            result
1139        } else {
1140            let result = self[at..].into();
1141            // SAFETY: the previous line `self[at...]` would have panicked if `at` was invalid
1142            unsafe { self.set_len(at) };
1143            result
1144        }
1145    }
1146
1147    /// Remove a range from the [`CompactString`], and return it as an iterator.
1148    ///
1149    /// Calling this function does not change the capacity of the [`CompactString`].
1150    ///
1151    /// # Panics
1152    ///
1153    /// Panics if the start or end of the range does not lie on a [`char`] boundary.
1154    ///
1155    /// # Examples
1156    ///
1157    /// Basic usage:
1158    ///
1159    /// ```
1160    /// # use compact_str::CompactString;
1161    /// let mut s = CompactString::new("Hello, world!");
1162    ///
1163    /// let mut d = s.drain(5..12);
1164    /// assert_eq!(d.next(), Some(','));   // iterate over the extracted data
1165    /// assert_eq!(d.as_str(), " world"); // or get the whole data as &str
1166    ///
1167    /// // The iterator keeps a reference to `s`, so you have to drop() the iterator,
1168    /// // before you can access `s` again.
1169    /// drop(d);
1170    /// assert_eq!(s, "Hello!");
1171    /// ```
1172    pub fn drain(&mut self, range: impl RangeBounds<usize>) -> Drain<'_> {
1173        let (start, end) = self.ensure_range(range);
1174        Drain {
1175            compact_string: self as *mut Self,
1176            start,
1177            end,
1178            chars: self[start..end].chars(),
1179        }
1180    }
1181
1182    /// Shrinks the capacity of this [`CompactString`] with a lower bound.
1183    ///
1184    /// The resulting capactity is never less than the size of 3×[`usize`],
1185    /// i.e. the capacity than can be inlined.
1186    ///
1187    /// # Examples
1188    ///
1189    /// Basic usage:
1190    ///
1191    /// ```
1192    /// # use compact_str::CompactString;
1193    /// let mut s = CompactString::with_capacity(100);
1194    /// assert_eq!(s.capacity(), 100);
1195    ///
1196    /// // if the capacity was already bigger than the argument, the call is a no-op
1197    /// s.shrink_to(100);
1198    /// assert_eq!(s.capacity(), 100);
1199    ///
1200    /// s.shrink_to(50);
1201    /// assert_eq!(s.capacity(), 50);
1202    ///
1203    /// // if the string can be inlined, it is
1204    /// s.shrink_to(10);
1205    /// assert_eq!(s.capacity(), 3 * std::mem::size_of::<usize>());
1206    /// ```
1207    #[inline]
1208    pub fn shrink_to(&mut self, min_capacity: usize) {
1209        self.0.shrink_to(min_capacity);
1210    }
1211
1212    /// Shrinks the capacity of this [`CompactString`] to match its length.
1213    ///
1214    /// The resulting capactity is never less than the size of 3×[`usize`],
1215    /// i.e. the capacity than can be inlined.
1216    ///
1217    /// This method is effectively the same as calling `string.shrink_to(0)`.
1218    ///
1219    /// # Examples
1220    ///
1221    /// Basic usage:
1222    ///
1223    /// ```
1224    /// # use compact_str::CompactString;
1225    /// let mut s = CompactString::from("This is a string with more than 24 characters.");
1226    ///
1227    /// s.reserve(100);
1228    /// assert!(s.capacity() >= 100);
1229    ///
1230    ///  s.shrink_to_fit();
1231    /// assert_eq!(s.len(), s.capacity());
1232    /// ```
1233    ///
1234    /// ```
1235    /// # use compact_str::CompactString;
1236    /// let mut s = CompactString::from("short string");
1237    ///
1238    /// s.reserve(100);
1239    /// assert!(s.capacity() >= 100);
1240    ///
1241    /// s.shrink_to_fit();
1242    /// assert_eq!(s.capacity(), 3 * std::mem::size_of::<usize>());
1243    /// ```
1244    #[inline]
1245    pub fn shrink_to_fit(&mut self) {
1246        self.0.shrink_to(0);
1247    }
1248
1249    /// Retains only the characters specified by the predicate.
1250    ///
1251    /// The method iterates over the characters in the string and calls the `predicate`.
1252    ///
1253    /// If the `predicate` returns `false`, then the character gets removed.
1254    /// If the `predicate` returns `true`, then the character is kept.
1255    ///
1256    /// # Examples
1257    ///
1258    /// ```
1259    /// # use compact_str::CompactString;
1260    /// let mut s = CompactString::from("äb𝄞d€");
1261    ///
1262    /// let keep = [false, true, true, false, true];
1263    /// let mut iter = keep.iter();
1264    /// s.retain(|_| *iter.next().unwrap());
1265    ///
1266    /// assert_eq!(s, "b𝄞€");
1267    /// ```
1268    pub fn retain(&mut self, mut predicate: impl FnMut(char) -> bool) {
1269        // We iterate over the string, and copy character by character.
1270
1271        struct SetLenOnDrop<'a> {
1272            self_: &'a mut CompactString,
1273            src_idx: usize,
1274            dst_idx: usize,
1275        }
1276
1277        let mut g = SetLenOnDrop {
1278            self_: self,
1279            src_idx: 0,
1280            dst_idx: 0,
1281        };
1282        let original_len = g.self_.len();
1283        let ptr = g.self_.0.as_mut_ptr();
1284        while g.src_idx < original_len {
1285            // SAFETY: Everything at and after `src_idx` is an untouched suffix of the
1286            // original string. In particular, it is initialized, valid UTF-8, and non-empty.
1287            let ch = unsafe {
1288                let suffix =
1289                    core::slice::from_raw_parts(ptr.add(g.src_idx), original_len - g.src_idx);
1290                core::str::from_utf8_unchecked(suffix)
1291                    .chars()
1292                    .next()
1293                    .expect("source suffix is non-empty")
1294            };
1295            let ch_len = ch.len_utf8();
1296            if predicate(ch) {
1297                // SAFETY: Both ranges are in the allocation and `copy` permits overlap. The
1298                // destination ends no later than the end of the current source character, so
1299                // the unprocessed suffix remains unchanged.
1300                unsafe {
1301                    core::ptr::copy(ptr.add(g.src_idx), ptr.add(g.dst_idx), ch_len);
1302                }
1303                g.dst_idx += ch_len;
1304            }
1305            g.src_idx += ch_len;
1306        }
1307
1308        impl Drop for SetLenOnDrop<'_> {
1309            fn drop(&mut self) {
1310                // SAFETY: We know that the index is a valid position to break the string.
1311                unsafe { self.self_.set_len(self.dst_idx) };
1312            }
1313        }
1314        drop(g);
1315    }
1316
1317    /// Decode a bytes slice as UTF-8 string, replacing any illegal codepoints
1318    ///
1319    /// # Examples
1320    ///
1321    /// ```
1322    /// # use compact_str::CompactString;
1323    /// let chess_knight = b"\xf0\x9f\xa8\x84";
1324    ///
1325    /// assert_eq!(
1326    ///     "🨄",
1327    ///     CompactString::from_utf8_lossy(chess_knight),
1328    /// );
1329    ///
1330    /// // For valid UTF-8 slices, this is the same as:
1331    /// assert_eq!(
1332    ///     "🨄",
1333    ///     CompactString::new(std::str::from_utf8(chess_knight).unwrap()),
1334    /// );
1335    /// ```
1336    ///
1337    /// Incorrect bytes:
1338    ///
1339    /// ```
1340    /// # use compact_str::CompactString;
1341    /// let broken = b"\xf0\x9f\xc8\x84";
1342    ///
1343    /// assert_eq!(
1344    ///     "�Ȅ",
1345    ///     CompactString::from_utf8_lossy(broken),
1346    /// );
1347    ///
1348    /// // For invalid UTF-8 slices, this is an optimized implemented for:
1349    /// assert_eq!(
1350    ///     "�Ȅ",
1351    ///     CompactString::from(String::from_utf8_lossy(broken)),
1352    /// );
1353    /// ```
1354    pub fn from_utf8_lossy(v: &[u8]) -> Self {
1355        // Fast path: the entire input is valid UTF-8, so copy it in a single shot. This is the
1356        // common case, and mirrors `String::from_utf8_lossy`, which borrows the input here.
1357        let mut error = match core::str::from_utf8(v) {
1358            Ok(valid) => return Self::new(valid),
1359            Err(error) => error,
1360        };
1361
1362        // Slow path: bulk-copy each run of valid UTF-8, emitting a single replacement character for
1363        // every maximal invalid subsequence. This produces the same result as
1364        // `String::from_utf8_lossy`, but writes straight into the `CompactString` rather than
1365        // building an intermediate `String`.
1366        const REPLACEMENT: &str = "\u{FFFD}";
1367        // `v.len()` is a heuristic, not an upper bound: a 1-byte invalid subsequence expands to the
1368        // 3-byte replacement character, so pathological all-invalid input may reallocate. This
1369        // matches what `String::from_utf8_lossy` does (`String::with_capacity(v.len())`).
1370        let mut result = Self::with_capacity(v.len());
1371        let mut remaining = v;
1372        loop {
1373            let valid_up_to = error.valid_up_to();
1374            // SAFETY: `remaining[..valid_up_to]` is valid UTF-8, by definition of `valid_up_to`.
1375            let valid = unsafe { core::str::from_utf8_unchecked(&remaining[..valid_up_to]) };
1376            result.push_str(valid);
1377            result.push_str(REPLACEMENT);
1378
1379            let invalid_len = match error.error_len() {
1380                Some(len) => len,
1381                // `None` means the input ended with an incomplete (but not yet invalid) sequence,
1382                // which we've now replaced, so we're done.
1383                None => return result,
1384            };
1385            remaining = &remaining[valid_up_to + invalid_len..];
1386
1387            // Re-validate the rest. If it's all valid we're done; otherwise loop on the next error.
1388            match core::str::from_utf8(remaining) {
1389                Ok(valid) => {
1390                    result.push_str(valid);
1391                    return result;
1392                }
1393                Err(next) => error = next,
1394            }
1395        }
1396    }
1397
1398    fn from_utf16x(
1399        v: &[u8],
1400        from_int: impl Fn(u16) -> u16,
1401        from_bytes: impl Fn([u8; 2]) -> u16,
1402    ) -> Result<Self, Utf16Error> {
1403        #[allow(clippy::manual_is_multiple_of)]
1404        if v.len() % 2 != 0 {
1405            // Input had an odd number of bytes.
1406            return Err(Utf16Error(()));
1407        }
1408
1409        // Note: we don't use collect::<Result<_, _>>() because that fails to pre-allocate a buffer,
1410        // even though the size of our iterator, `v`, is known ahead of time.
1411        //
1412        // rustlang issue #48994 is tracking the fix
1413        let mut result = CompactString::with_capacity(v.len() / 2);
1414
1415        // SAFETY: `u8` and `u16` are `Copy`, so if the alignment fits, we can transmute a
1416        //         `[u8; 2*N]` to `[u16; N]`. `slice::align_to()` checks if the alignment is right.
1417        match unsafe { v.align_to::<u16>() } {
1418            (&[], v, &[]) => {
1419                // Input is correctly aligned.
1420                for c in core::char::decode_utf16(v.iter().copied().map(from_int)) {
1421                    result.push(c.map_err(|_| Utf16Error(()))?);
1422                }
1423            }
1424            _ => {
1425                // Input's alignment is off.
1426                // SAFETY: we can always reinterpret a `[u8; 2*N]` slice as `[[u8; 2]; N]`
1427                let v = unsafe { slice::from_raw_parts(v.as_ptr().cast(), v.len() / 2) };
1428                for c in core::char::decode_utf16(v.iter().copied().map(from_bytes)) {
1429                    result.push(c.map_err(|_| Utf16Error(()))?);
1430                }
1431            }
1432        }
1433
1434        Ok(result)
1435    }
1436
1437    fn from_utf16x_lossy(
1438        v: &[u8],
1439        from_int: impl Fn(u16) -> u16,
1440        from_bytes: impl Fn([u8; 2]) -> u16,
1441    ) -> Self {
1442        // Notice: We write the string "�" instead of the character '�', so the character does not
1443        //         have to be formatted before it can be appended.
1444
1445        #[allow(clippy::manual_is_multiple_of)]
1446        let (trailing_extra_byte, v) = match v.len() % 2 != 0 {
1447            true => (true, &v[..v.len() - 1]),
1448            false => (false, v),
1449        };
1450        let mut result = CompactString::with_capacity(v.len() / 2);
1451
1452        // SAFETY: `u8` and `u16` are `Copy`, so if the alignment fits, we can transmute a
1453        //         `[u8; 2*N]` to `[u16; N]`. `slice::align_to()` checks if the alignment is right.
1454        match unsafe { v.align_to::<u16>() } {
1455            (&[], v, &[]) => {
1456                // Input is correctly aligned.
1457                for c in core::char::decode_utf16(v.iter().copied().map(from_int)) {
1458                    match c {
1459                        Ok(c) => result.push(c),
1460                        Err(_) => result.push_str("�"),
1461                    }
1462                }
1463            }
1464            _ => {
1465                // Input's alignment is off.
1466                // SAFETY: we can always reinterpret a `[u8; 2*N]` slice as `[[u8; 2]; N]`
1467                let v = unsafe { slice::from_raw_parts(v.as_ptr().cast(), v.len() / 2) };
1468                for c in core::char::decode_utf16(v.iter().copied().map(from_bytes)) {
1469                    match c {
1470                        Ok(c) => result.push(c),
1471                        Err(_) => result.push_str("�"),
1472                    }
1473                }
1474            }
1475        }
1476
1477        if trailing_extra_byte {
1478            result.push_str("�");
1479        }
1480        result
1481    }
1482
1483    /// Decode a slice of bytes as UTF-16 encoded string, in little endian.
1484    ///
1485    /// # Errors
1486    ///
1487    /// If the slice has an odd number of bytes, or if it did not contain valid UTF-16 characters,
1488    /// a [`Utf16Error`] is returned.
1489    ///
1490    /// # Examples
1491    ///
1492    /// ```
1493    /// # use compact_str::CompactString;
1494    /// const DANCING_MEN: &[u8] = b"\x3d\xd8\x6f\xdc\x0d\x20\x42\x26\x0f\xfe";
1495    /// let dancing_men = CompactString::from_utf16le(DANCING_MEN).unwrap();
1496    /// assert_eq!(dancing_men, "👯‍♂️");
1497    /// ```
1498    #[inline]
1499    pub fn from_utf16le(v: impl AsRef<[u8]>) -> Result<Self, Utf16Error> {
1500        CompactString::from_utf16x(v.as_ref(), u16::from_le, u16::from_le_bytes)
1501    }
1502
1503    /// Decode a slice of bytes as UTF-16 encoded string, in big endian.
1504    ///
1505    /// # Errors
1506    ///
1507    /// If the slice has an odd number of bytes, or if it did not contain valid UTF-16 characters,
1508    /// a [`Utf16Error`] is returned.
1509    ///
1510    /// # Examples
1511    ///
1512    /// ```
1513    /// # use compact_str::CompactString;
1514    /// const DANCING_WOMEN: &[u8] = b"\xd8\x3d\xdc\x6f\x20\x0d\x26\x40\xfe\x0f";
1515    /// let dancing_women = CompactString::from_utf16be(DANCING_WOMEN).unwrap();
1516    /// assert_eq!(dancing_women, "👯‍♀️");
1517    /// ```
1518    #[inline]
1519    pub fn from_utf16be(v: impl AsRef<[u8]>) -> Result<Self, Utf16Error> {
1520        CompactString::from_utf16x(v.as_ref(), u16::from_be, u16::from_be_bytes)
1521    }
1522
1523    /// Lossy decode a slice of bytes as UTF-16 encoded string, in little endian.
1524    ///
1525    /// In this context "lossy" means that any broken characters in the input are replaced by the
1526    /// \<REPLACEMENT CHARACTER\> `'�'`. Please notice that, unlike UTF-8, UTF-16 is not self
1527    /// synchronizing. I.e. if a byte in the input is dropped, all following data is broken.
1528    ///
1529    /// # Examples
1530    ///
1531    /// ```
1532    /// # use compact_str::CompactString;
1533    /// // A "random" bit was flipped in the 4th byte:
1534    /// const DANCING_MEN: &[u8] = b"\x3d\xd8\x6f\xfc\x0d\x20\x42\x26\x0f\xfe";
1535    /// let dancing_men = CompactString::from_utf16le_lossy(DANCING_MEN);
1536    /// assert_eq!(dancing_men, "�\u{fc6f}\u{200d}♂️");
1537    /// ```
1538    #[inline]
1539    pub fn from_utf16le_lossy(v: impl AsRef<[u8]>) -> Self {
1540        CompactString::from_utf16x_lossy(v.as_ref(), u16::from_le, u16::from_le_bytes)
1541    }
1542
1543    /// Lossy decode a slice of bytes as UTF-16 encoded string, in big endian.
1544    ///
1545    /// In this context "lossy" means that any broken characters in the input are replaced by the
1546    /// \<REPLACEMENT CHARACTER\> `'�'`. Please notice that, unlike UTF-8, UTF-16 is not self
1547    /// synchronizing. I.e. if a byte in the input is dropped, all following data is broken.
1548    ///
1549    /// # Examples
1550    ///
1551    /// ```
1552    /// # use compact_str::CompactString;
1553    /// // A "random" bit was flipped in the 9th byte:
1554    /// const DANCING_WOMEN: &[u8] = b"\xd8\x3d\xdc\x6f\x20\x0d\x26\x40\xde\x0f";
1555    /// let dancing_women = CompactString::from_utf16be_lossy(DANCING_WOMEN);
1556    /// assert_eq!(dancing_women, "👯\u{200d}♀�");
1557    /// ```
1558    #[inline]
1559    pub fn from_utf16be_lossy(v: impl AsRef<[u8]>) -> Self {
1560        CompactString::from_utf16x_lossy(v.as_ref(), u16::from_be, u16::from_be_bytes)
1561    }
1562
1563    /// Convert the [`CompactString`] into a [`String`].
1564    ///
1565    /// # Examples
1566    ///
1567    /// ```
1568    /// # use compact_str::CompactString;
1569    /// let s = CompactString::new("Hello world");
1570    /// let s = s.into_string();
1571    /// assert_eq!(s, "Hello world");
1572    /// ```
1573    pub fn into_string(self) -> String {
1574        self.0.into_string()
1575    }
1576
1577    /// Convert a [`String`] into a [`CompactString`] _without inlining_.
1578    ///
1579    /// Note: You probably don't need to use this method, instead you should use `From<String>`
1580    /// which is implemented for [`CompactString`].
1581    ///
1582    /// This method exists incase your code is very sensitive to memory allocations. Normally when
1583    /// converting a [`String`] to a [`CompactString`] we'll inline short strings onto the stack.
1584    /// But this results in [`Drop`]-ing the original [`String`], which causes memory it owned on
1585    /// the heap to be deallocated. Instead when using this method, we always reuse the buffer that
1586    /// was previously owned by the [`String`], so no trips to the allocator are needed.
1587    ///
1588    /// # Examples
1589    ///
1590    /// ### Short Strings
1591    /// ```
1592    /// use compact_str::CompactString;
1593    ///
1594    /// let short = "hello world".to_string();
1595    /// let c_heap = CompactString::from_string_buffer(short);
1596    ///
1597    /// // using CompactString::from_string_buffer, we'll re-use the String's underlying buffer
1598    /// assert!(c_heap.is_heap_allocated());
1599    ///
1600    /// // note: when Clone-ing a short heap allocated string, we'll eagerly inline at that point
1601    /// let c_inline = c_heap.clone();
1602    /// assert!(!c_inline.is_heap_allocated());
1603    ///
1604    /// assert_eq!(c_heap, c_inline);
1605    /// ```
1606    ///
1607    /// ### Longer Strings
1608    /// ```
1609    /// use compact_str::CompactString;
1610    ///
1611    /// let x = "longer string that will be on the heap".to_string();
1612    /// let c1 = CompactString::from(x);
1613    ///
1614    /// let y = "longer string that will be on the heap".to_string();
1615    /// let c2 = CompactString::from_string_buffer(y);
1616    ///
1617    /// // for longer strings, we re-use the underlying String's buffer in both cases
1618    /// assert!(c1.is_heap_allocated());
1619    /// assert!(c2.is_heap_allocated());
1620    /// ```
1621    ///
1622    /// ### Buffer Re-use
1623    /// ```
1624    /// use compact_str::CompactString;
1625    ///
1626    /// let og = "hello world".to_string();
1627    /// let og_addr = og.as_ptr();
1628    ///
1629    /// let mut c = CompactString::from_string_buffer(og);
1630    /// let ex_addr = c.as_ptr();
1631    ///
1632    /// // When converting to/from String and CompactString with from_string_buffer we always re-use
1633    /// // the same underlying allocated memory/buffer
1634    /// assert_eq!(og_addr, ex_addr);
1635    ///
1636    /// let long = "this is a long string that will be on the heap".to_string();
1637    /// let long_addr = long.as_ptr();
1638    ///
1639    /// let mut long_c = CompactString::from(long);
1640    /// let long_ex_addr = long_c.as_ptr();
1641    ///
1642    /// // When converting to/from String and CompactString with From<String>, we'll also re-use the
1643    /// // underlying buffer, if the string is long, otherwise when converting to CompactString we
1644    /// // eagerly inline
1645    /// assert_eq!(long_addr, long_ex_addr);
1646    /// ```
1647    #[inline]
1648    #[track_caller]
1649    pub fn from_string_buffer(s: String) -> Self {
1650        let repr = Repr::from_string(s, false).unwrap_with_msg();
1651        CompactString(repr)
1652    }
1653
1654    /// Returns a copy of this string where each character is mapped to its
1655    /// ASCII lower case equivalent.
1656    ///
1657    /// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z',
1658    /// but non-ASCII letters are unchanged.
1659    ///
1660    /// To lowercase the value in-place, use [`str::make_ascii_lowercase`].
1661    ///
1662    /// To lowercase ASCII characters in addition to non-ASCII characters, use
1663    /// [`CompactString::to_lowercase`].
1664    ///
1665    /// # Examples
1666    ///
1667    /// ```
1668    /// use compact_str::CompactString;
1669    /// let s = CompactString::new("Grüße, Jürgen ❤");
1670    ///
1671    /// assert_eq!("grüße, jürgen ❤", s.to_ascii_lowercase());
1672    /// ```
1673    #[must_use = "to lowercase the value in-place, use `make_ascii_lowercase()`"]
1674    #[inline]
1675    pub fn to_ascii_lowercase(&self) -> Self {
1676        let mut s = self.clone();
1677        s.make_ascii_lowercase();
1678        s
1679    }
1680
1681    /// Returns a copy of this string where each character is mapped to its
1682    /// ASCII upper case equivalent.
1683    ///
1684    /// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z',
1685    /// but non-ASCII letters are unchanged.
1686    ///
1687    /// To uppercase the value in-place, use [`str::make_ascii_uppercase`].
1688    ///
1689    /// To uppercase ASCII characters in addition to non-ASCII characters, use
1690    /// [`CompactString::to_uppercase`].
1691    ///
1692    /// # Examples
1693    ///
1694    /// ```
1695    /// use compact_str::CompactString;
1696    /// let s = CompactString::new("Grüße, Jürgen ❤");
1697    ///
1698    /// assert_eq!("GRüßE, JüRGEN ❤", s.to_ascii_uppercase());
1699    /// ```
1700    #[must_use = "to uppercase the value in-place, use `make_ascii_uppercase()`"]
1701    #[inline]
1702    pub fn to_ascii_uppercase(&self) -> Self {
1703        let mut s = self.clone();
1704        s.make_ascii_uppercase();
1705        s
1706    }
1707
1708    /// Returns the lowercase equivalent of this string slice, as a new [`CompactString`].
1709    ///
1710    /// 'Lowercase' is defined according to the terms of the Unicode Derived Core Property
1711    /// `Lowercase`.
1712    ///
1713    /// Since some characters can expand into multiple characters when changing
1714    /// the case, this function returns a [`CompactString`] instead of modifying the
1715    /// parameter in-place.
1716    ///
1717    /// # Examples
1718    ///
1719    /// Basic usage:
1720    ///
1721    /// ```
1722    /// use compact_str::CompactString;
1723    /// let s = CompactString::new("HELLO");
1724    ///
1725    /// assert_eq!("hello", s.to_lowercase());
1726    /// ```
1727    ///
1728    /// A tricky example, with sigma:
1729    ///
1730    /// ```
1731    /// use compact_str::CompactString;
1732    /// let sigma = CompactString::new("Σ");
1733    ///
1734    /// assert_eq!("σ", sigma.to_lowercase());
1735    ///
1736    /// // but at the end of a word, it's ς, not σ:
1737    /// let odysseus = CompactString::new("ὈΔΥΣΣΕΎΣ");
1738    ///
1739    /// assert_eq!("ὀδυσσεύς", odysseus.to_lowercase());
1740    /// ```
1741    ///
1742    /// Languages without case are not changed:
1743    ///
1744    /// ```
1745    /// use compact_str::CompactString;
1746    /// let new_year = CompactString::new("农历新年");
1747    ///
1748    /// assert_eq!(new_year, new_year.to_lowercase());
1749    /// ```
1750    #[must_use = "this returns the lowercase string as a new CompactString, \
1751                  without modifying the original"]
1752    pub fn to_lowercase(&self) -> Self {
1753        Self::from_str_to_lowercase(self.as_str())
1754    }
1755
1756    /// Returns the lowercase equivalent of this string slice, as a new [`CompactString`].
1757    ///
1758    /// 'Lowercase' is defined according to the terms of the Unicode Derived Core Property
1759    /// `Lowercase`.
1760    ///
1761    /// Since some characters can expand into multiple characters when changing
1762    /// the case, this function returns a [`CompactString`] instead of modifying the
1763    /// parameter in-place.
1764    ///
1765    /// # Examples
1766    ///
1767    /// Basic usage:
1768    ///
1769    /// ```
1770    /// use compact_str::CompactString;
1771    ///
1772    /// assert_eq!("hello", CompactString::from_str_to_lowercase("HELLO"));
1773    /// ```
1774    ///
1775    /// A tricky example, with sigma:
1776    ///
1777    /// ```
1778    /// use compact_str::CompactString;
1779    ///
1780    /// assert_eq!("σ", CompactString::from_str_to_lowercase("Σ"));
1781    ///
1782    /// // but at the end of a word, it's ς, not σ:
1783    /// assert_eq!("ὀδυσσεύς", CompactString::from_str_to_lowercase("ὈΔΥΣΣΕΎΣ"));
1784    /// ```
1785    ///
1786    /// Languages without case are not changed:
1787    ///
1788    /// ```
1789    /// use compact_str::CompactString;
1790    ///
1791    /// let new_year = "农历新年";
1792    /// assert_eq!(new_year, CompactString::from_str_to_lowercase(new_year));
1793    /// ```
1794    #[must_use = "this returns the lowercase string as a new CompactString, \
1795                  without modifying the original"]
1796    pub fn from_str_to_lowercase(input: &str) -> Self {
1797        let mut s = convert_while_ascii(input.as_bytes(), u8::to_ascii_lowercase);
1798
1799        // Safety: we know this is a valid char boundary since
1800        // out.len() is only progressed if ascii bytes are found
1801        let rest = unsafe { input.get_unchecked(s.len()..) };
1802
1803        for (i, c) in rest.char_indices() {
1804            if c == 'Σ' {
1805                // Σ maps to σ, except at the end of a word where it maps to ς.
1806                // This is the only conditional (contextual) but language-independent mapping
1807                // in `SpecialCasing.txt`,
1808                // so hard-code it rather than have a generic "condition" mechanism.
1809                // See https://github.com/rust-lang/rust/issues/26035
1810                map_uppercase_sigma(rest, i, &mut s)
1811            } else {
1812                s.extend(c.to_lowercase());
1813            }
1814        }
1815        return s;
1816
1817        fn map_uppercase_sigma(from: &str, i: usize, to: &mut CompactString) {
1818            // See https://www.unicode.org/versions/Unicode7.0.0/ch03.pdf#G33992
1819            // for the definition of `Final_Sigma`.
1820            debug_assert!('Σ'.len_utf8() == 2);
1821            let is_word_final = case_ignorable_then_cased(from[..i].chars().rev())
1822                && !case_ignorable_then_cased(from[i + 2..].chars());
1823            to.push_str(if is_word_final { "ς" } else { "σ" });
1824        }
1825
1826        fn case_ignorable_then_cased<I: Iterator<Item = char>>(mut iter: I) -> bool {
1827            use unicode_data::case_ignorable::lookup as Case_Ignorable;
1828            use unicode_data::cased::lookup as Cased;
1829            match iter.find(|&c| !Case_Ignorable(c)) {
1830                Some(c) => Cased(c),
1831                None => false,
1832            }
1833        }
1834    }
1835
1836    /// Returns the uppercase equivalent of this string slice, as a new [`CompactString`].
1837    ///
1838    /// 'Uppercase' is defined according to the terms of the Unicode Derived Core Property
1839    /// `Uppercase`.
1840    ///
1841    /// Since some characters can expand into multiple characters when changing
1842    /// the case, this function returns a [`CompactString`] instead of modifying the
1843    /// parameter in-place.
1844    ///
1845    /// # Examples
1846    ///
1847    /// Basic usage:
1848    ///
1849    /// ```
1850    /// use compact_str::CompactString;
1851    /// let s = CompactString::new("hello");
1852    ///
1853    /// assert_eq!("HELLO", s.to_uppercase());
1854    /// ```
1855    ///
1856    /// Scripts without case are not changed:
1857    ///
1858    /// ```
1859    /// use compact_str::CompactString;
1860    /// let new_year = CompactString::new("农历新年");
1861    ///
1862    /// assert_eq!(new_year, new_year.to_uppercase());
1863    /// ```
1864    ///
1865    /// One character can become multiple:
1866    /// ```
1867    /// use compact_str::CompactString;
1868    /// let s = CompactString::new("tschüß");
1869    ///
1870    /// assert_eq!("TSCHÜSS", s.to_uppercase());
1871    /// ```
1872    #[must_use = "this returns the uppercase string as a new CompactString, \
1873                  without modifying the original"]
1874    pub fn to_uppercase(&self) -> Self {
1875        Self::from_str_to_uppercase(self.as_str())
1876    }
1877
1878    /// Returns the uppercase equivalent of this string slice, as a new [`CompactString`].
1879    ///
1880    /// 'Uppercase' is defined according to the terms of the Unicode Derived Core Property
1881    /// `Uppercase`.
1882    ///
1883    /// Since some characters can expand into multiple characters when changing
1884    /// the case, this function returns a [`CompactString`] instead of modifying the
1885    /// parameter in-place.
1886    ///
1887    /// # Examples
1888    ///
1889    /// Basic usage:
1890    ///
1891    /// ```
1892    /// use compact_str::CompactString;
1893    ///
1894    /// assert_eq!("HELLO", CompactString::from_str_to_uppercase("hello"));
1895    /// ```
1896    ///
1897    /// Scripts without case are not changed:
1898    ///
1899    /// ```
1900    /// use compact_str::CompactString;
1901    ///
1902    /// let new_year = "农历新年";
1903    /// assert_eq!(new_year, CompactString::from_str_to_uppercase(new_year));
1904    /// ```
1905    ///
1906    /// One character can become multiple:
1907    /// ```
1908    /// use compact_str::CompactString;
1909    ///
1910    /// assert_eq!("TSCHÜSS", CompactString::from_str_to_uppercase("tschüß"));
1911    /// ```
1912    #[must_use = "this returns the uppercase string as a new CompactString, \
1913                  without modifying the original"]
1914    pub fn from_str_to_uppercase(input: &str) -> Self {
1915        let mut out = convert_while_ascii(input.as_bytes(), u8::to_ascii_uppercase);
1916
1917        // Safety: we know this is a valid char boundary since
1918        // out.len() is only progressed if ascii bytes are found
1919        let rest = unsafe { input.get_unchecked(out.len()..) };
1920
1921        for c in rest.chars() {
1922            out.extend(c.to_uppercase());
1923        }
1924
1925        out
1926    }
1927}
1928
1929/// Converts the bytes while the bytes are still ascii.
1930/// For better average performance, this is happens in chunks of `2*size_of::<usize>()`.
1931/// Returns a vec with the converted bytes.
1932///
1933/// Copied from https://doc.rust-lang.org/nightly/src/alloc/str.rs.html#623-666
1934#[inline]
1935fn convert_while_ascii(b: &[u8], convert: fn(&u8) -> u8) -> CompactString {
1936    let mut out = CompactString::with_capacity(b.len());
1937
1938    const USIZE_SIZE: usize = mem::size_of::<usize>();
1939    const MAGIC_UNROLL: usize = 2;
1940    const N: usize = USIZE_SIZE * MAGIC_UNROLL;
1941    const NONASCII_MASK: usize = usize::from_ne_bytes([0x80; USIZE_SIZE]);
1942
1943    let mut i = 0;
1944    unsafe {
1945        while i + N <= b.len() {
1946            // Safety: we have checks the sizes `b` and `out` to know that our
1947            let in_chunk = b.get_unchecked(i..i + N);
1948            let out_chunk = out.spare_capacity_mut().get_unchecked_mut(i..i + N);
1949
1950            let mut bits = 0;
1951            for j in 0..MAGIC_UNROLL {
1952                // read the bytes 1 usize at a time (unaligned since we haven't checked the
1953                // alignment) safety: in_chunk is valid bytes in the range
1954                bits |= in_chunk.as_ptr().cast::<usize>().add(j).read_unaligned();
1955            }
1956            // if our chunks aren't ascii, then return only the prior bytes as init
1957            if bits & NONASCII_MASK != 0 {
1958                break;
1959            }
1960
1961            // perform the case conversions on N bytes (gets heavily autovec'd)
1962            for j in 0..N {
1963                // safety: in_chunk and out_chunk is valid bytes in the range
1964                let out = out_chunk.get_unchecked_mut(j);
1965                out.write(convert(in_chunk.get_unchecked(j)));
1966            }
1967
1968            // mark these bytes as initialised
1969            i += N;
1970        }
1971        out.set_len(i);
1972    }
1973
1974    out
1975}
1976
1977impl Clone for CompactString {
1978    #[inline]
1979    fn clone(&self) -> Self {
1980        Self(self.0.clone())
1981    }
1982
1983    #[inline]
1984    fn clone_from(&mut self, source: &Self) {
1985        self.0.clone_from(&source.0)
1986    }
1987}
1988
1989impl Default for CompactString {
1990    #[inline]
1991    fn default() -> Self {
1992        CompactString::const_new("")
1993    }
1994}
1995
1996impl Deref for CompactString {
1997    type Target = str;
1998
1999    #[inline]
2000    fn deref(&self) -> &str {
2001        self.as_str()
2002    }
2003}
2004
2005impl DerefMut for CompactString {
2006    #[inline]
2007    fn deref_mut(&mut self) -> &mut str {
2008        self.as_mut_str()
2009    }
2010}
2011
2012impl AsRef<str> for CompactString {
2013    #[inline]
2014    fn as_ref(&self) -> &str {
2015        self.as_str()
2016    }
2017}
2018
2019#[cfg(feature = "std")]
2020impl AsRef<OsStr> for CompactString {
2021    #[inline]
2022    fn as_ref(&self) -> &OsStr {
2023        OsStr::new(self.as_str())
2024    }
2025}
2026
2027impl AsRef<[u8]> for CompactString {
2028    #[inline]
2029    fn as_ref(&self) -> &[u8] {
2030        self.as_bytes()
2031    }
2032}
2033
2034impl Borrow<str> for CompactString {
2035    #[inline]
2036    fn borrow(&self) -> &str {
2037        self.as_str()
2038    }
2039}
2040
2041impl BorrowMut<str> for CompactString {
2042    #[inline]
2043    fn borrow_mut(&mut self) -> &mut str {
2044        self.as_mut_str()
2045    }
2046}
2047
2048impl Eq for CompactString {}
2049
2050impl<T: AsRef<str> + ?Sized> PartialEq<T> for CompactString {
2051    fn eq(&self, other: &T) -> bool {
2052        self.as_str() == other.as_ref()
2053    }
2054}
2055
2056impl PartialEq<CompactString> for &CompactString {
2057    fn eq(&self, other: &CompactString) -> bool {
2058        self.as_str() == other.as_str()
2059    }
2060}
2061
2062impl PartialEq<CompactString> for String {
2063    fn eq(&self, other: &CompactString) -> bool {
2064        self.as_str() == other.as_str()
2065    }
2066}
2067
2068impl PartialEq<&CompactString> for String {
2069    fn eq(&self, other: &&CompactString) -> bool {
2070        self.as_str() == other.as_str()
2071    }
2072}
2073
2074impl PartialEq<CompactString> for &String {
2075    fn eq(&self, other: &CompactString) -> bool {
2076        self.as_str() == other.as_str()
2077    }
2078}
2079
2080impl PartialEq<CompactString> for str {
2081    fn eq(&self, other: &CompactString) -> bool {
2082        self == other.as_str()
2083    }
2084}
2085
2086impl PartialEq<&'_ CompactString> for str {
2087    fn eq(&self, other: &&CompactString) -> bool {
2088        self == other.as_str()
2089    }
2090}
2091
2092impl PartialEq<CompactString> for &str {
2093    fn eq(&self, other: &CompactString) -> bool {
2094        *self == other.as_str()
2095    }
2096}
2097
2098impl PartialEq<CompactString> for &&str {
2099    fn eq(&self, other: &CompactString) -> bool {
2100        **self == other.as_str()
2101    }
2102}
2103
2104impl PartialEq<CompactString> for Cow<'_, str> {
2105    fn eq(&self, other: &CompactString) -> bool {
2106        *self == other.as_str()
2107    }
2108}
2109
2110impl PartialEq<CompactString> for &Cow<'_, str> {
2111    fn eq(&self, other: &CompactString) -> bool {
2112        *self == other.as_str()
2113    }
2114}
2115
2116impl PartialEq<String> for &CompactString {
2117    fn eq(&self, other: &String) -> bool {
2118        self.as_str() == other.as_str()
2119    }
2120}
2121
2122impl PartialEq<Cow<'_, str>> for &CompactString {
2123    fn eq(&self, other: &Cow<'_, str>) -> bool {
2124        self.as_str() == other
2125    }
2126}
2127
2128impl Ord for CompactString {
2129    fn cmp(&self, other: &Self) -> Ordering {
2130        self.as_str().cmp(other.as_str())
2131    }
2132}
2133
2134impl PartialOrd for CompactString {
2135    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
2136        Some(self.cmp(other))
2137    }
2138}
2139
2140impl Hash for CompactString {
2141    fn hash<H: Hasher>(&self, state: &mut H) {
2142        self.as_str().hash(state)
2143    }
2144}
2145
2146impl<'a> From<&'a str> for CompactString {
2147    #[inline]
2148    #[track_caller]
2149    fn from(s: &'a str) -> Self {
2150        CompactString::new(s)
2151    }
2152}
2153
2154impl From<String> for CompactString {
2155    #[inline]
2156    #[track_caller]
2157    fn from(s: String) -> Self {
2158        let repr = Repr::from_string(s, true).unwrap_with_msg();
2159        CompactString(repr)
2160    }
2161}
2162
2163impl<'a> From<&'a String> for CompactString {
2164    #[inline]
2165    #[track_caller]
2166    fn from(s: &'a String) -> Self {
2167        CompactString::new(s)
2168    }
2169}
2170
2171impl<'a> From<Cow<'a, str>> for CompactString {
2172    fn from(cow: Cow<'a, str>) -> Self {
2173        match cow {
2174            Cow::Borrowed(s) => s.into(),
2175            // we separate these two so we can re-use the underlying buffer in the owned case
2176            Cow::Owned(s) => s.into(),
2177        }
2178    }
2179}
2180
2181impl From<Box<str>> for CompactString {
2182    #[inline]
2183    #[track_caller]
2184    fn from(b: Box<str>) -> Self {
2185        let s = b.into_string();
2186        let repr = Repr::from_string(s, true).unwrap_with_msg();
2187        CompactString(repr)
2188    }
2189}
2190
2191impl From<CompactString> for String {
2192    #[inline]
2193    fn from(s: CompactString) -> Self {
2194        s.into_string()
2195    }
2196}
2197
2198impl From<CompactString> for Cow<'_, str> {
2199    #[inline]
2200    fn from(s: CompactString) -> Self {
2201        if let Some(s) = s.as_static_str() {
2202            Self::Borrowed(s)
2203        } else {
2204            Self::Owned(s.into_string())
2205        }
2206    }
2207}
2208
2209impl<'a> From<&'a CompactString> for Cow<'a, str> {
2210    #[inline]
2211    fn from(s: &'a CompactString) -> Self {
2212        Self::Borrowed(s)
2213    }
2214}
2215
2216#[cfg(target_has_atomic = "ptr")]
2217impl From<CompactString> for alloc::sync::Arc<str> {
2218    fn from(value: CompactString) -> Self {
2219        Self::from(value.as_str())
2220    }
2221}
2222
2223impl From<CompactString> for alloc::rc::Rc<str> {
2224    fn from(value: CompactString) -> Self {
2225        Self::from(value.as_str())
2226    }
2227}
2228
2229#[cfg(feature = "std")]
2230impl From<CompactString> for Box<dyn std::error::Error + Send + Sync> {
2231    fn from(value: CompactString) -> Self {
2232        struct StringError(CompactString);
2233
2234        impl std::error::Error for StringError {
2235            #[allow(deprecated)]
2236            fn description(&self) -> &str {
2237                &self.0
2238            }
2239        }
2240
2241        impl fmt::Display for StringError {
2242            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2243                fmt::Display::fmt(&self.0, f)
2244            }
2245        }
2246
2247        // Purposefully skip printing "StringError(..)"
2248        impl fmt::Debug for StringError {
2249            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2250                fmt::Debug::fmt(&self.0, f)
2251            }
2252        }
2253
2254        Box::new(StringError(value))
2255    }
2256}
2257
2258#[cfg(feature = "std")]
2259impl From<CompactString> for Box<dyn std::error::Error> {
2260    fn from(value: CompactString) -> Self {
2261        let err1: Box<dyn std::error::Error + Send + Sync> = From::from(value);
2262        let err2: Box<dyn std::error::Error> = err1;
2263        err2
2264    }
2265}
2266
2267impl From<CompactString> for Box<str> {
2268    fn from(value: CompactString) -> Self {
2269        if value.is_heap_allocated() {
2270            value.into_string().into_boxed_str()
2271        } else {
2272            Box::from(value.as_str())
2273        }
2274    }
2275}
2276
2277#[cfg(feature = "std")]
2278impl From<CompactString> for std::ffi::OsString {
2279    fn from(value: CompactString) -> Self {
2280        Self::from(value.into_string())
2281    }
2282}
2283
2284#[cfg(feature = "std")]
2285impl From<CompactString> for std::path::PathBuf {
2286    fn from(value: CompactString) -> Self {
2287        Self::from(std::ffi::OsString::from(value))
2288    }
2289}
2290
2291#[cfg(feature = "std")]
2292impl AsRef<std::path::Path> for CompactString {
2293    fn as_ref(&self) -> &std::path::Path {
2294        std::path::Path::new(self.as_str())
2295    }
2296}
2297
2298impl From<CompactString> for alloc::vec::Vec<u8> {
2299    fn from(value: CompactString) -> Self {
2300        if value.is_heap_allocated() {
2301            value.into_string().into_bytes()
2302        } else {
2303            value.as_bytes().to_vec()
2304        }
2305    }
2306}
2307
2308impl FromStr for CompactString {
2309    type Err = core::convert::Infallible;
2310    fn from_str(s: &str) -> Result<CompactString, Self::Err> {
2311        Ok(CompactString::from(s))
2312    }
2313}
2314
2315impl fmt::Debug for CompactString {
2316    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2317        fmt::Debug::fmt(self.as_str(), f)
2318    }
2319}
2320
2321impl fmt::Display for CompactString {
2322    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2323        fmt::Display::fmt(self.as_str(), f)
2324    }
2325}
2326
2327impl FromIterator<char> for CompactString {
2328    fn from_iter<T: IntoIterator<Item = char>>(iter: T) -> Self {
2329        let repr = iter.into_iter().collect();
2330        CompactString(repr)
2331    }
2332}
2333
2334impl<'a> FromIterator<&'a char> for CompactString {
2335    fn from_iter<T: IntoIterator<Item = &'a char>>(iter: T) -> Self {
2336        let repr = iter.into_iter().collect();
2337        CompactString(repr)
2338    }
2339}
2340
2341impl<'a> FromIterator<&'a str> for CompactString {
2342    fn from_iter<T: IntoIterator<Item = &'a str>>(iter: T) -> Self {
2343        let repr = iter.into_iter().collect();
2344        CompactString(repr)
2345    }
2346}
2347
2348impl FromIterator<Box<str>> for CompactString {
2349    fn from_iter<T: IntoIterator<Item = Box<str>>>(iter: T) -> Self {
2350        let repr = iter.into_iter().collect();
2351        CompactString(repr)
2352    }
2353}
2354
2355impl<'a> FromIterator<Cow<'a, str>> for CompactString {
2356    fn from_iter<T: IntoIterator<Item = Cow<'a, str>>>(iter: T) -> Self {
2357        let repr = iter.into_iter().collect();
2358        CompactString(repr)
2359    }
2360}
2361
2362impl FromIterator<String> for CompactString {
2363    fn from_iter<T: IntoIterator<Item = String>>(iter: T) -> Self {
2364        let repr = iter.into_iter().collect();
2365        CompactString(repr)
2366    }
2367}
2368
2369impl FromIterator<CompactString> for CompactString {
2370    fn from_iter<T: IntoIterator<Item = CompactString>>(iter: T) -> Self {
2371        let repr = iter.into_iter().collect();
2372        CompactString(repr)
2373    }
2374}
2375
2376impl FromIterator<CompactString> for String {
2377    fn from_iter<T: IntoIterator<Item = CompactString>>(iter: T) -> Self {
2378        let mut iterator = iter.into_iter();
2379        match iterator.next() {
2380            None => String::new(),
2381            Some(buf) => {
2382                let mut buf = buf.into_string();
2383                buf.extend(iterator);
2384                buf
2385            }
2386        }
2387    }
2388}
2389
2390impl FromIterator<CompactString> for Cow<'_, str> {
2391    fn from_iter<T: IntoIterator<Item = CompactString>>(iter: T) -> Self {
2392        String::from_iter(iter).into()
2393    }
2394}
2395
2396impl Extend<char> for CompactString {
2397    fn extend<T: IntoIterator<Item = char>>(&mut self, iter: T) {
2398        self.0.extend(iter)
2399    }
2400}
2401
2402impl<'a> Extend<&'a char> for CompactString {
2403    fn extend<T: IntoIterator<Item = &'a char>>(&mut self, iter: T) {
2404        self.0.extend(iter)
2405    }
2406}
2407
2408impl<'a> Extend<&'a str> for CompactString {
2409    fn extend<T: IntoIterator<Item = &'a str>>(&mut self, iter: T) {
2410        self.0.extend(iter)
2411    }
2412}
2413
2414impl Extend<Box<str>> for CompactString {
2415    fn extend<T: IntoIterator<Item = Box<str>>>(&mut self, iter: T) {
2416        self.0.extend(iter)
2417    }
2418}
2419
2420impl<'a> Extend<Cow<'a, str>> for CompactString {
2421    fn extend<T: IntoIterator<Item = Cow<'a, str>>>(&mut self, iter: T) {
2422        iter.into_iter().for_each(move |s| self.push_str(&s));
2423    }
2424}
2425
2426impl Extend<String> for CompactString {
2427    fn extend<T: IntoIterator<Item = String>>(&mut self, iter: T) {
2428        self.0.extend(iter)
2429    }
2430}
2431
2432impl Extend<CompactString> for String {
2433    fn extend<T: IntoIterator<Item = CompactString>>(&mut self, iter: T) {
2434        for s in iter {
2435            self.push_str(&s);
2436        }
2437    }
2438}
2439
2440impl Extend<CompactString> for CompactString {
2441    fn extend<T: IntoIterator<Item = CompactString>>(&mut self, iter: T) {
2442        for s in iter {
2443            self.push_str(&s);
2444        }
2445    }
2446}
2447
2448impl Extend<CompactString> for Cow<'_, str> {
2449    fn extend<T: IntoIterator<Item = CompactString>>(&mut self, iter: T) {
2450        self.to_mut().extend(iter);
2451    }
2452}
2453
2454impl fmt::Write for CompactString {
2455    fn write_str(&mut self, s: &str) -> fmt::Result {
2456        self.push_str(s);
2457        Ok(())
2458    }
2459
2460    fn write_fmt(mut self: &mut Self, args: fmt::Arguments<'_>) -> fmt::Result {
2461        match args.as_str() {
2462            Some(s) => {
2463                if self.is_empty() && !self.is_heap_allocated() {
2464                    // Since self is currently an empty inline variant or
2465                    // an empty `StaticStr` variant, constructing a new one
2466                    // with `Self::const_new` is more efficient since
2467                    // it is guaranteed to be O(1).
2468                    *self = Self::const_new(s);
2469                } else {
2470                    self.push_str(s);
2471                }
2472                Ok(())
2473            }
2474            None => fmt::write(&mut self, args),
2475        }
2476    }
2477}
2478
2479impl Add<&str> for CompactString {
2480    type Output = Self;
2481    fn add(mut self, rhs: &str) -> Self::Output {
2482        self.push_str(rhs);
2483        self
2484    }
2485}
2486
2487impl AddAssign<&str> for CompactString {
2488    fn add_assign(&mut self, rhs: &str) {
2489        self.push_str(rhs);
2490    }
2491}
2492
2493/// A possible error value when converting a [`CompactString`] from a UTF-16 byte slice.
2494///
2495/// This type is the error type for the [`from_utf16`] method on [`CompactString`].
2496///
2497/// [`from_utf16`]: CompactString::from_utf16
2498/// # Examples
2499///
2500/// Basic usage:
2501///
2502/// ```
2503/// # use compact_str::CompactString;
2504/// // 𝄞mu<invalid>ic
2505/// let v = &[0xD834, 0xDD1E, 0x006d, 0x0075,
2506///           0xD800, 0x0069, 0x0063];
2507///
2508/// assert!(CompactString::from_utf16(v).is_err());
2509/// ```
2510#[derive(Copy, Clone, Debug)]
2511pub struct Utf16Error(());
2512
2513impl fmt::Display for Utf16Error {
2514    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2515        fmt::Display::fmt("invalid utf-16: lone surrogate found", f)
2516    }
2517}
2518
2519/// An iterator over the exacted data by [`CompactString::drain()`].
2520///
2521/// Note: this is deliberately not `#[must_use]`. Dropping a `Drain` still removes the
2522/// selected range from the source `CompactString` (see the `Drop` impl), so calling
2523/// `drain(range)` purely to delete a range, without consuming the iterator, is a valid
2524/// and common use, mirroring `alloc::string::Drain`.
2525pub struct Drain<'a> {
2526    compact_string: *mut CompactString,
2527    start: usize,
2528    end: usize,
2529    chars: core::str::Chars<'a>,
2530}
2531
2532// SAFETY: Drain keeps the lifetime of the CompactString it belongs to.
2533unsafe impl Send for Drain<'_> {}
2534unsafe impl Sync for Drain<'_> {}
2535
2536impl fmt::Debug for Drain<'_> {
2537    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2538        f.debug_tuple("Drain").field(&self.as_str()).finish()
2539    }
2540}
2541
2542impl fmt::Display for Drain<'_> {
2543    #[inline]
2544    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2545        f.write_str(self.as_str())
2546    }
2547}
2548
2549impl Drop for Drain<'_> {
2550    #[inline]
2551    fn drop(&mut self) {
2552        // SAFETY: Drain keeps a mutable reference to compact_string, so one one else can access
2553        //         the CompactString, but this function right now. CompactString::drain() ensured
2554        //         that the new extracted range does not split a UTF-8 character.
2555        unsafe { (*self.compact_string).replace_range_shrink(self.start, self.end, "") };
2556    }
2557}
2558
2559impl Drain<'_> {
2560    /// The remaining, unconsumed characters of the extracted substring.
2561    #[inline]
2562    pub fn as_str(&self) -> &str {
2563        self.chars.as_str()
2564    }
2565}
2566
2567impl Deref for Drain<'_> {
2568    type Target = str;
2569
2570    #[inline]
2571    fn deref(&self) -> &Self::Target {
2572        self.as_str()
2573    }
2574}
2575
2576impl Iterator for Drain<'_> {
2577    type Item = char;
2578
2579    #[inline]
2580    fn next(&mut self) -> Option<char> {
2581        self.chars.next()
2582    }
2583
2584    #[inline]
2585    fn count(self) -> usize {
2586        // <Chars as Iterator>::count() is specialized, and cloning is trivial.
2587        self.chars.clone().count()
2588    }
2589
2590    fn size_hint(&self) -> (usize, Option<usize>) {
2591        self.chars.size_hint()
2592    }
2593
2594    #[inline]
2595    fn last(mut self) -> Option<char> {
2596        self.chars.next_back()
2597    }
2598}
2599
2600impl DoubleEndedIterator for Drain<'_> {
2601    #[inline]
2602    fn next_back(&mut self) -> Option<char> {
2603        self.chars.next_back()
2604    }
2605}
2606
2607impl FusedIterator for Drain<'_> {}
2608
2609/// A possible error value if allocating or resizing a [`CompactString`] failed.
2610#[derive(Debug, Clone, Copy, PartialEq)]
2611pub struct ReserveError(());
2612
2613impl fmt::Display for ReserveError {
2614    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2615        f.write_str("Cannot allocate memory to hold CompactString")
2616    }
2617}
2618
2619#[cfg(feature = "std")]
2620#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
2621impl std::error::Error for ReserveError {}
2622
2623/// A possible error value if [`ToCompactString::try_to_compact_string()`] failed.
2624#[derive(Debug, Clone, Copy, PartialEq)]
2625#[non_exhaustive]
2626pub enum ToCompactStringError {
2627    /// Cannot allocate memory to hold CompactString
2628    Reserve(ReserveError),
2629    /// [`Display::fmt()`][core::fmt::Display::fmt] returned an error
2630    Fmt(fmt::Error),
2631}
2632
2633impl fmt::Display for ToCompactStringError {
2634    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2635        match self {
2636            ToCompactStringError::Reserve(err) => err.fmt(f),
2637            ToCompactStringError::Fmt(err) => err.fmt(f),
2638        }
2639    }
2640}
2641
2642impl From<ReserveError> for ToCompactStringError {
2643    #[inline]
2644    fn from(value: ReserveError) -> Self {
2645        Self::Reserve(value)
2646    }
2647}
2648
2649impl From<fmt::Error> for ToCompactStringError {
2650    #[inline]
2651    fn from(value: fmt::Error) -> Self {
2652        Self::Fmt(value)
2653    }
2654}
2655
2656#[cfg(feature = "std")]
2657#[cfg_attr(docsrs, doc(cfg(feature = "std")))]
2658impl std::error::Error for ToCompactStringError {
2659    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
2660        match self {
2661            ToCompactStringError::Reserve(err) => Some(err),
2662            ToCompactStringError::Fmt(err) => Some(err),
2663        }
2664    }
2665}
2666
2667trait UnwrapWithMsg {
2668    type T;
2669
2670    fn unwrap_with_msg(self) -> Self::T;
2671}
2672
2673impl<T, E: fmt::Display> UnwrapWithMsg for Result<T, E> {
2674    type T = T;
2675
2676    #[inline(always)]
2677    #[track_caller]
2678    fn unwrap_with_msg(self) -> T {
2679        match self {
2680            Ok(value) => value,
2681            Err(err) => unwrap_with_msg_fail(err),
2682        }
2683    }
2684}
2685
2686#[inline(never)]
2687#[cold]
2688#[track_caller]
2689fn unwrap_with_msg_fail<E: fmt::Display>(error: E) -> ! {
2690    panic!("{error}")
2691}
2692
2693static_assertions::assert_eq_size!(CompactString, String);
2694static_assertions::assert_eq_size!(Option<CompactString>, CompactString);