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