heapless/string/
mod.rs

1//! A fixed capacity [`String`](https://doc.rust-lang.org/std/string/struct.String.html).
2
3use core::{
4    borrow,
5    char::DecodeUtf16Error,
6    cmp::Ordering,
7    fmt,
8    fmt::{Arguments, Write},
9    hash, iter,
10    ops::{self, Range, RangeBounds},
11    str::{self, Utf8Error},
12};
13
14use crate::CapacityError;
15use crate::{
16    len_type::LenType,
17    vec::{OwnedVecStorage, Vec, VecInner, ViewVecStorage},
18};
19
20mod drain;
21pub use drain::Drain;
22
23/// A possible error value when converting a [`String`] from a UTF-16 byte slice.
24///
25/// This type is the error type for the [`from_utf16`] method on [`String`].
26///
27/// [`from_utf16`]: String::from_utf16
28#[derive(Debug)]
29pub enum FromUtf16Error {
30    /// The capacity of the `String` is too small for the given operation.
31    Capacity(CapacityError),
32    /// Error decoding UTF-16.
33    DecodeUtf16(DecodeUtf16Error),
34}
35
36impl fmt::Display for FromUtf16Error {
37    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
38        match self {
39            Self::Capacity(err) => write!(f, "{err}"),
40            Self::DecodeUtf16(err) => write!(f, "invalid UTF-16: {err}"),
41        }
42    }
43}
44
45impl core::error::Error for FromUtf16Error {}
46
47impl From<CapacityError> for FromUtf16Error {
48    fn from(e: CapacityError) -> Self {
49        Self::Capacity(e)
50    }
51}
52
53mod storage {
54    use super::{StringInner, StringView};
55    use crate::{
56        vec::{OwnedVecStorage, VecStorage, ViewVecStorage},
57        LenType,
58    };
59
60    /// Trait defining how data for a String is stored.
61    ///
62    /// There's two implementations available:
63    ///
64    /// - [`OwnedStorage`]: stores the data in an array whose size is known at compile time.
65    /// - [`ViewStorage`]: stores the data in an unsized slice
66    ///
67    /// This allows [`String`] to be generic over either sized or unsized storage. The [`string`](super)
68    /// module contains a [`StringInner`] struct that's generic on [`StringStorage`],
69    /// and two type aliases for convenience:
70    ///
71    /// - [`String<N>`](crate::string::String) = `StringInner<OwnedStorage<u8, N>>`
72    /// - [`StringView<T>`](crate::string::StringView) = `StringInner<ViewStorage<u8>>`
73    ///
74    /// `String` can be unsized into `StrinsgView`, either by unsizing coercions such as `&mut String -> &mut StringView` or
75    /// `Box<String> -> Box<StringView>`, or explicitly with [`.as_view()`](crate::string::String::as_view) or [`.as_mut_view()`](crate::string::String::as_mut_view).
76    ///
77    /// This trait is sealed, so you cannot implement it for your own types. You can only use
78    /// the implementations provided by this crate.
79    ///
80    /// [`StringInner`]: super::StringInner
81    /// [`String`]: super::String
82    /// [`OwnedStorage`]: super::OwnedStorage
83    /// [`ViewStorage`]: super::ViewStorage
84    pub trait StringStorage: StringStorageSealed {}
85    pub trait StringStorageSealed: VecStorage<u8> {
86        fn as_string_view<LenT: LenType>(this: &StringInner<LenT, Self>) -> &StringView<LenT>
87        where
88            Self: StringStorage;
89        fn as_string_mut_view<LenT: LenType>(
90            this: &mut StringInner<LenT, Self>,
91        ) -> &mut StringView<LenT>
92        where
93            Self: StringStorage;
94    }
95
96    impl<const N: usize> StringStorage for OwnedVecStorage<u8, N> {}
97    impl<const N: usize> StringStorageSealed for OwnedVecStorage<u8, N> {
98        fn as_string_view<LenT: LenType>(this: &StringInner<LenT, Self>) -> &StringView<LenT>
99        where
100            Self: StringStorage,
101        {
102            this
103        }
104        fn as_string_mut_view<LenT: LenType>(
105            this: &mut StringInner<LenT, Self>,
106        ) -> &mut StringView<LenT>
107        where
108            Self: StringStorage,
109        {
110            this
111        }
112    }
113
114    impl StringStorage for ViewVecStorage<u8> {}
115
116    impl StringStorageSealed for ViewVecStorage<u8> {
117        fn as_string_view<LenT: LenType>(this: &StringInner<LenT, Self>) -> &StringView<LenT>
118        where
119            Self: StringStorage,
120        {
121            this
122        }
123        fn as_string_mut_view<LenT: LenType>(
124            this: &mut StringInner<LenT, Self>,
125        ) -> &mut StringView<LenT>
126        where
127            Self: StringStorage,
128        {
129            this
130        }
131    }
132}
133
134pub use storage::StringStorage;
135
136/// Implementation of [`StringStorage`] that stores the data in an array whose size is known at compile time.
137pub type OwnedStorage<const N: usize> = OwnedVecStorage<u8, N>;
138/// Implementation of [`StringStorage`] that stores the data in an unsized slice.
139pub type ViewStorage = ViewVecStorage<u8>;
140
141/// Base struct for [`String`] and [`StringView`], generic over the [`StringStorage`].
142///
143/// In most cases you should use [`String`] or [`StringView`] directly. Only use this
144/// struct if you want to write code that's generic over both.
145pub struct StringInner<LenT: LenType, S: StringStorage + ?Sized> {
146    vec: VecInner<u8, LenT, S>,
147}
148
149/// A fixed capacity [`String`](https://doc.rust-lang.org/std/string/struct.String.html).
150pub type String<const N: usize, LenT = usize> = StringInner<LenT, OwnedStorage<N>>;
151
152/// A dynamic capacity [`String`](https://doc.rust-lang.org/std/string/struct.String.html).
153pub type StringView<LenT = usize> = StringInner<LenT, ViewStorage>;
154
155impl<LenT: LenType, const N: usize> String<N, LenT> {
156    /// Constructs a new, empty `String` with a fixed capacity of `N` bytes.
157    ///
158    /// # Examples
159    ///
160    /// Basic usage:
161    ///
162    /// ```
163    /// use heapless::String;
164    ///
165    /// // allocate the string on the stack
166    /// let mut s: String<4> = String::new();
167    ///
168    /// // allocate the string in a static variable
169    /// static mut S: String<4> = String::new();
170    /// ```
171    #[inline]
172    pub const fn new() -> Self {
173        Self { vec: Vec::new() }
174    }
175
176    /// Decodes a UTF-16–encoded slice `v` into a `String`, returning [`Err`]
177    /// if `v` contains any invalid data.
178    ///
179    /// # Examples
180    ///
181    /// Basic usage:
182    ///
183    /// ```
184    /// use heapless::String;
185    ///
186    /// // 𝄞music
187    /// let v = &[0xD834, 0xDD1E, 0x006d, 0x0075, 0x0073, 0x0069, 0x0063];
188    /// let s: String<10> = String::from_utf16(v).unwrap();
189    /// assert_eq!(s, "𝄞music");
190    ///
191    /// // 𝄞mu<invalid>ic
192    /// let v = &[0xD834, 0xDD1E, 0x006d, 0x0075, 0xD800, 0x0069, 0x0063];
193    /// assert!(String::<10>::from_utf16(v).is_err());
194    /// ```
195    #[inline]
196    pub fn from_utf16(v: &[u16]) -> Result<Self, FromUtf16Error> {
197        let mut s = Self::new();
198
199        for c in char::decode_utf16(v.iter().cloned()) {
200            match c {
201                Ok(c) => {
202                    s.push(c).map_err(|_| CapacityError)?;
203                }
204                Err(err) => {
205                    return Err(FromUtf16Error::DecodeUtf16(err));
206                }
207            }
208        }
209
210        Ok(s)
211    }
212
213    /// Convert UTF-8 bytes into a `String`.
214    ///
215    /// # Examples
216    ///
217    /// Basic usage:
218    ///
219    /// ```
220    /// use heapless::{String, Vec};
221    ///
222    /// let mut sparkle_heart = Vec::<u8, 4>::new();
223    /// sparkle_heart.extend_from_slice(&[240, 159, 146, 150]);
224    ///
225    /// let sparkle_heart: String<4> = String::from_utf8(sparkle_heart)?;
226    /// assert_eq!("💖", sparkle_heart);
227    /// # Ok::<(), core::str::Utf8Error>(())
228    /// ```
229    ///
230    /// Invalid UTF-8:
231    ///
232    /// ```
233    /// use core::str::Utf8Error;
234    /// use heapless::{String, Vec};
235    ///
236    /// let mut vec = Vec::<u8, 4>::new();
237    /// vec.extend_from_slice(&[0, 159, 146, 150]);
238    ///
239    /// let e: Utf8Error = String::from_utf8(vec).unwrap_err();
240    /// assert_eq!(e.valid_up_to(), 1);
241    /// # Ok::<(), core::str::Utf8Error>(())
242    /// ```
243    #[inline]
244    pub fn from_utf8(vec: Vec<u8, N, LenT>) -> Result<Self, Utf8Error> {
245        core::str::from_utf8(&vec)?;
246
247        // SAFETY: UTF-8 invariant has just been checked by `str::from_utf8`.
248        Ok(unsafe { Self::from_utf8_unchecked(vec) })
249    }
250
251    /// Convert UTF-8 bytes into a `String`, without checking that the string
252    /// contains valid UTF-8.
253    ///
254    /// # Safety
255    ///
256    /// The bytes passed in must be valid UTF-8.
257    ///
258    /// # Examples
259    ///
260    /// Basic usage:
261    ///
262    /// ```
263    /// use heapless::{String, Vec};
264    ///
265    /// let mut sparkle_heart = Vec::<u8, 4>::new();
266    /// sparkle_heart.extend_from_slice(&[240, 159, 146, 150]);
267    ///
268    /// // Safety: `sparkle_heart` Vec is known to contain valid UTF-8
269    /// let sparkle_heart: String<4> = unsafe { String::from_utf8_unchecked(sparkle_heart) };
270    /// assert_eq!("💖", sparkle_heart);
271    /// ```
272    #[inline]
273    pub unsafe fn from_utf8_unchecked(vec: Vec<u8, N, LenT>) -> Self {
274        Self { vec }
275    }
276
277    /// Converts a `String` into a byte vector.
278    ///
279    /// This consumes the `String`, so we do not need to copy its contents.
280    ///
281    /// # Examples
282    ///
283    /// Basic usage:
284    ///
285    /// ```
286    /// use heapless::String;
287    ///
288    /// let s: String<4> = String::try_from("ab")?;
289    /// let b = s.into_bytes();
290    /// assert!(b.len() == 2);
291    ///
292    /// assert_eq!(&[b'a', b'b'], &b[..]);
293    /// # Ok::<(), heapless::CapacityError>(())
294    /// ```
295    #[inline]
296    pub fn into_bytes(self) -> Vec<u8, N, LenT> {
297        self.vec
298    }
299}
300
301impl<LenT: LenType, S: StringStorage + ?Sized> StringInner<LenT, S> {
302    /// Removes the specified range from the string in bulk, returning all
303    /// removed characters as an iterator.
304    ///
305    /// The returned iterator keeps a mutable borrow on the string to optimize
306    /// its implementation.
307    ///
308    /// # Panics
309    ///
310    /// Panics if the starting point or end point do not lie on a [`char`]
311    /// boundary, or if they're out of bounds.
312    ///
313    /// # Leaking
314    ///
315    /// If the returned iterator goes out of scope without being dropped (due to
316    /// [`core::mem::forget`], for example), the string may still contain a copy
317    /// of any drained characters, or may have lost characters arbitrarily,
318    /// including characters outside the range.
319    ///
320    /// # Examples
321    ///
322    /// ```
323    /// use heapless::String;
324    ///
325    /// let mut s = String::<32>::try_from("α is alpha, β is beta").unwrap();
326    /// let beta_offset = s.find('β').unwrap_or(s.len());
327    ///
328    /// // Remove the range up until the β from the string
329    /// let t: String<32> = s.drain(..beta_offset).collect();
330    /// assert_eq!(t, "α is alpha, ");
331    /// assert_eq!(s, "β is beta");
332    ///
333    /// // A full range clears the string, like `clear()` does
334    /// s.drain(..);
335    /// assert_eq!(s, "");
336    /// ```
337    pub fn drain<R>(&mut self, range: R) -> Drain<'_, LenT>
338    where
339        R: RangeBounds<usize>,
340    {
341        // Memory safety
342        //
343        // The `String` version of `Drain` does not have the memory safety issues
344        // of the `Vec` version. The data is just plain bytes.
345        // Because the range removal happens in `Drop`, if the `Drain` iterator is leaked,
346        // the removal will not happen.
347        let Range { start, end } = crate::slice::range(range, ..self.len());
348        assert!(self.is_char_boundary(start));
349        assert!(self.is_char_boundary(end));
350
351        // Take out two simultaneous borrows. The &mut String won't be accessed
352        // until iteration is over, in Drop.
353        let self_ptr = self.as_mut_view() as *mut _;
354        // SAFETY: `slice::range` and `is_char_boundary` do the appropriate bounds checks.
355        let chars_iter = unsafe { self.get_unchecked(start..end) }.chars();
356
357        Drain {
358            start: LenT::from_usize(start),
359            end: LenT::from_usize(end),
360            iter: chars_iter,
361            string: self_ptr,
362        }
363    }
364
365    /// Get a reference to the `String`, erasing the `N` const-generic.
366    ///
367    ///
368    /// ```rust
369    /// # use heapless::string::{String, StringView};
370    /// let s: String<10, _> = String::try_from("hello").unwrap();
371    /// let view: &StringView = s.as_view();
372    /// ```
373    ///
374    /// It is often preferable to do the same through type coerction, since `String<N>` implements `Unsize<StringView>`:
375    ///
376    /// ```rust
377    /// # use heapless::string::{String, StringView};
378    /// let s: String<10, _> = String::try_from("hello").unwrap();
379    /// let view: &StringView = &s;
380    /// ```
381    #[inline]
382    pub fn as_view(&self) -> &StringView<LenT> {
383        S::as_string_view(self)
384    }
385
386    /// Get a mutable reference to the `String`, erasing the `N` const-generic.
387    ///
388    ///
389    /// ```rust
390    /// # use heapless::string::{String, StringView};
391    /// let mut s: String<10> = String::try_from("hello").unwrap();
392    /// let view: &mut StringView = s.as_mut_view();
393    /// ```
394    ///
395    /// It is often preferable to do the same through type coerction, since `String<N>` implements `Unsize<StringView>`:
396    ///
397    /// ```rust
398    /// # use heapless::string::{String, StringView};
399    /// let mut s: String<10> = String::try_from("hello").unwrap();
400    /// let view: &mut StringView = &mut s;
401    /// ```
402    #[inline]
403    pub fn as_mut_view(&mut self) -> &mut StringView<LenT> {
404        S::as_string_mut_view(self)
405    }
406
407    /// Extracts a string slice containing the entire string.
408    ///
409    /// # Examples
410    ///
411    /// Basic usage:
412    ///
413    /// ```
414    /// use heapless::String;
415    ///
416    /// let mut s: String<4> = String::try_from("ab")?;
417    /// assert!(s.as_str() == "ab");
418    ///
419    /// let _s = s.as_str();
420    /// // s.push('c'); // <- cannot borrow `s` as mutable because it is also borrowed as immutable
421    /// # Ok::<(), heapless::CapacityError>(())
422    /// ```
423    #[inline]
424    pub fn as_str(&self) -> &str {
425        unsafe { str::from_utf8_unchecked(self.vec.as_slice()) }
426    }
427
428    /// Converts a `String` into a mutable string slice.
429    ///
430    /// # Examples
431    ///
432    /// Basic usage:
433    ///
434    /// ```
435    /// use heapless::String;
436    ///
437    /// let mut s: String<4> = String::try_from("ab")?;
438    /// let s = s.as_mut_str();
439    /// s.make_ascii_uppercase();
440    /// # Ok::<(), heapless::CapacityError>(())
441    /// ```
442    #[inline]
443    pub fn as_mut_str(&mut self) -> &mut str {
444        unsafe { str::from_utf8_unchecked_mut(self.vec.as_mut_slice()) }
445    }
446
447    /// Returns a mutable reference to the contents of this `String`.
448    ///
449    /// # Safety
450    ///
451    /// This function is unsafe because it does not check that the bytes passed
452    /// to it are valid UTF-8. If this constraint is violated, it may cause
453    /// memory unsafety issues with future users of the `String`, as the rest of
454    /// the library assumes that `String`s are valid UTF-8.
455    ///
456    /// # Examples
457    ///
458    /// Basic usage:
459    ///
460    /// ```
461    /// use heapless::String;
462    ///
463    /// let mut s: String<8> = String::try_from("hello")?;
464    ///
465    /// unsafe {
466    ///     let vec = s.as_mut_vec();
467    ///     assert_eq!(&[104, 101, 108, 108, 111][..], &vec[..]);
468    ///
469    ///     vec.reverse();
470    /// }
471    /// assert_eq!(s, "olleh");
472    /// # Ok::<(), heapless::CapacityError>(())
473    /// ```
474    pub unsafe fn as_mut_vec(&mut self) -> &mut VecInner<u8, LenT, S> {
475        &mut self.vec
476    }
477
478    /// Appends a given string slice onto the end of this `String`.
479    ///
480    /// # Examples
481    ///
482    /// Basic usage:
483    ///
484    /// ```
485    /// use heapless::String;
486    ///
487    /// let mut s: String<8> = String::try_from("foo")?;
488    ///
489    /// assert!(s.push_str("bar").is_ok());
490    ///
491    /// assert_eq!("foobar", s);
492    ///
493    /// assert!(s.push_str("tender").is_err());
494    /// # Ok::<(), heapless::CapacityError>(())
495    /// ```
496    #[inline]
497    pub fn push_str(&mut self, string: &str) -> Result<(), CapacityError> {
498        self.vec.extend_from_slice(string.as_bytes())
499    }
500
501    /// Returns the maximum number of elements the String can hold.
502    ///
503    /// # Examples
504    ///
505    /// Basic usage:
506    ///
507    /// ```
508    /// use heapless::String;
509    ///
510    /// let mut s: String<4> = String::new();
511    /// assert!(s.capacity() == 4);
512    /// ```
513    #[inline]
514    pub fn capacity(&self) -> usize {
515        self.vec.capacity()
516    }
517
518    /// Appends the given [`char`] to the end of this `String`.
519    ///
520    /// # Examples
521    ///
522    /// Basic usage:
523    ///
524    /// ```
525    /// use heapless::String;
526    ///
527    /// let mut s: String<8> = String::try_from("abc")?;
528    ///
529    /// s.push('1').unwrap();
530    /// s.push('2').unwrap();
531    /// s.push('3').unwrap();
532    ///
533    /// assert!("abc123" == s.as_str());
534    ///
535    /// assert_eq!("abc123", s);
536    /// # Ok::<(), heapless::CapacityError>(())
537    /// ```
538    #[inline]
539    pub fn push(&mut self, c: char) -> Result<(), CapacityError> {
540        match c.len_utf8() {
541            1 => self.vec.push(c as u8).map_err(|_| CapacityError),
542            _ => self
543                .vec
544                .extend_from_slice(c.encode_utf8(&mut [0; 4]).as_bytes()),
545        }
546    }
547
548    /// Shortens this `String` to the specified length.
549    ///
550    /// If `new_len` is greater than the string's current length, this has no
551    /// effect.
552    ///
553    /// Note that this method has no effect on the allocated capacity
554    /// of the string
555    ///
556    /// # Panics
557    ///
558    /// Panics if `new_len` does not lie on a [`char`] boundary.
559    ///
560    /// # Examples
561    ///
562    /// Basic usage:
563    ///
564    /// ```
565    /// use heapless::String;
566    ///
567    /// let mut s: String<8> = String::try_from("hello")?;
568    ///
569    /// s.truncate(2);
570    ///
571    /// assert_eq!("he", s);
572    /// # Ok::<(), heapless::CapacityError>(())
573    /// ```
574    #[inline]
575    pub fn truncate(&mut self, new_len: usize) {
576        if new_len <= self.len() {
577            assert!(self.is_char_boundary(new_len));
578            self.vec.truncate(new_len);
579        }
580    }
581
582    /// Removes the last character from the string buffer and returns it.
583    ///
584    /// Returns [`None`] if this `String` is empty.
585    ///
586    /// # Examples
587    ///
588    /// Basic usage:
589    ///
590    /// ```
591    /// use heapless::String;
592    ///
593    /// let mut s: String<8> = String::try_from("foo")?;
594    ///
595    /// assert_eq!(s.pop(), Some('o'));
596    /// assert_eq!(s.pop(), Some('o'));
597    /// assert_eq!(s.pop(), Some('f'));
598    ///
599    /// assert_eq!(s.pop(), None);
600    /// Ok::<(), heapless::CapacityError>(())
601    /// ```
602    pub fn pop(&mut self) -> Option<char> {
603        let ch = self.chars().next_back()?;
604
605        // pop bytes that correspond to `ch`
606        for _ in 0..ch.len_utf8() {
607            unsafe {
608                self.vec.pop_unchecked();
609            }
610        }
611
612        Some(ch)
613    }
614
615    /// Removes a [`char`] from this `String` at a byte position and returns it.
616    ///
617    /// Note: Because this shifts over the remaining elements, it has a
618    /// worst-case performance of *O*(n).
619    ///
620    /// # Panics
621    ///
622    /// Panics if `idx` is larger than or equal to the `String`'s length,
623    /// or if it does not lie on a [`char`] boundary.
624    ///
625    /// # Examples
626    ///
627    /// Basic usage:
628    ///
629    /// ```
630    /// use heapless::String;
631    ///
632    /// let mut s: String<8> = String::try_from("foo").unwrap();
633    ///
634    /// assert_eq!(s.remove(0), 'f');
635    /// assert_eq!(s.remove(1), 'o');
636    /// assert_eq!(s.remove(0), 'o');
637    /// ```
638    #[inline]
639    pub fn remove(&mut self, index: usize) -> char {
640        let ch = self[index..]
641            .chars()
642            .next()
643            .unwrap_or_else(|| panic!("cannot remove a char from the end of a string"));
644
645        let next = index + ch.len_utf8();
646        let len = self.len();
647        let ptr = self.vec.as_mut_ptr();
648        unsafe {
649            core::ptr::copy(ptr.add(next), ptr.add(index), len - next);
650            self.vec.set_len(len - (next - index));
651        }
652        ch
653    }
654
655    /// Truncates this `String`, removing all contents.
656    ///
657    /// While this means the `String` will have a length of zero, it does not
658    /// touch its capacity.
659    ///
660    /// # Examples
661    ///
662    /// Basic usage:
663    ///
664    /// ```
665    /// use heapless::String;
666    ///
667    /// let mut s: String<8> = String::try_from("foo")?;
668    ///
669    /// s.clear();
670    ///
671    /// assert!(s.is_empty());
672    /// assert_eq!(0, s.len());
673    /// assert_eq!(8, s.capacity());
674    /// Ok::<(), heapless::CapacityError>(())
675    /// ```
676    #[inline]
677    pub fn clear(&mut self) {
678        self.vec.clear();
679    }
680
681    /// Inserts a character into this `String` at a byte position.
682    ///
683    /// This is an *O*(*n*) operation as it requires copying every element in the
684    /// buffer.
685    ///
686    /// # Panics
687    ///
688    /// Panics if `idx` is larger than the `String`'s length, or if it does not
689    /// lie on a [`char`] boundary.
690    ///
691    /// # Examples
692    ///
693    /// ```
694    /// use heapless::String;
695    ///
696    /// let mut s: String<4> = String::new();
697    ///
698    /// s.insert(0, 'f').unwrap();
699    /// s.insert(1, 'o').unwrap();
700    /// s.insert(2, 'o').unwrap();
701    ///
702    /// assert_eq!("foo", s);
703    /// # Ok::<(), heapless::CapacityError>(())
704    /// ```
705    #[inline]
706    pub fn insert(&mut self, idx: usize, ch: char) -> Result<(), CapacityError> {
707        assert!(self.is_char_boundary(idx), "index must be a char boundary");
708
709        let len = self.len();
710        let ch_len = ch.len_utf8();
711
712        // Check if there is enough capacity
713        if len + ch_len > self.capacity() {
714            return Err(CapacityError);
715        }
716
717        // SAFETY: Move the bytes starting from `idx` to their new location `ch_len`
718        // bytes ahead. This is safe because we checked `len + ch_len` does not
719        // exceed the capacity and `idx` is a char boundary.
720        unsafe {
721            let ptr = self.vec.as_mut_ptr();
722            core::ptr::copy(ptr.add(idx), ptr.add(idx + ch_len), len - idx);
723        }
724
725        // SAFETY: Encode the character into the vacated region if `idx != len`,
726        // or into the uninitialized spare capacity otherwise. This is safe
727        // because `is_char_boundary` checks that `idx <= len`, and we checked that
728        // `(idx + ch_len)` does not exceed the capacity.
729        unsafe {
730            let buf = core::slice::from_raw_parts_mut(self.vec.as_mut_ptr().add(idx), ch_len);
731            ch.encode_utf8(buf);
732        }
733
734        // SAFETY: Update the length to include the newly added bytes. This is
735        // safe because we checked that `len + ch_len` does not exceed the capacity.
736        unsafe {
737            self.vec.set_len(len + ch_len);
738        }
739
740        Ok(())
741    }
742
743    /// Inserts a string slice into this `String` at a byte position.
744    ///
745    /// This is an *O*(*n*) operation as it requires copying every element in the
746    /// buffer.
747    ///
748    /// # Panics
749    ///
750    /// Panics if `idx` is larger than the `String`'s length, or if it does not
751    /// lie on a [`char`] boundary.
752    ///
753    /// # Examples
754    ///
755    /// ```
756    /// use heapless::String;
757    ///
758    /// let mut s: String<8> = String::try_from("bar")?;
759    ///
760    /// s.insert_str(0, "foo")?;
761    ///
762    /// assert_eq!("foobar", s);
763    /// # Ok::<(), heapless::CapacityError>(())
764    /// ```
765    #[inline]
766    pub fn insert_str(&mut self, idx: usize, string: &str) -> Result<(), CapacityError> {
767        assert!(self.is_char_boundary(idx), "index must be a char boundary");
768
769        let len = self.len();
770        let string_len = string.len();
771
772        // Check if there is enough capacity
773        if len + string_len > self.capacity() {
774            return Err(CapacityError);
775        }
776
777        // SAFETY: Move the bytes starting from `idx` to their new location
778        // `string_len` bytes ahead. This is safe because we checked there is
779        // sufficient capacity, and `idx` is a char boundary.
780        unsafe {
781            let ptr = self.vec.as_mut_ptr();
782            core::ptr::copy(ptr.add(idx), ptr.add(idx + string_len), len - idx);
783        }
784
785        // SAFETY: Copy the new string slice into the vacated region if `idx != len`,
786        // or into the uninitialized spare capacity otherwise. The borrow checker
787        // ensures that the source and destination do not overlap.
788        unsafe {
789            core::ptr::copy_nonoverlapping(
790                string.as_ptr(),
791                self.vec.as_mut_ptr().add(idx),
792                string_len,
793            );
794        }
795
796        // SAFETY: Update the length to include the newly added bytes.
797        unsafe {
798            self.vec.set_len(len + string_len);
799        }
800
801        Ok(())
802    }
803}
804
805impl<LenT: LenType, const N: usize> Default for String<N, LenT> {
806    fn default() -> Self {
807        Self::new()
808    }
809}
810
811impl<'a, LenT: LenType, const N: usize> TryFrom<&'a str> for String<N, LenT> {
812    type Error = CapacityError;
813
814    fn try_from(s: &'a str) -> Result<Self, Self::Error> {
815        let mut new = Self::new();
816        new.push_str(s)?;
817        Ok(new)
818    }
819}
820
821impl<LenT: LenType, const N: usize> str::FromStr for String<N, LenT> {
822    type Err = CapacityError;
823
824    fn from_str(s: &str) -> Result<Self, Self::Err> {
825        let mut new = Self::new();
826        new.push_str(s)?;
827        Ok(new)
828    }
829}
830
831impl<LenT: LenType, const N: usize> iter::FromIterator<char> for String<N, LenT> {
832    fn from_iter<T: IntoIterator<Item = char>>(iter: T) -> Self {
833        let mut new = Self::new();
834        for c in iter {
835            new.push(c).unwrap();
836        }
837        new
838    }
839}
840
841impl<'a, LenT: LenType, const N: usize> iter::FromIterator<&'a char> for String<N, LenT> {
842    fn from_iter<T: IntoIterator<Item = &'a char>>(iter: T) -> Self {
843        let mut new = Self::new();
844        for c in iter {
845            new.push(*c).unwrap();
846        }
847        new
848    }
849}
850
851impl<'a, LenT: LenType, const N: usize> iter::FromIterator<&'a str> for String<N, LenT> {
852    fn from_iter<T: IntoIterator<Item = &'a str>>(iter: T) -> Self {
853        let mut new = Self::new();
854        for c in iter {
855            new.push_str(c).unwrap();
856        }
857        new
858    }
859}
860
861impl<LenT: LenType, const N: usize> Clone for String<N, LenT> {
862    fn clone(&self) -> Self {
863        Self {
864            vec: self.vec.clone(),
865        }
866    }
867}
868
869impl<LenT: LenType, S: StringStorage + ?Sized> fmt::Debug for StringInner<LenT, S> {
870    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
871        <str as fmt::Debug>::fmt(self, f)
872    }
873}
874
875impl<LenT: LenType, S: StringStorage + ?Sized> fmt::Display for StringInner<LenT, S> {
876    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
877        <str as fmt::Display>::fmt(self, f)
878    }
879}
880
881impl<LenT: LenType, S: StringStorage + ?Sized> hash::Hash for StringInner<LenT, S> {
882    #[inline]
883    fn hash<H: hash::Hasher>(&self, hasher: &mut H) {
884        <str as hash::Hash>::hash(self, hasher);
885    }
886}
887
888impl<LenT: LenType, S: StringStorage + ?Sized> fmt::Write for StringInner<LenT, S> {
889    fn write_str(&mut self, s: &str) -> Result<(), fmt::Error> {
890        self.push_str(s).map_err(|_| fmt::Error)
891    }
892
893    fn write_char(&mut self, c: char) -> Result<(), fmt::Error> {
894        self.push(c).map_err(|_| fmt::Error)
895    }
896}
897
898impl<LenT: LenType, S: StringStorage + ?Sized> ops::Deref for StringInner<LenT, S> {
899    type Target = str;
900
901    fn deref(&self) -> &str {
902        self.as_str()
903    }
904}
905
906impl<LenT: LenType, S: StringStorage + ?Sized> ops::DerefMut for StringInner<LenT, S> {
907    fn deref_mut(&mut self) -> &mut str {
908        self.as_mut_str()
909    }
910}
911
912impl<LenT: LenType, S: StringStorage + ?Sized> borrow::Borrow<str> for StringInner<LenT, S> {
913    fn borrow(&self) -> &str {
914        self.as_str()
915    }
916}
917impl<LenT: LenType, S: StringStorage + ?Sized> borrow::BorrowMut<str> for StringInner<LenT, S> {
918    fn borrow_mut(&mut self) -> &mut str {
919        self.as_mut_str()
920    }
921}
922
923impl<LenT: LenType, S: StringStorage + ?Sized> AsRef<str> for StringInner<LenT, S> {
924    #[inline]
925    fn as_ref(&self) -> &str {
926        self
927    }
928}
929
930impl<LenT: LenType, S: StringStorage + ?Sized> AsRef<[u8]> for StringInner<LenT, S> {
931    #[inline]
932    fn as_ref(&self) -> &[u8] {
933        self.as_bytes()
934    }
935}
936
937impl<LenT1: LenType, LenT2: LenType, S1: StringStorage + ?Sized, S2: StringStorage + ?Sized>
938    PartialEq<StringInner<LenT1, S1>> for StringInner<LenT2, S2>
939{
940    fn eq(&self, rhs: &StringInner<LenT1, S1>) -> bool {
941        str::eq(&**self, &**rhs)
942    }
943}
944
945// String<N> == str
946impl<LenT: LenType, S: StringStorage + ?Sized> PartialEq<str> for StringInner<LenT, S> {
947    #[inline]
948    fn eq(&self, other: &str) -> bool {
949        str::eq(self, other)
950    }
951}
952
953// String<N> == &'str
954impl<LenT: LenType, S: StringStorage + ?Sized> PartialEq<&str> for StringInner<LenT, S> {
955    #[inline]
956    fn eq(&self, other: &&str) -> bool {
957        str::eq(self, &other[..])
958    }
959}
960
961// str == String<N>
962impl<LenT: LenType, S: StringStorage + ?Sized> PartialEq<StringInner<LenT, S>> for str {
963    #[inline]
964    fn eq(&self, other: &StringInner<LenT, S>) -> bool {
965        Self::eq(self, &other[..])
966    }
967}
968
969// &'str == String<N>
970impl<LenT: LenType, S: StringStorage + ?Sized> PartialEq<StringInner<LenT, S>> for &str {
971    #[inline]
972    fn eq(&self, other: &StringInner<LenT, S>) -> bool {
973        str::eq(self, &other[..])
974    }
975}
976
977impl<LenT: LenType, S: StringStorage + ?Sized> Eq for StringInner<LenT, S> {}
978
979impl<LenT1: LenType, LenT2: LenType, S1: StringStorage + ?Sized, S2: StringStorage + ?Sized>
980    PartialOrd<StringInner<LenT1, S1>> for StringInner<LenT2, S2>
981{
982    #[inline]
983    fn partial_cmp(&self, other: &StringInner<LenT1, S1>) -> Option<Ordering> {
984        PartialOrd::partial_cmp(&**self, &**other)
985    }
986}
987
988impl<LenT: LenType, S: StringStorage + ?Sized> Ord for StringInner<LenT, S> {
989    #[inline]
990    fn cmp(&self, other: &Self) -> Ordering {
991        Ord::cmp(&**self, &**other)
992    }
993}
994
995/// Equivalent to [`format`](https://doc.rust-lang.org/std/fmt/fn.format.html).
996///
997/// Please note that using [`format!`] might be preferable.
998///
999/// # Errors
1000///
1001/// There are two possible error cases. Both return the unit type [`core::fmt::Error`].
1002///
1003/// - In case the formatting exceeds the string's capacity. This error does not exist in
1004/// the standard library as the string would just grow.
1005/// - If a formatting trait implementation returns an error. The standard library panics
1006/// in this case.
1007///
1008/// [`format!`]: crate::format!
1009#[doc(hidden)]
1010pub fn format<const N: usize, LenT: LenType>(
1011    args: Arguments<'_>,
1012) -> Result<String<N, LenT>, fmt::Error> {
1013    fn format_inner<const N: usize, LenT: LenType>(
1014        args: Arguments<'_>,
1015    ) -> Result<String<N, LenT>, fmt::Error> {
1016        let mut output = String::new();
1017        output.write_fmt(args)?;
1018        Ok(output)
1019    }
1020
1021    args.as_str().map_or_else(
1022        || format_inner(args),
1023        |s| s.try_into().map_err(|_| fmt::Error),
1024    )
1025}
1026
1027/// Macro that creates a fixed capacity [`String`]. Equivalent to [`format!`](https://doc.rust-lang.org/std/macro.format.html).
1028///
1029/// The macro's arguments work in the same way as the regular macro.
1030///
1031/// It is possible to explicitly specify the capacity of the returned string as the first argument.
1032/// In this case it is necessary to disambiguate by separating the capacity with a semicolon.
1033///
1034/// # Errors
1035///
1036/// There are two possible error cases. Both return the unit type [`core::fmt::Error`].
1037///
1038/// - In case the formatting exceeds the string's capacity. This error does not exist in
1039///   the standard library as the string would just grow.
1040/// - If a formatting trait implementation returns an error. The standard library panics
1041///   in this case.
1042///
1043/// # Examples
1044///
1045/// ```
1046/// # fn main() -> Result<(), core::fmt::Error> {
1047/// use heapless::{format, String};
1048///
1049/// // Notice semicolon instead of comma!
1050/// format!(4; "test")?;
1051/// format!(15; "hello {}", "world!")?;
1052/// format!(20; "x = {}, y = {y}", 10, y = 30)?;
1053/// let (x, y) = (1, 2);
1054/// format!(12; "{x} + {y} = 3")?;
1055///
1056/// let implicit: String<10> = format!("speed = {}", 7)?;
1057/// # Ok(())
1058/// # }
1059/// ```
1060#[macro_export]
1061macro_rules! format {
1062    // Without semicolon as separator to disambiguate between arms, Rust just
1063    // chooses the first so that the format string would land in $max.
1064    ($max:expr; $lenT:path; $($arg:tt)*) => {{
1065        let res = $crate::_export::format::<$max, $lenT>(core::format_args!($($arg)*));
1066        res
1067    }};
1068    ($max:expr; $($arg:tt)*) => {{
1069        let res = $crate::_export::format::<$max, usize>(core::format_args!($($arg)*));
1070        res
1071    }};
1072    ($($arg:tt)*) => {{
1073        let res = $crate::_export::format(core::format_args!($($arg)*));
1074        res
1075    }};
1076}
1077
1078macro_rules! impl_try_from_num {
1079    ($num:ty, $size:expr) => {
1080        impl<LenT: LenType, const N: usize> core::convert::TryFrom<$num> for String<N, LenT> {
1081            type Error = ();
1082            fn try_from(s: $num) -> Result<Self, Self::Error> {
1083                let mut new = String::new();
1084                write!(&mut new, "{}", s).map_err(|_| ())?;
1085                Ok(new)
1086            }
1087        }
1088    };
1089}
1090
1091impl_try_from_num!(i8, 4);
1092impl_try_from_num!(i16, 6);
1093impl_try_from_num!(i32, 11);
1094impl_try_from_num!(i64, 20);
1095
1096impl_try_from_num!(u8, 3);
1097impl_try_from_num!(u16, 5);
1098impl_try_from_num!(u32, 10);
1099impl_try_from_num!(u64, 20);
1100
1101#[cfg(test)]
1102mod tests {
1103    use crate::{CapacityError, String, Vec};
1104
1105    #[test]
1106    fn static_new() {
1107        static mut _S: String<8> = String::new();
1108    }
1109
1110    #[test]
1111    fn clone() {
1112        let s1: String<20> = String::try_from("abcd").unwrap();
1113        let mut s2 = s1.clone();
1114        s2.push_str(" efgh").unwrap();
1115
1116        assert_eq!(s1, "abcd");
1117        assert_eq!(s2, "abcd efgh");
1118    }
1119
1120    #[test]
1121    fn cmp() {
1122        let s1: String<4> = String::try_from("abcd").unwrap();
1123        let s2: String<4> = String::try_from("zzzz").unwrap();
1124
1125        assert!(s1 < s2);
1126    }
1127
1128    #[test]
1129    fn cmp_heterogenous_size() {
1130        let s1: String<4> = String::try_from("abcd").unwrap();
1131        let s2: String<8> = String::try_from("zzzz").unwrap();
1132
1133        assert!(s1 < s2);
1134    }
1135
1136    #[test]
1137    fn debug() {
1138        use core::fmt::Write;
1139
1140        let s: String<8> = String::try_from("abcd").unwrap();
1141        let mut std_s = std::string::String::new();
1142        write!(std_s, "{s:?}").unwrap();
1143        assert_eq!("\"abcd\"", std_s);
1144    }
1145
1146    #[test]
1147    fn display() {
1148        use core::fmt::Write;
1149
1150        let s: String<8> = String::try_from("abcd").unwrap();
1151        let mut std_s = std::string::String::new();
1152        write!(std_s, "{s}").unwrap();
1153        assert_eq!("abcd", std_s);
1154    }
1155
1156    #[test]
1157    fn empty() {
1158        let s: String<4> = String::new();
1159        assert!(s.capacity() == 4);
1160        assert_eq!(s, "");
1161        assert_eq!(s.len(), 0);
1162        assert_ne!(s.len(), 4);
1163    }
1164
1165    #[test]
1166    fn try_from() {
1167        let s: String<4> = String::try_from("123").unwrap();
1168        assert!(s.len() == 3);
1169        assert_eq!(s, "123");
1170
1171        let _: CapacityError = String::<2>::try_from("123").unwrap_err();
1172    }
1173
1174    #[test]
1175    fn from_str() {
1176        use core::str::FromStr;
1177
1178        let s: String<4> = String::<4>::from_str("123").unwrap();
1179        assert!(s.len() == 3);
1180        assert_eq!(s, "123");
1181
1182        let _: CapacityError = String::<2>::from_str("123").unwrap_err();
1183    }
1184
1185    #[test]
1186    fn from_iter() {
1187        let mut v: Vec<char, 5> = Vec::new();
1188        v.push('h').unwrap();
1189        v.push('e').unwrap();
1190        v.push('l').unwrap();
1191        v.push('l').unwrap();
1192        v.push('o').unwrap();
1193        let string1: String<5> = v.iter().collect(); //&char
1194        let string2: String<5> = "hello".chars().collect(); //char
1195        assert_eq!(string1, "hello");
1196        assert_eq!(string2, "hello");
1197    }
1198
1199    #[test]
1200    #[should_panic]
1201    fn from_panic() {
1202        let _: String<4> = String::try_from("12345").unwrap();
1203    }
1204
1205    #[test]
1206    fn try_from_num() {
1207        let v: String<20> = String::try_from(18446744073709551615_u64).unwrap();
1208        assert_eq!(v, "18446744073709551615");
1209
1210        let _: () = String::<2>::try_from(18446744073709551615_u64).unwrap_err();
1211    }
1212
1213    #[test]
1214    fn into_bytes() {
1215        let s: String<4> = String::try_from("ab").unwrap();
1216        let b: Vec<u8, 4> = s.into_bytes();
1217        assert_eq!(b.len(), 2);
1218        assert_eq!(b"ab", &b[..]);
1219    }
1220
1221    #[test]
1222    fn as_str() {
1223        let s: String<4> = String::try_from("ab").unwrap();
1224
1225        assert_eq!(s.as_str(), "ab");
1226        // should be moved to fail test
1227        //    let _s = s.as_str();
1228        // s.push('c'); // <- cannot borrow `s` as mutable because it is also borrowed as immutable
1229    }
1230
1231    #[test]
1232    fn as_mut_str() {
1233        let mut s: String<4> = String::try_from("ab").unwrap();
1234        let s = s.as_mut_str();
1235        s.make_ascii_uppercase();
1236        assert_eq!(s, "AB");
1237    }
1238
1239    #[test]
1240    fn push_str() {
1241        let mut s: String<8> = String::try_from("foo").unwrap();
1242        assert!(s.push_str("bar").is_ok());
1243        assert_eq!("foobar", s);
1244        assert_eq!(s, "foobar");
1245        assert!(s.push_str("tender").is_err());
1246        assert_eq!("foobar", s);
1247        assert_eq!(s, "foobar");
1248    }
1249
1250    #[test]
1251    fn push() {
1252        let mut s: String<6> = String::try_from("abc").unwrap();
1253        assert!(s.push('1').is_ok());
1254        assert!(s.push('2').is_ok());
1255        assert!(s.push('3').is_ok());
1256        assert!(s.push('4').is_err());
1257        assert!("abc123" == s.as_str());
1258    }
1259
1260    #[test]
1261    fn as_bytes() {
1262        let s: String<8> = String::try_from("hello").unwrap();
1263        assert_eq!(&[104, 101, 108, 108, 111], s.as_bytes());
1264    }
1265
1266    #[test]
1267    fn truncate() {
1268        let mut s: String<8> = String::try_from("hello").unwrap();
1269        s.truncate(6);
1270        assert_eq!(s.len(), 5);
1271        s.truncate(2);
1272        assert_eq!(s.len(), 2);
1273        assert_eq!("he", s);
1274        assert_eq!(s, "he");
1275    }
1276
1277    #[test]
1278    fn pop() {
1279        let mut s: String<8> = String::try_from("foo").unwrap();
1280        assert_eq!(s.pop(), Some('o'));
1281        assert_eq!(s.pop(), Some('o'));
1282        assert_eq!(s.pop(), Some('f'));
1283        assert_eq!(s.pop(), None);
1284    }
1285
1286    #[test]
1287    fn pop_uenc() {
1288        let mut s: String<8> = String::try_from("é").unwrap();
1289        assert_eq!(s.len(), 3);
1290        match s.pop() {
1291            Some(c) => {
1292                assert_eq!(s.len(), 1);
1293                assert_eq!(c, '\u{0301}'); // acute accent of e
1294            }
1295            None => panic!(),
1296        };
1297    }
1298
1299    #[test]
1300    fn is_empty() {
1301        let mut v: String<8> = String::new();
1302        assert!(v.is_empty());
1303        let _ = v.push('a');
1304        assert!(!v.is_empty());
1305    }
1306
1307    #[test]
1308    fn clear() {
1309        let mut s: String<8> = String::try_from("foo").unwrap();
1310        s.clear();
1311        assert!(s.is_empty());
1312        assert_eq!(0, s.len());
1313        assert_eq!(8, s.capacity());
1314    }
1315
1316    #[test]
1317    fn remove() {
1318        let mut s: String<8> = String::try_from("foo").unwrap();
1319        assert_eq!(s.remove(0), 'f');
1320        assert_eq!(s.as_str(), "oo");
1321    }
1322
1323    #[test]
1324    fn remove_uenc() {
1325        let mut s: String<8> = String::try_from("ĝėēƶ").unwrap();
1326        assert_eq!(s.remove(2), 'ė');
1327        assert_eq!(s.remove(2), 'ē');
1328        assert_eq!(s.remove(2), 'ƶ');
1329        assert_eq!(s.as_str(), "ĝ");
1330    }
1331
1332    #[test]
1333    fn remove_uenc_combo_characters() {
1334        let mut s: String<8> = String::try_from("héy").unwrap();
1335        assert_eq!(s.remove(2), '\u{0301}');
1336        assert_eq!(s.as_str(), "hey");
1337    }
1338
1339    #[test]
1340    fn format() {
1341        let number = 5;
1342        let float = 3.12;
1343        let formatted = format!(15; "{:0>3} plus {float}", number).unwrap();
1344        assert_eq!(formatted, "005 plus 3.12");
1345    }
1346    #[test]
1347    fn format_inferred_capacity() {
1348        let number = 5;
1349        let float = 3.12;
1350        let formatted: String<15> = format!("{:0>3} plus {float}", number).unwrap();
1351        assert_eq!(formatted, "005 plus 3.12");
1352    }
1353
1354    #[test]
1355    fn format_overflow() {
1356        let i = 1234567;
1357        let formatted = format!(4; "13{}", i);
1358        assert_eq!(formatted, Err(core::fmt::Error));
1359    }
1360
1361    #[test]
1362    fn format_plain_string_overflow() {
1363        let formatted = format!(2; "123");
1364        assert_eq!(formatted, Err(core::fmt::Error));
1365    }
1366
1367    #[test]
1368    fn insert() {
1369        let mut s: String<6> = String::try_from("123").unwrap();
1370        assert!(s.insert(0, 'a').is_ok());
1371        assert_eq!(s, "a123");
1372
1373        assert!(s.insert(2, 'b').is_ok());
1374        assert_eq!(s, "a1b23");
1375
1376        assert!(s.insert(s.len(), '4').is_ok());
1377        assert_eq!(s, "a1b234");
1378
1379        assert_eq!(s.len(), 6);
1380        assert!(s.insert(0, 'd').is_err());
1381        assert_eq!(s, "a1b234");
1382    }
1383
1384    #[test]
1385    fn insert_unicode() {
1386        let mut s: String<21> = String::try_from("ĝėēƶ").unwrap();
1387        let idx = s.find("ė").unwrap();
1388
1389        assert!(s.insert(idx, '🦀').is_ok());
1390        assert_eq!(s, "ĝ🦀ėēƶ");
1391
1392        s.insert(s.len(), '🦀').unwrap();
1393        assert_eq!(s, "ĝ🦀ėēƶ🦀");
1394
1395        s.insert(0, '🦀').unwrap();
1396        assert_eq!(s, "🦀ĝ🦀ėēƶ🦀");
1397
1398        assert_eq!(s.len(), 20);
1399        assert_eq!('ƶ'.len_utf8(), 2);
1400        assert!(s.insert(0, 'ƶ').is_err());
1401        assert_eq!(s, "🦀ĝ🦀ėēƶ🦀");
1402    }
1403
1404    #[test]
1405    #[should_panic = "index must be a char boundary"]
1406    fn insert_at_non_char_boundary_panics() {
1407        let mut s: String<8> = String::try_from("é").unwrap();
1408        _ = s.insert(1, 'a');
1409    }
1410
1411    #[test]
1412    #[should_panic = "index must be a char boundary"]
1413    fn insert_beyond_length_panics() {
1414        let mut s: String<8> = String::try_from("a").unwrap();
1415        _ = s.insert(2, 'a');
1416    }
1417
1418    #[test]
1419    fn insert_str() {
1420        let mut s: String<14> = String::try_from("bar").unwrap();
1421        assert!(s.insert_str(0, "foo").is_ok());
1422        assert_eq!(s, "foobar");
1423
1424        assert!(s.insert_str(3, "baz").is_ok());
1425        assert_eq!(s, "foobazbar");
1426
1427        assert!(s.insert_str(s.len(), "end").is_ok());
1428        assert_eq!(s, "foobazbarend");
1429
1430        assert_eq!(s.len(), 12);
1431        assert!(s.insert_str(0, "def").is_err());
1432        assert_eq!(s, "foobazbarend");
1433    }
1434
1435    #[test]
1436    fn insert_str_unicode() {
1437        let mut s: String<20> = String::try_from("Héllô").unwrap();
1438        let idx = s.find("lô").unwrap();
1439
1440        assert!(s.insert_str(idx, "p, í'm ").is_ok());
1441        assert_eq!(s, "Hélp, í'm lô");
1442
1443        assert!(s.insert_str(s.len(), "st").is_ok());
1444        assert_eq!(s, "Hélp, í'm lôst");
1445
1446        assert_eq!(s.len(), 17);
1447        assert_eq!("🦀".len(), 4);
1448        assert!(s.insert_str(0, "🦀").is_err());
1449        assert_eq!(s, "Hélp, í'm lôst");
1450    }
1451
1452    #[test]
1453    #[should_panic = "index must be a char boundary"]
1454    fn insert_str_at_non_char_boundary_panics() {
1455        let mut s: String<8> = String::try_from("é").unwrap();
1456        _ = s.insert_str(1, "a");
1457    }
1458
1459    #[test]
1460    #[should_panic = "index must be a char boundary"]
1461    fn insert_str_beyond_length_panics() {
1462        let mut s: String<8> = String::try_from("a").unwrap();
1463        _ = s.insert_str(2, "a");
1464    }
1465}