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