Skip to main content

stack_buf/
str.rs

1use crate::StackVec;
2#[cfg(feature = "std")]
3use std::borrow::Cow;
4use std::borrow::{Borrow, BorrowMut};
5use std::cmp::Ordering;
6use std::hash::{Hash, Hasher};
7use std::iter::FromIterator;
8use std::ops::{Add, AddAssign, Deref, DerefMut};
9use std::str::{FromStr, Utf8Error};
10use std::{fmt, ptr, str};
11
12/// A possible error value when converting a `StackStr` from a UTF-8 byte vector.
13///
14/// This type is the error type for the [`from_utf8`] method on [`StackStr`]. It
15/// is designed in such a way to carefully avoid reallocations: the
16/// [`into_bytes`] method will give back the byte vector that was used in the
17/// conversion attempt.
18///
19/// [`from_utf8`]: StackStr::from_utf8
20/// [`into_bytes`]: FromUtf8Error::into_bytes
21///
22/// # Examples
23///
24/// ```
25/// use stack_buf::{StackStr, stack_vec};
26///
27/// // some invalid bytes, in a vector
28/// let bytes = stack_vec![0, 159];
29///
30/// let value = StackStr::<2>::from_utf8(bytes);
31///
32/// assert!(value.is_err());
33/// assert_eq!(stack_vec![0, 159], value.unwrap_err().into_bytes());
34/// ```
35#[cfg_attr(docsrs, doc(cfg(feature = "str")))]
36#[derive(Debug, Clone, PartialEq, Eq)]
37pub struct FromUtf8Error<const N: usize> {
38    bytes: StackVec<u8, N>,
39    error: Utf8Error,
40}
41
42#[cfg(feature = "std")]
43#[cfg_attr(docsrs, doc(cfg(all(feature = "std", feature = "str"))))]
44impl<const N: usize> std::error::Error for FromUtf8Error<N> {}
45
46impl<const N: usize> fmt::Display for FromUtf8Error<N> {
47    #[inline]
48    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
49        fmt::Display::fmt(&self.error, f)
50    }
51}
52
53impl<const N: usize> FromUtf8Error<N> {
54    /// Returns a slice of [`u8`]s bytes that were attempted to convert to a `StackStr`.
55    ///
56    /// # Examples
57    ///
58    /// ```
59    /// use stack_buf::{StackStr, stack_vec};
60    ///
61    /// // some invalid bytes, in a vector
62    /// let bytes = stack_vec![0, 159];
63    ///
64    /// let value = StackStr::<2>::from_utf8(bytes);
65    ///
66    /// assert_eq!(&[0, 159], value.unwrap_err().as_bytes());
67    /// ```
68    #[inline]
69    pub const fn as_bytes(&self) -> &[u8] {
70        self.bytes.as_slice()
71    }
72
73    /// Returns the bytes that were attempted to convert to a `StackStr`.
74    ///
75    /// # Examples
76    ///
77    /// ```
78    /// use stack_buf::{stack_vec, StackStr};
79    ///
80    /// // some invalid bytes, in a vector
81    /// let bytes = stack_vec![0, 159];
82    ///
83    /// let value = StackStr::<2>::from_utf8(bytes);
84    ///
85    /// assert_eq!(stack_vec![0, 159], value.unwrap_err().into_bytes());
86    /// ```
87    #[inline]
88    pub fn into_bytes(self) -> StackVec<u8, N> {
89        self.bytes
90    }
91
92    /// Fetch a `Utf8Error` to get more details about the conversion failure.
93    ///
94    /// # Examples
95    ///
96    /// ```
97    /// use stack_buf::{StackStr, stack_vec};
98    ///
99    /// // some invalid bytes, in a vector
100    /// let bytes = stack_vec![0, 159];
101    ///
102    /// let error = StackStr::<2>::from_utf8(bytes).unwrap_err().utf8_error();
103    ///
104    /// // the first byte is invalid here
105    /// assert_eq!(1, error.valid_up_to());
106    /// ```
107    #[inline]
108    pub const fn utf8_error(&self) -> Utf8Error {
109        self.error
110    }
111}
112
113/// A string with a fixed capacity and stored on the stack.
114///
115/// The `StackStr` is a string backed by a fixed size `StackVec`. It keeps track
116/// of its length, and is parameterized by `N` for the maximum capacity.
117///
118/// `N` is of type `usize` but is range limited to `u32::MAX`; attempting to create
119/// string with larger size will panic.
120#[cfg_attr(docsrs, doc(cfg(feature = "str")))]
121pub struct StackStr<const N: usize> {
122    vec: StackVec<u8, N>,
123}
124
125// Keeps StackStr valid if the retain predicate panics after moving bytes.
126struct RetainGuard<'a, const N: usize> {
127    vec: &'a mut StackVec<u8, N>,
128    len: usize,
129}
130
131impl<const N: usize> Drop for RetainGuard<'_, N> {
132    fn drop(&mut self) {
133        unsafe { self.vec.set_len(self.len) };
134    }
135}
136
137impl<const N: usize> StackStr<N> {
138    /// Creates a new empty `StackStr`.
139    ///
140    /// The maximum capacity is given by the generic parameter `N`.
141    ///
142    /// # Examples
143    ///
144    /// ```
145    /// use stack_buf::StackStr;
146    ///
147    /// let s: StackStr<3> = StackStr::new();
148    /// ```
149    #[inline]
150    pub const fn new() -> Self {
151        StackStr {
152            vec: StackVec::new(),
153        }
154    }
155
156    /// Converts a vector of bytes to a `StackStr`.
157    ///
158    /// If you are sure that the byte slice is valid UTF-8, and you don't want
159    /// to incur the overhead of the validity check, there is an unsafe version
160    /// of this function, [`from_utf8_unchecked`], which has the same behavior
161    /// but skips the check.
162    ///
163    /// The inverse of this method is [`into_bytes`].
164    ///
165    /// # Errors
166    ///
167    /// Returns [`Err`] if the slice is not UTF-8 with a description as to why the
168    /// provided bytes are not UTF-8. The vector you moved in is also included.
169    ///
170    /// # Examples
171    ///
172    /// ```
173    /// use stack_buf::{StackStr, stack_vec};
174    ///
175    /// // some bytes, in a vector
176    /// let sparkle_heart = stack_vec![240, 159, 146, 150];
177    ///
178    /// // We know these bytes are valid, so we'll use `unwrap()`.
179    /// let sparkle_heart = StackStr::from_utf8(sparkle_heart).unwrap();
180    ///
181    /// assert_eq!("💖", sparkle_heart);
182    /// ```
183    ///
184    /// Incorrect bytes:
185    ///
186    /// ```
187    /// use stack_buf::{StackStr, stack_vec};
188    ///
189    /// // some invalid bytes, in a vector
190    /// let sparkle_heart = stack_vec![0, 159, 146, 150];
191    ///
192    /// assert!(StackStr::from_utf8(sparkle_heart).is_err());
193    /// ```
194    ///
195    /// See the docs for [`FromUtf8Error`] for more details on what you can do
196    /// with this error.
197    ///
198    /// [`from_utf8_unchecked`]: StackStr::from_utf8_unchecked
199    /// [`into_bytes`]: StackStr::into_bytes
200    #[inline]
201    pub fn from_utf8(vec: StackVec<u8, N>) -> Result<Self, FromUtf8Error<N>> {
202        match str::from_utf8(&vec) {
203            Ok(..) => Ok(StackStr { vec }),
204            Err(e) => Err(FromUtf8Error {
205                bytes: vec,
206                error: e,
207            }),
208        }
209    }
210
211    /// Converts a vector of bytes to a `StackStr` without checking that the
212    /// string contains valid UTF-8.
213    ///
214    /// See the safe version, [`from_utf8`], for more details.
215    ///
216    /// [`from_utf8`]: StackStr::from_utf8
217    ///
218    /// # Safety
219    ///
220    /// This function is unsafe because it does not check that the bytes passed
221    /// to it are valid UTF-8. If this constraint is violated, it may cause
222    /// memory unsafety issues with future users of the `StackStr`, as the rest of
223    /// the library assumes that `StackStr`s are valid UTF-8.
224    ///
225    /// # Examples
226    ///
227    /// ```
228    /// use stack_buf::{StackStr, stack_vec};
229    ///
230    /// // some bytes, in a vector
231    /// let sparkle_heart = stack_vec![240, 159, 146, 150];
232    ///
233    /// let sparkle_heart = unsafe {
234    ///     StackStr::from_utf8_unchecked(sparkle_heart)
235    /// };
236    ///
237    /// assert_eq!("💖", sparkle_heart);
238    /// ```
239    #[inline]
240    pub const unsafe fn from_utf8_unchecked(bytes: StackVec<u8, N>) -> Self {
241        StackStr { vec: bytes }
242    }
243
244    /// Converts a `StackStr` into a byte vector.
245    ///
246    /// This consumes the `StackStr`, so we do not need to copy its contents.
247    ///
248    /// # Examples
249    ///
250    /// ```
251    /// use stack_buf::StackStr;
252    ///
253    /// let s = StackStr::<5>::from("hello");
254    /// let bytes = s.into_bytes();
255    ///
256    /// assert_eq!(&[104, 101, 108, 108, 111][..], &bytes[..]);
257    /// ```
258    #[inline]
259    pub fn into_bytes(self) -> StackVec<u8, N> {
260        self.vec
261    }
262
263    /// Returns the length of this `StackStr`, in bytes, not [`char`]s or
264    /// graphemes. In other words, it may not be what a human considers the
265    /// length of the string.
266    #[inline]
267    pub const fn len(&self) -> usize {
268        self.vec.len()
269    }
270
271    /// Returns whether the string is empty.
272    #[inline]
273    pub const fn is_empty(&self) -> bool {
274        self.len() == 0
275    }
276
277    /// Returns `true` if the `StackStr` is completely filled to its capacity, false otherwise.
278    ///
279    /// # Examples
280    ///
281    /// ```
282    /// use stack_buf::StackStr;
283    ///
284    /// let mut s = StackStr::<1>::new();
285    /// assert!(!s.is_full());
286    /// s.push('a');
287    /// assert!(s.is_full());
288    /// ```
289    #[inline]
290    pub const fn is_full(&self) -> bool {
291        self.len() == self.capacity()
292    }
293
294    /// Returns this `StackStr`'s capacity, in bytes.
295    ///
296    /// # Examples
297    ///
298    /// ```
299    /// use stack_buf::StackStr;
300    ///
301    /// let s = StackStr::<10>::new();
302    ///
303    /// assert_eq!(s.capacity(), 10);
304    /// ```
305    #[inline]
306    pub const fn capacity(&self) -> usize {
307        self.vec.capacity()
308    }
309
310    /// Returns the capacity left in the `StackStr`.
311    ///
312    /// # Examples
313    ///
314    /// ```
315    /// use stack_buf::StackStr;
316    ///
317    /// let mut s = StackStr::<3>::from("123");
318    /// s.pop();
319    /// assert_eq!(s.remaining_capacity(), 1);
320    /// ```
321    #[inline]
322    pub const fn remaining_capacity(&self) -> usize {
323        self.capacity() - self.len()
324    }
325
326    /// Sets the `StackStr`’s length without dropping or moving out elements
327    ///
328    /// # Safety
329    /// This method is `unsafe` because it changes the notion of the
330    /// number of “valid” elements in the vector.
331    ///
332    /// This method uses *debug assertions* to check that `length` is
333    /// not greater than the capacity.
334    #[inline]
335    pub const unsafe fn set_len(&mut self, length: usize) {
336        unsafe { self.vec.set_len(length) };
337    }
338
339    /// Extracts a string slice containing the entire `StackStr`.
340    ///
341    /// # Examples
342    ///
343    /// ```
344    /// use stack_buf::StackStr;
345    ///
346    /// let s = StackStr::<5>::from("foo");
347    ///
348    /// assert_eq!("foo", s.as_str());
349    /// ```
350    #[inline]
351    pub const fn as_str(&self) -> &str {
352        unsafe { str::from_utf8_unchecked(self.vec.as_slice()) }
353    }
354
355    /// Converts a `StackStr` into a mutable string slice.
356    ///
357    /// # Examples
358    ///
359    /// ```
360    /// use stack_buf::StackStr;
361    ///
362    /// let mut s = StackStr::<10>::from("foobar");
363    /// let s_mut_str = s.as_mut_str();
364    ///
365    /// s_mut_str.make_ascii_uppercase();
366    ///
367    /// assert_eq!("FOOBAR", s_mut_str);
368    /// ```
369    #[inline]
370    pub const fn as_mut_str(&mut self) -> &mut str {
371        unsafe { str::from_utf8_unchecked_mut(self.vec.as_mut_slice()) }
372    }
373
374    /// Returns a raw pointer to the `StackStr`'s buffer.
375    #[inline(always)]
376    pub const fn as_ptr(&self) -> *const u8 {
377        self.vec.as_ptr() as _
378    }
379
380    /// Returns a raw mutable pointer to the `StackStr`'s buffer.
381    #[inline(always)]
382    pub const fn as_mut_ptr(&mut self) -> *mut u8 {
383        self.vec.as_mut_ptr() as _
384    }
385
386    /// Returns a byte slice of this `StackStr`'s contents.
387    ///
388    /// The inverse of this method is [`from_utf8`].
389    ///
390    /// [`from_utf8`]: StackStr::from_utf8
391    ///
392    /// # Examples
393    ///
394    /// ```
395    /// use stack_buf::StackStr;
396    ///
397    /// let s = StackStr::<5>::from("hello");
398    ///
399    /// assert_eq!(&[104, 101, 108, 108, 111], s.as_bytes());
400    /// ```
401    #[inline]
402    pub const fn as_bytes(&self) -> &[u8] {
403        self.vec.as_slice()
404    }
405
406    /// Returns a mutable reference to the contents of this `StackStr`.
407    ///
408    /// # Safety
409    ///
410    /// This function is unsafe because it does not check that the bytes passed
411    /// to it are valid UTF-8. If this constraint is violated, it may cause
412    /// memory unsafety issues with future users of the `StackStr`, as the rest of
413    /// the standard library assumes that `StackStr`s are valid UTF-8.
414    ///
415    /// # Examples
416    ///
417    /// ```
418    /// use stack_buf::StackStr;
419    ///
420    /// let mut s = StackStr::<5>::from("hello");
421    ///
422    /// unsafe {
423    ///     let vec = s.as_mut_vec();
424    ///     assert_eq!(&[104, 101, 108, 108, 111][..], &vec[..]);
425    ///
426    ///     vec.reverse();
427    /// }
428    /// assert_eq!(s, "olleh");
429    /// ```
430    #[inline]
431    pub const unsafe fn as_mut_vec(&mut self) -> &mut StackVec<u8, N> {
432        &mut self.vec
433    }
434
435    /// Appends a given string slice onto the end of this `StackStr`.
436    ///
437    /// # Examples
438    ///
439    /// ```
440    /// use stack_buf::StackStr;
441    ///
442    /// let mut s = StackStr::<10>::from("foo");
443    ///
444    /// s.push_str("bar");
445    ///
446    /// assert_eq!("foobar", s);
447    /// ```
448    #[inline]
449    pub fn push_str(&mut self, string: &str) {
450        self.vec.copy_from_slice(string.as_bytes())
451    }
452
453    /// Appends the given [`char`] to the end of this `StackStr`.
454    ///
455    /// # Examples
456    ///
457    /// ```
458    /// use stack_buf::StackStr;
459    ///
460    /// let mut s = StackStr::<6>::from("abc");
461    ///
462    /// s.push('1');
463    /// s.push('2');
464    /// s.push('3');
465    ///
466    /// assert_eq!("abc123", s);
467    /// ```
468    #[inline]
469    pub fn push(&mut self, ch: char) {
470        match ch.len_utf8() {
471            1 => self.vec.push(ch as u8),
472            _ => self
473                .vec
474                .copy_from_slice(ch.encode_utf8(&mut [0; 4]).as_bytes()),
475        }
476    }
477
478    /// Removes the last character from the string buffer and returns it.
479    ///
480    /// Returns [`None`] if this `StackStr` is empty.
481    ///
482    /// # Examples
483    ///
484    /// ```
485    /// use stack_buf::StackStr;
486    ///
487    /// let mut s = StackStr::<3>::from("foo");
488    ///
489    /// assert_eq!(s.pop(), Some('o'));
490    /// assert_eq!(s.pop(), Some('o'));
491    /// assert_eq!(s.pop(), Some('f'));
492    ///
493    /// assert_eq!(s.pop(), None);
494    /// ```
495    #[inline]
496    pub fn pop(&mut self) -> Option<char> {
497        let ch = self.chars().next_back()?;
498        let new_len = self.len() - ch.len_utf8();
499        unsafe {
500            self.vec.set_len(new_len);
501        }
502        Some(ch)
503    }
504
505    /// Shortens this `StackStr` to the specified length.
506    ///
507    /// If `new_len` is greater than the string's current length, this has no
508    /// effect.
509    ///
510    /// # Panics
511    ///
512    /// Panics if `new_len` does not lie on a [`char`] boundary.
513    ///
514    /// # Examples
515    ///
516    /// ```
517    /// use stack_buf::StackStr;
518    ///
519    /// let mut s = StackStr::<5>::from("hello");
520    ///
521    /// s.truncate(2);
522    ///
523    /// assert_eq!("he", s);
524    /// ```
525    #[inline]
526    pub fn truncate(&mut self, new_len: usize) {
527        if new_len <= self.len() {
528            assert!(self.is_char_boundary(new_len));
529            unsafe { self.set_len(new_len) }
530        }
531    }
532
533    /// Truncates this `StackStr`, removing all contents.
534    ///
535    /// While this means the `StackStr` will have a length of zero, it does not
536    /// touch its capacity.
537    ///
538    /// # Examples
539    ///
540    /// ```
541    /// use stack_buf::StackStr;
542    ///
543    /// let mut s = StackStr::<3>::from("foo");
544    ///
545    /// s.clear();
546    ///
547    /// assert!(s.is_empty());
548    /// assert_eq!(0, s.len());
549    /// assert_eq!(3, s.capacity());
550    /// ```
551    #[inline]
552    pub fn clear(&mut self) {
553        unsafe {
554            self.set_len(0);
555        }
556    }
557
558    /// Retains only the characters specified by the predicate.
559    ///
560    /// In other words, remove all characters `c` such that `f(c)` returns `false`.
561    /// This method operates in place, visiting each character exactly once in the
562    /// original order, and preserves the order of the retained characters.
563    ///
564    /// # Examples
565    ///
566    /// ```
567    /// use stack_buf::StackStr;
568    ///
569    /// let mut s = StackStr::<10>::from("f_o_ob_ar");
570    ///
571    /// s.retain(|c| c != '_');
572    ///
573    /// assert_eq!(s, "foobar");
574    /// ```
575    ///
576    /// The exact order may be useful for tracking external state, like an index.
577    ///
578    /// ```
579    /// use stack_buf::StackStr;
580    ///
581    /// let mut s = StackStr::<5>::from("abcde");
582    /// let keep = [false, true, true, false, true];
583    /// let mut i = 0;
584    /// s.retain(|_| (keep[i], i += 1).0);
585    /// assert_eq!(s, "bce");
586    /// ```
587    #[inline]
588    pub fn retain<F>(&mut self, mut f: F)
589    where
590        F: FnMut(char) -> bool,
591    {
592        let len = self.len();
593        let mut del_bytes = 0;
594        let mut idx = 0;
595        let mut guard = RetainGuard {
596            vec: &mut self.vec,
597            len: 0,
598        };
599
600        while idx < len {
601            // The guard has shortened vec, so read the original initialized bytes directly.
602            let bytes =
603                unsafe { std::slice::from_raw_parts(guard.vec.as_ptr().add(idx), len - idx) };
604            let ch = unsafe { str::from_utf8_unchecked(bytes) }
605                .chars()
606                .next()
607                .unwrap();
608            let ch_len = ch.len_utf8();
609
610            if !f(ch) {
611                del_bytes += ch_len;
612            } else if del_bytes > 0 {
613                unsafe {
614                    ptr::copy(
615                        guard.vec.as_ptr().add(idx),
616                        guard.vec.as_mut_ptr().add(idx - del_bytes),
617                        ch_len,
618                    );
619                }
620            }
621
622            guard.len = idx + ch_len - del_bytes;
623
624            // Point idx to the next char
625            idx += ch_len;
626        }
627    }
628
629    /// Inserts a character into this `StackStr` at a byte position.
630    ///
631    /// This is an *O*(*n*) operation as it requires copying every element in the
632    /// buffer.
633    ///
634    /// # Panics
635    ///
636    /// Panics if `idx` is larger than the `StackStr`'s length, or if it does not
637    /// lie on a [`char`] boundary.
638    ///
639    /// # Examples
640    ///
641    /// ```
642    /// use stack_buf::StackStr;
643    ///
644    /// let mut s = StackStr::<3>::new();
645    ///
646    /// s.insert(0, 'f');
647    /// s.insert(1, 'o');
648    /// s.insert(2, 'o');
649    ///
650    /// assert_eq!("foo", s);
651    /// ```
652    #[inline]
653    pub fn insert(&mut self, idx: usize, ch: char) {
654        assert!(self.is_char_boundary(idx));
655        let mut bits = [0; 4];
656        let bits = ch.encode_utf8(&mut bits).as_bytes();
657
658        unsafe {
659            self.insert_bytes(idx, bits);
660        }
661    }
662
663    unsafe fn insert_bytes(&mut self, idx: usize, bytes: &[u8]) {
664        let len = self.len();
665        let amt = bytes.len();
666        assert!(self.vec.remaining_capacity() >= amt);
667
668        unsafe {
669            ptr::copy(
670                self.vec.as_ptr().add(idx),
671                self.vec.as_mut_ptr().add(idx + amt),
672                len - idx,
673            );
674            ptr::copy(bytes.as_ptr(), self.vec.as_mut_ptr().add(idx), amt);
675            self.vec.set_len(len + amt);
676        }
677    }
678
679    /// Inserts a string slice into this `StackStr` at a byte position.
680    ///
681    /// This is an *O*(*n*) operation as it requires copying every element in the
682    /// buffer.
683    ///
684    /// # Panics
685    ///
686    /// Panics if `idx` is larger than the `StackStr`'s length, or if it does not
687    /// lie on a [`char`] boundary.
688    ///
689    /// # Examples
690    ///
691    /// ```
692    /// use stack_buf::StackStr;
693    ///
694    /// let mut s = StackStr::<6>::from("bar");
695    ///
696    /// s.insert_str(0, "foo");
697    ///
698    /// assert_eq!("foobar", s);
699    /// ```
700    #[inline]
701    pub fn insert_str(&mut self, idx: usize, string: &str) {
702        assert!(self.is_char_boundary(idx));
703
704        unsafe {
705            self.insert_bytes(idx, string.as_bytes());
706        }
707    }
708
709    /// Removes a [`char`] from this `StackStr` at a byte position and returns it.
710    ///
711    /// This is an *O*(*n*) operation, as it requires copying every element in the
712    /// buffer.
713    ///
714    /// # Panics
715    ///
716    /// Panics if `idx` is larger than or equal to the `StackStr`'s length,
717    /// or if it does not lie on a [`char`] boundary.
718    ///
719    /// # Examples
720    ///
721    /// ```
722    /// use stack_buf::StackStr;
723    ///
724    /// let mut s = StackStr::<3>::from("foo");
725    ///
726    /// assert_eq!(s.remove(0), 'f');
727    /// assert_eq!(s.remove(1), 'o');
728    /// assert_eq!(s.remove(0), 'o');
729    /// ```
730    #[inline]
731    pub fn remove(&mut self, idx: usize) -> char {
732        let ch = match self[idx..].chars().next() {
733            Some(ch) => ch,
734            None => panic!("cannot remove a char from the end of a StackStr"),
735        };
736
737        let next = idx + ch.len_utf8();
738        let len = self.len();
739        unsafe {
740            ptr::copy(
741                self.vec.as_ptr().add(next),
742                self.vec.as_mut_ptr().add(idx),
743                len - next,
744            );
745            self.vec.set_len(len - (next - idx));
746        }
747        ch
748    }
749}
750
751impl<const N: usize> Clone for StackStr<N> {
752    #[inline]
753    fn clone(&self) -> Self {
754        let mut vec = StackVec::new();
755        vec.copy_from_slice(&self.vec);
756        StackStr { vec }
757    }
758
759    #[inline]
760    fn clone_from(&mut self, source: &Self) {
761        self.clear();
762        self.vec.copy_from_slice(&source.vec);
763    }
764}
765
766impl<const N: usize> Deref for StackStr<N> {
767    type Target = str;
768
769    #[inline(always)]
770    fn deref(&self) -> &str {
771        unsafe { std::str::from_utf8_unchecked(self.vec.as_slice()) }
772    }
773}
774
775impl<const N: usize> DerefMut for StackStr<N> {
776    #[inline(always)]
777    fn deref_mut(&mut self) -> &mut str {
778        unsafe { std::str::from_utf8_unchecked_mut(self.vec.as_mut_slice()) }
779    }
780}
781
782impl<const N: usize> AsRef<str> for StackStr<N> {
783    #[inline(always)]
784    fn as_ref(&self) -> &str {
785        self
786    }
787}
788
789impl<const N: usize> AsMut<str> for StackStr<N> {
790    #[inline(always)]
791    fn as_mut(&mut self) -> &mut str {
792        self
793    }
794}
795
796impl<const N: usize> AsRef<[u8]> for StackStr<N> {
797    #[inline(always)]
798    fn as_ref(&self) -> &[u8] {
799        self.as_bytes()
800    }
801}
802
803impl<const N: usize> Borrow<str> for StackStr<N> {
804    #[inline(always)]
805    fn borrow(&self) -> &str {
806        self
807    }
808}
809
810impl<const N: usize> BorrowMut<str> for StackStr<N> {
811    #[inline(always)]
812    fn borrow_mut(&mut self) -> &mut str {
813        self
814    }
815}
816
817impl<const N: usize> Default for StackStr<N> {
818    /// Creates an empty `StackStr<N>`.
819    #[inline(always)]
820    fn default() -> StackStr<N> {
821        StackStr::new()
822    }
823}
824
825impl<const N: usize> fmt::Debug for StackStr<N> {
826    #[inline]
827    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
828        (**self).fmt(f)
829    }
830}
831
832impl<const N: usize> fmt::Display for StackStr<N> {
833    #[inline]
834    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
835        (**self).fmt(f)
836    }
837}
838
839impl<const N: usize> fmt::Write for StackStr<N> {
840    #[inline]
841    fn write_str(&mut self, s: &str) -> fmt::Result {
842        self.push_str(s);
843        Ok(())
844    }
845}
846
847impl<const N1: usize, const N2: usize> PartialEq<StackStr<N2>> for StackStr<N1> {
848    #[inline]
849    fn eq(&self, other: &StackStr<N2>) -> bool {
850        **self == **other
851    }
852}
853
854impl<const N: usize> PartialEq<str> for StackStr<N> {
855    #[inline]
856    fn eq(&self, other: &str) -> bool {
857        &**self == other
858    }
859}
860
861impl<const N: usize> PartialEq<StackStr<N>> for str {
862    #[inline]
863    fn eq(&self, other: &StackStr<N>) -> bool {
864        self == &**other
865    }
866}
867
868impl<const N: usize> PartialEq<&str> for StackStr<N> {
869    #[inline]
870    fn eq(&self, other: &&str) -> bool {
871        &**self == *other
872    }
873}
874
875impl<const N: usize> PartialEq<StackStr<N>> for &str {
876    #[inline]
877    fn eq(&self, other: &StackStr<N>) -> bool {
878        *self == &**other
879    }
880}
881
882impl<const N: usize> Eq for StackStr<N> {}
883
884impl<const N1: usize, const N2: usize> PartialOrd<StackStr<N2>> for StackStr<N1> {
885    #[inline]
886    fn partial_cmp(&self, other: &StackStr<N2>) -> Option<Ordering> {
887        (**self).partial_cmp(&**other)
888    }
889}
890
891impl<const N: usize> PartialOrd<str> for StackStr<N> {
892    #[inline]
893    fn partial_cmp(&self, other: &str) -> Option<Ordering> {
894        (**self).partial_cmp(other)
895    }
896}
897
898impl<const N: usize> PartialOrd<StackStr<N>> for str {
899    #[inline]
900    fn partial_cmp(&self, other: &StackStr<N>) -> Option<Ordering> {
901        self.partial_cmp(&**other)
902    }
903}
904
905impl<const N: usize> PartialOrd<&str> for StackStr<N> {
906    #[inline]
907    fn partial_cmp(&self, other: &&str) -> Option<Ordering> {
908        (**self).partial_cmp(*other)
909    }
910}
911
912impl<const N: usize> PartialOrd<StackStr<N>> for &str {
913    #[inline]
914    fn partial_cmp(&self, other: &StackStr<N>) -> Option<Ordering> {
915        (*self).partial_cmp(&**other)
916    }
917}
918
919impl<const N: usize> Ord for StackStr<N> {
920    #[inline]
921    fn cmp(&self, other: &Self) -> Ordering {
922        (**self).cmp(&**other)
923    }
924}
925
926impl<const N: usize> Extend<char> for StackStr<N> {
927    #[inline]
928    fn extend<I: IntoIterator<Item = char>>(&mut self, iter: I) {
929        let iterator = iter.into_iter();
930        iterator.for_each(move |c| self.push(c));
931    }
932}
933
934impl<'a, const N: usize> Extend<&'a char> for StackStr<N> {
935    #[inline]
936    fn extend<I: IntoIterator<Item = &'a char>>(&mut self, iter: I) {
937        self.extend(iter.into_iter().cloned());
938    }
939}
940
941impl<'a, const N: usize> Extend<&'a str> for StackStr<N> {
942    #[inline]
943    fn extend<I: IntoIterator<Item = &'a str>>(&mut self, iter: I) {
944        iter.into_iter().for_each(move |s| self.push_str(s));
945    }
946}
947
948#[cfg(feature = "std")]
949#[cfg_attr(docsrs, doc(cfg(all(feature = "std", feature = "str"))))]
950impl<const N: usize> Extend<Box<str>> for StackStr<N> {
951    #[inline]
952    fn extend<I: IntoIterator<Item = Box<str>>>(&mut self, iter: I) {
953        iter.into_iter().for_each(move |s| self.push_str(&s));
954    }
955}
956
957#[cfg(feature = "std")]
958#[cfg_attr(docsrs, doc(cfg(all(feature = "std", feature = "str"))))]
959impl<const N: usize> Extend<String> for StackStr<N> {
960    #[inline]
961    fn extend<I: IntoIterator<Item = String>>(&mut self, iter: I) {
962        iter.into_iter().for_each(move |s| self.push_str(&s));
963    }
964}
965
966#[cfg(feature = "std")]
967#[cfg_attr(docsrs, doc(cfg(all(feature = "std", feature = "str"))))]
968impl<'a, const N: usize> Extend<Cow<'a, str>> for StackStr<N> {
969    #[inline]
970    fn extend<I: IntoIterator<Item = Cow<'a, str>>>(&mut self, iter: I) {
971        iter.into_iter().for_each(move |s| self.push_str(&s));
972    }
973}
974
975impl<const N: usize> FromIterator<char> for StackStr<N> {
976    #[inline]
977    fn from_iter<I: IntoIterator<Item = char>>(iter: I) -> Self {
978        let mut buf = StackStr::new();
979        buf.extend(iter);
980        buf
981    }
982}
983
984impl<'a, const N: usize> FromIterator<&'a char> for StackStr<N> {
985    #[inline]
986    fn from_iter<I: IntoIterator<Item = &'a char>>(iter: I) -> Self {
987        let mut buf = StackStr::new();
988        buf.extend(iter);
989        buf
990    }
991}
992
993impl<'a, const N: usize> FromIterator<&'a str> for StackStr<N> {
994    #[inline]
995    fn from_iter<I: IntoIterator<Item = &'a str>>(iter: I) -> Self {
996        let mut buf = StackStr::new();
997        buf.extend(iter);
998        buf
999    }
1000}
1001
1002#[cfg(feature = "std")]
1003#[cfg_attr(docsrs, doc(cfg(all(feature = "std", feature = "str"))))]
1004impl<const N: usize> FromIterator<String> for StackStr<N> {
1005    #[inline]
1006    fn from_iter<I: IntoIterator<Item = String>>(iter: I) -> Self {
1007        let mut buf = StackStr::new();
1008        buf.extend(iter);
1009        buf
1010    }
1011}
1012
1013#[cfg(feature = "std")]
1014#[cfg_attr(docsrs, doc(cfg(all(feature = "std", feature = "str"))))]
1015impl<const N: usize> FromIterator<Box<str>> for StackStr<N> {
1016    #[inline]
1017    fn from_iter<I: IntoIterator<Item = Box<str>>>(iter: I) -> Self {
1018        let mut buf = StackStr::new();
1019        buf.extend(iter);
1020        buf
1021    }
1022}
1023
1024#[cfg(feature = "std")]
1025#[cfg_attr(docsrs, doc(cfg(all(feature = "std", feature = "str"))))]
1026impl<'a, const N: usize> FromIterator<Cow<'a, str>> for StackStr<N> {
1027    #[inline]
1028    fn from_iter<I: IntoIterator<Item = Cow<'a, str>>>(iter: I) -> Self {
1029        let mut buf = StackStr::new();
1030        buf.extend(iter);
1031        buf
1032    }
1033}
1034
1035impl<const N: usize> From<&str> for StackStr<N> {
1036    #[inline]
1037    fn from(s: &str) -> Self {
1038        let mut buf = StackStr::new();
1039        buf.push_str(s);
1040        buf
1041    }
1042}
1043
1044impl<const N: usize> From<&mut str> for StackStr<N> {
1045    #[inline]
1046    fn from(s: &mut str) -> Self {
1047        let mut buf = StackStr::new();
1048        buf.push_str(s);
1049        buf
1050    }
1051}
1052
1053impl<const N1: usize, const N2: usize> From<&StackStr<N2>> for StackStr<N1> {
1054    #[inline]
1055    fn from(s: &StackStr<N2>) -> Self {
1056        let mut buf = StackStr::new();
1057        buf.push_str(s);
1058        buf
1059    }
1060}
1061
1062#[cfg(feature = "std")]
1063#[cfg_attr(docsrs, doc(cfg(all(feature = "std", feature = "str"))))]
1064impl<const N: usize> From<Box<str>> for StackStr<N> {
1065    /// Converts the given boxed `str` slice to a `StrackStr`.
1066    /// It is notable that the `str` slice is owned.
1067    ///
1068    /// # Examples
1069    ///
1070    /// ```
1071    /// use stack_buf::StackStr;
1072    ///
1073    /// let s1 = String::from("hello world");
1074    /// let s2 = s1.into_boxed_str();
1075    /// let s3 = StackStr::<16>::from(s2);
1076    ///
1077    /// assert_eq!("hello world", s3)
1078    /// ```
1079    #[inline]
1080    fn from(s: Box<str>) -> Self {
1081        let mut buf = StackStr::new();
1082        buf.push_str(&s);
1083        buf
1084    }
1085}
1086
1087#[cfg(feature = "std")]
1088#[cfg_attr(docsrs, doc(cfg(all(feature = "std", feature = "str"))))]
1089impl<const N: usize> From<Cow<'_, str>> for StackStr<N> {
1090    #[inline]
1091    fn from(s: Cow<'_, str>) -> Self {
1092        let mut buf = StackStr::new();
1093        buf.push_str(&s);
1094        buf
1095    }
1096}
1097
1098impl<const N: usize> Hash for StackStr<N> {
1099    #[inline]
1100    fn hash<H: Hasher>(&self, hasher: &mut H) {
1101        (**self).hash(hasher)
1102    }
1103}
1104
1105/// Implements the `+` operator for concatenating two strings.
1106///
1107/// This consumes the `StackStr` on the left-hand side and re-uses its buffer.
1108/// This is done to avoid allocating a new `StackStr` and copying the entire contents on
1109/// every operation, which would lead to *O*(*n*^2) running time when building an *n*-byte string by
1110/// repeated concatenation.
1111///
1112/// The string on the right-hand side is only borrowed; its contents are copied into the returned
1113/// `StackStr`.
1114///
1115/// # Examples
1116///
1117/// Concatenating two `StackStr`s takes the first by value and borrows the second:
1118///
1119/// ```
1120/// use stack_buf::StackStr;
1121///
1122/// let a = StackStr::<16>::from("hello");
1123/// let b = StackStr::<6>::from(" world");
1124/// let c = a + &b;
1125/// // `a` is moved and can no longer be used here.
1126///
1127/// assert_eq!(c, "hello world");
1128/// ```
1129///
1130/// If you want to keep using the first `StackStr`, you can clone it and append to the clone instead:
1131///
1132/// ```
1133/// use stack_buf::StackStr;
1134///
1135/// let a = StackStr::<16>::from("hello");
1136/// let b = StackStr::<6>::from(" world");
1137/// let c = a.clone() + &b;
1138/// // `a` is still valid here.
1139///
1140/// assert_eq!(c, "hello world");
1141/// ```
1142impl<const N: usize> Add<&str> for StackStr<N> {
1143    type Output = StackStr<N>;
1144
1145    #[inline]
1146    fn add(mut self, other: &str) -> Self {
1147        self.push_str(other);
1148        self
1149    }
1150}
1151
1152/// Implements the `+=` operator for appending to a `StackStr`.
1153///
1154/// This has the same behavior as the [`push_str`][StackStr::push_str] method.
1155impl<const N: usize> AddAssign<&str> for StackStr<N> {
1156    #[inline]
1157    fn add_assign(&mut self, other: &str) {
1158        self.push_str(other);
1159    }
1160}
1161
1162impl<const N: usize> FromStr for StackStr<N> {
1163    type Err = std::convert::Infallible;
1164
1165    #[inline]
1166    fn from_str(s: &str) -> Result<Self, Self::Err> {
1167        Ok(StackStr::from(s))
1168    }
1169}
1170
1171impl<const N: usize> From<StackStr<N>> for StackVec<u8, N> {
1172    #[inline]
1173    fn from(s: StackStr<N>) -> Self {
1174        s.into_bytes()
1175    }
1176}
1177
1178#[cfg(all(test, feature = "std"))]
1179mod tests {
1180    use super::StackStr;
1181
1182    #[test]
1183    fn retain_keeps_a_valid_prefix_when_predicate_panics() {
1184        let mut value = StackStr::<4>::from("aéz");
1185        let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
1186            value.retain(|ch| match ch {
1187                'a' => false,
1188                'é' => true,
1189                _ => panic!("predicate failed"),
1190            });
1191        }));
1192
1193        assert!(result.is_err());
1194        assert_eq!(value, "é");
1195    }
1196}
1197
1198#[cfg(feature = "serde")]
1199mod impl_serde {
1200    use super::*;
1201    use serde::de::{Error, Unexpected, Visitor};
1202    use serde::{Deserialize, Deserializer, Serialize, Serializer};
1203    use std::marker::PhantomData;
1204
1205    #[cfg_attr(docsrs, doc(cfg(all(feature = "str", feature = "serde"))))]
1206    impl<const N: usize> Serialize for StackStr<N> {
1207        #[inline]
1208        fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1209        where
1210            S: Serializer,
1211        {
1212            serializer.serialize_str(self)
1213        }
1214    }
1215
1216    #[cfg_attr(docsrs, doc(cfg(all(feature = "str", feature = "serde"))))]
1217    impl<'de, const N: usize> Deserialize<'de> for StackStr<N> {
1218        #[inline]
1219        fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1220        where
1221            D: Deserializer<'de>,
1222        {
1223            struct StackStrVisitor<const N: usize>(PhantomData<[u8; N]>);
1224
1225            impl<const N: usize> Visitor<'_> for StackStrVisitor<N> {
1226                type Value = StackStr<N>;
1227
1228                #[inline]
1229                fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
1230                    write!(formatter, "a string with no more than {} bytes", N)
1231                }
1232
1233                #[inline]
1234                fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
1235                where
1236                    E: Error,
1237                {
1238                    Ok(StackStr::from(v))
1239                }
1240
1241                #[inline]
1242                fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
1243                where
1244                    E: Error,
1245                {
1246                    let s = str::from_utf8(v)
1247                        .map_err(|_| E::invalid_value(Unexpected::Bytes(v), &self))?;
1248                    Ok(StackStr::from(s))
1249                }
1250            }
1251
1252            deserializer.deserialize_str(StackStrVisitor::<N>(PhantomData))
1253        }
1254    }
1255}