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}