coca/
string.rs

1//! UTF-8 encoded, growable string types with constant capacity.
2
3use core::fmt::{self, Display};
4use core::ops::{RangeBounds, Range};
5use core::str::{self, Utf8Error, FromStr};
6
7use crate::CapacityError;
8use crate::collections::vec::Vec;
9use crate::storage::{ArrayLayout, Storage, Capacity, InlineStorage, ArenaStorage, normalize_range};
10
11/// A possible error value when converting a UTF-8 byte vector into a [`String`].
12/// 
13/// This is the error type for the [`from_utf8`] method on `String`.
14/// 
15/// [`from_utf8`]: String::from_utf8
16#[derive(Debug, PartialEq, Eq)]
17pub struct FromUtf8Error<S: Storage<ArrayLayout<u8>>, I: Capacity> {
18    bytes: Vec<u8, S, I>,
19    error: Utf8Error,
20}
21
22impl<S: Storage<ArrayLayout<u8>>, I: Capacity> FromUtf8Error<S, I> {
23    /// Returns a slice of bytes that were attempted to convert to a [`String`].
24    pub fn as_bytes(&self) -> &[u8] {
25        self.bytes.as_slice()
26    }
27
28    /// Returns the byte vector that was attempted to convert to a [`String`].
29    pub fn into_bytes(self) -> Vec<u8, S, I> {
30        self.bytes
31    }
32
33    /// Returns a [`Utf8Error`] that provides more details about the conversion failure.
34    pub fn utf8_error(&self) -> Utf8Error {
35        self.error
36    }
37}
38
39impl<S: Storage<ArrayLayout<u8>>, I: Capacity> Clone for FromUtf8Error<S, I> where Vec<u8, S, I>: Clone {
40    fn clone(&self) -> Self {
41        FromUtf8Error {
42            bytes: self.bytes.clone(),
43            error: self.error,
44        }
45    }
46}
47
48impl<S: Storage<ArrayLayout<u8>>, I: Capacity> Display for FromUtf8Error<S, I> {
49    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> fmt::Result {
50        fmt::Display::fmt(&self.error, f)
51    }
52}
53
54/// A UTF-8 encoded, growable string.
55/// 
56/// Generic over the storage buffer type `S` and the index type `I`.
57pub struct String<S: Storage<ArrayLayout<u8>>, I: Capacity = usize> {
58    vec: Vec<u8, S, I>,
59}
60
61impl<S: Storage<ArrayLayout<u8>>, I: Capacity> From<S> for String<S, I> {
62    fn from(buf: S) -> Self {
63        String { vec: Vec::from(buf) }
64    }
65}
66
67impl<S: Storage<ArrayLayout<u8>>, I: Capacity> String<S, I> {
68    /// Converts a vector of bytes into a `String` without copying.
69    /// 
70    /// If you are sure that the byte vector is valid UTF-8, and don't want to
71    /// incur the overhead of the validity check, consider [`from_utf8_unchecked`],
72    /// which has the same behavior but skips the check.
73    /// 
74    /// If you need a [`&str`] instead of a `String`, consider [`str::from_utf8`].
75    /// 
76    /// The inverse of this method is [`into_bytes`].
77    /// 
78    /// [`from_utf8_unchecked`]: String::from_utf8_unchecked
79    /// [`&str`]: prim@str "&str"
80    /// [`into_bytes`]: String::into_bytes
81    /// 
82    /// # Errors
83    /// Returns [`Err`] if the slice is not UTF-8 with a description as to why
84    /// the provided bytes are not UTF-8. The moved vector is also included.
85    /// 
86    /// # Examples
87    /// ```
88    /// // Basic Usage:
89    /// let mut bytes = coca::collections::InlineVec::<u8, 8>::new();
90    /// bytes.extend_from_slice(&[240, 159, 146, 150]);
91    /// 
92    /// let sparkle_heart = coca::InlineString::from_utf8(bytes).unwrap();
93    /// assert_eq!(sparkle_heart, "💖");
94    /// 
95    /// // Invalid Bytes:
96    /// let mut bytes = coca::collections::InlineVec::<u8, 8>::new();
97    /// bytes.extend_from_slice(&[0, 159, 146, 150]);
98    /// assert!(coca::InlineString::from_utf8(bytes).is_err());
99    /// ```
100    #[inline]
101    pub fn from_utf8(vec: Vec<u8, S, I>) -> Result<Self, FromUtf8Error<S, I>> {
102        match core::str::from_utf8(&vec) {
103            Ok(_) => Ok(String { vec }),
104            Err(e) => Err(FromUtf8Error { bytes: vec, error: e }),
105        }
106    }
107
108    /// Decomposes a `String` into its raw parts.
109    /// 
110    /// Returns the raw storage type and the length of the string (in bytes).
111    /// These are the same arguments in the same order as the arguments to
112    /// [`from_raw_parts`](String::from_raw_parts).
113    /// 
114    /// # Examples
115    /// ```
116    /// use core::str::FromStr;
117    /// let s = coca::InlineString::<8>::from_str("hello").unwrap();
118    /// let (storage, len): ([core::mem::MaybeUninit<u8>; 8], usize) = s.into_raw_parts();
119    /// assert_eq!(len, 5);
120    /// ```
121    #[inline]
122    pub fn into_raw_parts(self) -> (S, I) {
123        self.vec.into_raw_parts()
124    }
125
126    /// Creates a new `String` from a length and raw storage buffer.
127    /// 
128    /// # Safety
129    /// Callers must ensure that
130    /// 
131    /// * `length` is less than or equal to `buf.capacity()`, and
132    /// * the first `length` bytes stored in `buf` are valid UTF-8.
133    /// 
134    /// # Examples
135    /// ```
136    /// use core::str::FromStr;
137    /// use coca::InlineString;
138    /// 
139    /// let s = InlineString::<8>::from_str("hello").unwrap();
140    /// let (storage, len) = s.into_raw_parts();
141    /// 
142    /// let rebuilt = unsafe { InlineString::from_raw_parts(storage, len) };
143    /// assert_eq!(rebuilt, "hello");
144    /// ```
145    #[inline]
146    pub unsafe fn from_raw_parts(buf: S, length: I) -> Self {
147        String { vec: Vec::from_raw_parts(buf, length) }
148    }
149
150    /// Converts a vector of bytes into a `String` without copying or checking
151    /// that the bytes are valid UTF-8.
152    /// 
153    /// See the safe version, [`from_utf8`], for more details.
154    /// 
155    /// [`from_utf8`]: String::from_utf8
156    /// 
157    /// # Safety
158    /// 
159    /// Callers must ensure that the passed bytes are valid UTF-8. If this
160    /// constraint is violated, it may cause memory unsafety issues with future
161    /// users of the `String`, as the rest of `coca` assumes `String`s to be
162    /// valid UTF-8.
163    /// 
164    /// # Examples
165    /// ```
166    /// let mut bytes = coca::collections::InlineVec::<u8, 8>::new();
167    /// bytes.extend_from_slice(&[240, 159, 146, 150]);
168    /// 
169    /// let sparkle_heart = unsafe { coca::InlineString::from_utf8_unchecked(bytes) };
170    /// assert_eq!(sparkle_heart, "💖");
171    /// ```
172    #[inline]
173    pub unsafe fn from_utf8_unchecked(bytes: Vec<u8, S, I>) -> Self {
174        String { vec: bytes }
175    }
176
177    /// Converts a `String` into a vector of bytes without copying, consuming the string.
178    /// 
179    /// # Examples
180    /// ```
181    /// use core::str::FromStr;
182    /// let s = coca::InlineString::<8>::from_str("hello").unwrap();
183    /// let bytes = s.into_bytes();
184    /// 
185    /// assert_eq!(&[104, 101, 108, 108, 111][..], &bytes[..]);
186    /// ```
187    #[inline]
188    pub fn into_bytes(self) -> Vec<u8, S, I> {
189        self.vec
190    }
191
192    /// Extracts a string slice containing the entire `String`.
193    pub fn as_str(&self) -> &str {
194        self
195    }
196
197    /// Extracts a mutable string slice containing the entire `String`.
198    pub fn as_mut_str(&mut self) -> &mut str {
199        self
200    }
201
202    /// Appends a given string slice onto the end of the `String`, returning
203    /// [`Err`] if the remaining space is insufficient.
204    /// 
205    /// # Examples
206    /// ```
207    /// use core::str::FromStr;
208    /// let mut s = coca::InlineString::<8>::from_str("foo").unwrap();
209    /// 
210    /// assert!(s.try_push_str("bar").is_ok());
211    /// 
212    /// assert!(s.try_push_str("bazz").is_err());
213    /// assert_eq!(s, "foobar");
214    /// ```
215    #[inline]
216    pub fn try_push_str(&mut self, string: &str) -> crate::Result<()> {
217        self.vec.try_extend_from_slice(string.as_bytes())
218    }
219
220    /// Appends a given string slice onto the end of the `String`.
221    /// 
222    /// # Panics
223    /// Panics if the space remaining in the string is insufficient.
224    /// See [`try_push_str`](String::try_push_str) for a checked version
225    /// that never panics.
226    #[inline]
227    pub fn push_str(&mut self, string: &str) {
228        #[cold]
229        #[inline(never)]
230        fn assert_failed() -> ! {
231            panic!("space remaining in string is insufficient")
232        }
233
234        if self.try_push_str(string).is_err() {
235            assert_failed();
236        }
237    }
238
239    /// Copies characters from the `src` range to the end of the string.
240    /// 
241    /// Returns [`Err`] if the remaining space is insufficient.
242    /// 
243    /// # Panics
244    /// Panics if the starting point is greater than the end point, if the end
245    /// point is greater than the length of the `String`, or if either one does
246    /// not lie on a [`char`] boundary.
247    /// 
248    /// # Examples
249    /// ```
250    /// use core::str::FromStr;
251    /// let mut s = coca::InlineString::<10>::from_str("abcde").unwrap();
252    /// 
253    /// assert!(s.try_extend_from_within(2..).is_ok());
254    /// assert_eq!(s, "abcdecde");
255    /// 
256    /// assert!(s.try_extend_from_within(..2).is_ok());
257    /// assert_eq!(s, "abcdecdeab");
258    /// 
259    /// assert!(s.try_extend_from_within(4..8).is_err());
260    /// ```
261    pub fn try_extend_from_within<R: RangeBounds<usize>>(&mut self, src: R) -> crate::Result<()> {
262        let Range { start, end } = normalize_range(src, self.len());
263
264        assert!(self.is_char_boundary(start));
265        assert!(self.is_char_boundary(end));
266
267        let src = I::from_usize(start)..I::from_usize(end);
268        self.vec.try_extend_from_within(src)
269    }
270
271    /// Copies the characters from the `src` range to the end of the string.
272    /// 
273    /// # Panics
274    /// Panics if the starting point is greater than the end point, if the end
275    /// point is greater than the length of the `String`, if either one does
276    /// not lie on a [`char`] boundary, or if the remaining space is insufficient.
277    pub fn extend_from_within<R: RangeBounds<usize>>(&mut self, src: R) {
278        self.try_extend_from_within(src).expect("space remaining in string is insufficient");
279    }
280
281    /// Returns the `String`'s capacity, in bytes.
282    #[inline]
283    pub fn capacity(&self) -> usize {
284        self.vec.capacity()
285    }
286
287    /// Returns the current length of the `String`, in bytes, not [`char`]s or
288    /// graphemes. This might not be what a human considers the length of the string.
289    #[inline]
290    pub fn len(&self) -> usize {
291        self.vec.len()
292    }
293
294    /// Returns `true` if the `String` has a length of zero, and `false` otherwise.
295    #[inline]
296    pub fn is_empty(&self) -> bool {
297        self.len() == 0
298    }
299
300    /// Returns `true` if the `String` has a length equal to its capacity, and `false` otherwise.
301    #[inline]
302    pub fn is_full(&self) -> bool {
303        self.len() == self.capacity()
304    }
305
306    /// Appends the given [`char`] to the end of the `String`, returning
307    /// `Err(ch)` if the remaining space is insufficient.
308    /// 
309    /// # Examples
310    /// ```
311    /// use core::str::FromStr;
312    /// let mut s = coca::InlineString::<4>::from_str("ab").unwrap();
313    /// 
314    /// assert!(s.try_push('c').is_ok());
315    /// assert!(s.try_push('d').is_ok());
316    /// assert!(s.try_push('e').is_err());
317    /// 
318    /// assert_eq!(s, "abcd");
319    /// ```
320    #[inline]
321    pub fn try_push(&mut self, ch: char) -> crate::Result<()> {
322        match ch.len_utf8() {
323            1 => self.vec.try_push(ch as u8).map_err(|_| CapacityError),
324            _ => self.vec.try_extend_from_slice(ch.encode_utf8(&mut [0; 4]).as_bytes())
325        }
326    }
327
328    /// Appends the given [`char`] to the end of the `String`.
329    /// 
330    /// # Panics
331    /// Panics if the space remaining in the string is insufficient.
332    /// See [`try_push`](String::try_push_str) for a checked version
333    /// that never panics.
334    #[inline]
335    pub fn push(&mut self, ch: char) {
336        #[cold]
337        #[inline(never)]
338        fn assert_failed() -> ! {
339            panic!("space remaining in string is insufficient")
340        }
341
342        if self.try_push(ch).is_err() {
343            assert_failed();
344        }
345    }
346
347    /// Returns a byte slice of this `String`'s contents.
348    /// 
349    /// The inverse of this method is [`from_utf8`](String::from_utf8).
350    /// 
351    /// # Examples
352    /// ```
353    /// use core::str::FromStr;
354    /// let s = coca::InlineString::<8>::from_str("hello").unwrap();
355    /// assert_eq!(&[104, 101, 108, 108, 111], s.as_bytes());
356    /// ```
357    #[inline]
358    pub fn as_bytes(&self) -> &[u8] {
359        &self.vec
360    }
361
362    /// Shortens the `String` to the specified length.
363    /// 
364    /// If `new_len` is greater than the string's current length, this has no effect.
365    /// 
366    /// # Panics
367    /// Panics if `new_len` does not lie on a [`char`] boundary.
368    /// 
369    /// # Examples
370    /// ```
371    /// use core::str::FromStr;
372    /// let mut s = coca::InlineString::<8>::from_str("hello").unwrap();
373    /// 
374    /// s.truncate(2);
375    /// 
376    /// assert_eq!(s, "he");
377    /// ```
378    #[inline]
379    pub fn truncate(&mut self, new_len: usize) {
380        if new_len <= self.len() {
381            assert!(self.is_char_boundary(new_len));
382            self.vec.truncate(I::from_usize(new_len));
383        }
384    }
385
386    /// Truncates the `String`, removing all contents.
387    #[inline]
388    pub fn clear(&mut self) {
389        self.truncate(0);
390    }
391
392    /// Removes the last [`char`] from the `String` and returns it,
393    /// or [`None`] if it is empty.
394    /// 
395    /// # Examples
396    /// ```
397    /// use core::str::FromStr;
398    /// let mut s = coca::InlineString::<4>::from_str("foo").unwrap();
399    /// 
400    /// assert_eq!(s.pop(), Some('o'));
401    /// assert_eq!(s.pop(), Some('o'));
402    /// assert_eq!(s.pop(), Some('f'));
403    /// 
404    /// assert_eq!(s.pop(), None);
405    /// ```
406    #[inline]
407    pub fn pop(&mut self) -> Option<char> {
408        let ch = self.chars().rev().next()?;
409        let newlen = I::from_usize(self.len() - ch.len_utf8());
410        unsafe { self.vec.set_len(newlen); }
411        Some(ch)
412    }
413
414    /// Removes a [`char`] at the given byte position from the `String` and returns it.
415    /// 
416    /// This is an *O*(*n*) operation, as it requires copying every character
417    /// after the removed element in the string.
418    /// 
419    /// # Panics
420    /// Panics if `idx` is larger than or equal to the string's length,
421    /// or if it does not lie on a [`char`] boundary.
422    /// 
423    /// # Examples
424    /// ```
425    /// use core::str::FromStr;
426    /// let mut s = coca::InlineString::<4>::from_str("foo").unwrap();
427    /// 
428    /// assert_eq!(s.remove(0), 'f');
429    /// assert_eq!(s.remove(1), 'o');
430    /// assert_eq!(s.remove(0), 'o');
431    /// 
432    /// assert!(s.is_empty());
433    /// ```
434    pub fn remove(&mut self, idx: usize) -> char {
435        let result = self[idx..].chars().next().expect("cannot remove a char from the end of a string");
436        
437        let next = idx + result.len_utf8();
438        let len = self.len();
439        let new_len = I::from_usize(len - (next - idx));
440
441        unsafe {
442            core::ptr::copy(self.vec.as_ptr().add(next), self.vec.as_mut_ptr().add(idx), len - next);
443            self.vec.set_len(new_len);
444        }
445
446        result
447    }
448
449    /// Retains only the characters specified by the predicate.
450    /// 
451    /// In other words, removes all characters `c` such that `f(c)` returns `false`.
452    /// This method operates in place, visiting each character exactly once in the
453    /// original order, and preserves the order of the retained characters.
454    /// 
455    /// # Examples
456    /// ```
457    /// use core::str::FromStr;
458    /// let mut s = coca::InlineString::<12>::from_str("f_o_o_b_a_r").unwrap();
459    /// 
460    /// s.retain(|ch| ch != '_');
461    /// 
462    /// assert_eq!(s, "foobar");
463    /// ```
464    /// Because the elements are visited exactly once in the original order,
465    /// external state may be used to decide which characters to keep:
466    /// ```
467    /// use core::str::FromStr;
468    /// let mut s = coca::InlineString::<8>::from_str("abcde").unwrap();
469    /// let keep = [false, true, true, false, true];
470    /// let mut iter = keep.iter();
471    /// s.retain(|_| *iter.next().unwrap());
472    /// assert_eq!(s, "bce");
473    /// ```
474    pub fn retain<F: FnMut(char) -> bool>(&mut self, mut f: F) {
475        let len = self.len();
476        let mut idx = 0;
477        let mut deleted_bytes = 0;
478        
479        while idx < len {
480            let ch = unsafe { self.get_unchecked(idx..len).chars().next().unwrap_unchecked() };
481            let ch_len = ch.len_utf8();
482
483            if !f(ch) {
484                deleted_bytes += ch_len;
485            } else if deleted_bytes > 0 {
486                unsafe {
487                    let src_ptr = self.vec.as_ptr().add(idx);
488                    let dst_ptr = self.vec.as_mut_ptr().add(idx - deleted_bytes);
489                    core::ptr::copy(src_ptr, dst_ptr, ch_len);
490                }
491            }
492
493            idx += ch_len;
494        }
495
496        unsafe { self.vec.set_len(I::from_usize(len - deleted_bytes)) };
497    }
498    
499    /// Inserts a character into the `String` at a given byte position.
500    /// 
501    /// Returns [`Err`] if the remaining space is insufficient.
502    /// 
503    /// This is an *O*(*n*) operation as it requires copying every element in the buffer.
504    /// 
505    /// # Panics
506    /// Panics if `idx` is larger than the `String`'s length, or if it does not lie
507    /// on a [`char`] boundary.
508    /// 
509    /// # Examples
510    /// ```
511    /// let mut s = coca::InlineString::<3>::new();
512    /// 
513    /// assert!(s.try_insert(0, 'o').is_ok());
514    /// assert!(s.try_insert(1, 'o').is_ok());
515    /// assert!(s.try_insert(0, 'f').is_ok());
516    /// 
517    /// assert!(s.try_insert(3, 'b').is_err());
518    /// 
519    /// assert_eq!(s, "foo");
520    /// ```
521    pub fn try_insert(&mut self, idx: usize, ch: char) -> crate::Result<()> {
522        assert!(self.is_char_boundary(idx));
523        let mut bits = [0; 4];
524        let bits = ch.encode_utf8(&mut bits).as_bytes();
525        self.vec.try_insert_slice(I::from_usize(idx), bits)
526    }
527
528    /// Inserts a character into the `String` at a given byte position.
529    /// 
530    /// This is an *O*(*n*) operation as it requires copying every element in the buffer.
531    /// 
532    /// # Panics
533    /// Panics if `idx` is larger than the `String`'s length, if it does not lie
534    /// on a [`char`] boundary, or if the remaining space is insufficient.
535    pub fn insert(&mut self, idx: usize, ch: char) {
536        self.try_insert(idx, ch).expect("remaining space is insufficient");
537    }
538
539    /// Inserts a string slice into the `String` at a given byte position.
540    /// 
541    /// Returns [`Err`] if the remaining space is insufficient.
542    /// 
543    /// This is an *O*(*n*) operation as it requires copying every element in the buffer.
544    /// 
545    /// # Panics
546    /// Panics if `idx` is larger than the `String`'s length, or if it does not
547    /// lie on a [`char`] boundary.
548    /// 
549    /// # Examples
550    /// ```
551    /// use core::str::FromStr;
552    /// let mut s = coca::InlineString::<8>::from_str("bar").unwrap();
553    /// 
554    /// assert!(s.try_insert_str(0, "foo").is_ok());
555    /// assert!(s.try_insert_str(6, "bazz").is_err());
556    /// 
557    /// assert_eq!(s, "foobar");
558    /// ```
559    pub fn try_insert_str(&mut self, idx: usize, string: &str) -> crate::Result<()> {
560        assert!(self.is_char_boundary(idx));
561        self.vec.try_insert_slice(I::from_usize(idx), string.as_bytes())
562    }
563
564    /// Inserts a string slice into the `String` at a given byte position.
565    /// 
566    /// This is an *O*(*n*) operation as it requires copying every element in the buffer.
567    /// 
568    /// # Panics
569    /// Panics if `idx` is larger than the `String`'s length, if it does not
570    /// lie on a [`char`] boundary, or if the remaining space is insufficient.
571    pub fn insert_str(&mut self, idx: usize, string: &str) {
572        self.try_insert_str(idx, string).expect("remaining space is insufficient");
573    }
574
575    /// Returns a mutable reference to the raw byte contents of this `String`.
576    /// 
577    /// # Safety
578    /// This function is unsafe because the returned `&mut Vec` allows writing
579    /// bytes which are not valid UTF-8. If this constraint is violated, using
580    /// the original `String` after dropping the `&mut Vec` may violate memory
581    /// safety, as the rest of `coca` assumes that `String`s are valid UTF-8.
582    /// 
583    /// # Examples
584    /// ```
585    /// use core::str::FromStr;
586    /// let mut s = coca::InlineString::<8>::from_str("hello").unwrap();
587    /// 
588    /// unsafe {
589    ///     let mut vec = s.as_mut_vec();
590    ///     assert_eq!(&[104, 101, 108, 108, 111][..], &vec[..]);
591    ///     
592    ///     vec.iter_mut().for_each(|b| *b += 1);
593    /// }
594    /// 
595    /// assert_eq!(s, "ifmmp");
596    /// ```
597    #[inline]
598    pub unsafe fn as_mut_vec(&mut self) -> &mut Vec<u8, S, I> {
599        &mut self.vec
600    }
601    
602    /// Creates a draining iterator that removes the specified range from the `String`
603    /// and yields the removed [`char`]s.
604    /// 
605    /// Note: No matter how many elements of the iterator are consumed,
606    /// the full range is removed when the iterator **is** dropped;
607    /// if the iterator **is not** dropped, the `String` remains unchanged.
608    /// 
609    /// # Panics
610    /// Panics if the starting point is greater than the end point, if the end
611    /// point is greater than the length of the `String`, or if either one does
612    /// not lie on a [`char`] boundary.
613    /// 
614    /// # Examples
615    /// ```
616    /// use core::str::FromStr;
617    /// let mut s = coca::InlineString::<32>::from_str("α is alpha, β is beta").unwrap();
618    /// let beta_offset = s.find('β').unwrap();
619    /// 
620    /// let mut drain_iter = s.drain(..beta_offset);
621    /// assert_eq!(drain_iter.next(), Some('α'));
622    /// assert_eq!(drain_iter.next_back(), Some(' '));
623    /// 
624    /// drop(drain_iter);
625    /// assert_eq!(s, "β is beta");
626    /// 
627    /// s.drain(..);
628    /// assert!(s.is_empty());
629    /// ```
630    pub fn drain<R: RangeBounds<usize>>(&mut self, range: R) -> Drain<'_, S, I> {
631        let Range { start, end } = normalize_range(range, self.len());
632        assert!(self.is_char_boundary(start));
633        assert!(self.is_char_boundary(end));
634        let target_range = I::from_usize(start)..I::from_usize(end);
635        
636        let self_ptr = self as *mut _;
637        let iter = unsafe { self.get_unchecked(start..end) }.chars();
638
639        Drain { parent: self_ptr, target_range, iter }
640    }
641    
642    /// Removes the specified range in the `String` and replaces it with the given string.
643    /// The given string doesn't need to be the same length as the range.
644    /// 
645    /// Returns [`Err`] if the remaining space is insufficient.
646    /// 
647    /// # Panics
648    /// Panics if the starting point is greater than the end point, if the end
649    /// point is greater than the length of the `String`, or if either one does
650    /// not lie on a [`char`] boundary.
651    /// 
652    /// # Examples
653    /// ```
654    /// use core::str::FromStr;
655    /// let mut s = coca::InlineString::<32>::from_str("α is alpha, β is beta").unwrap();
656    /// let beta_offset = s.find('β').unwrap();
657    /// 
658    /// assert!(s.try_replace_range(..beta_offset, "A is capital alpha; ").is_ok());
659    /// assert_eq!(s, "A is capital alpha; β is beta");
660    /// 
661    /// let beta_offset = s.find('β').unwrap();
662    /// assert!(s.try_replace_range(beta_offset.., "B is capital beta.").is_err());
663    /// ```
664    pub fn try_replace_range<R: RangeBounds<usize>>(&mut self, range: R, replace_with: &str) -> crate::Result<()> {
665        let Range { start, end } = normalize_range(range, self.len());
666
667        assert!(self.is_char_boundary(start));
668        assert!(self.is_char_boundary(end));
669
670        let range = I::from_usize(start)..I::from_usize(end);
671        self.vec.try_replace_range(range, replace_with.as_bytes())
672    }
673
674    /// Removes the specified range in the `String` and replaces it with the given string.
675    /// The given string doesn't need to be the same length as the range.
676    /// 
677    /// # Panics
678    /// Panics if the starting point is greater than the end point, if the end
679    /// point is greater than the length of the `String`, if either one does
680    /// not lie on a [`char`] boundary, or if the remaining space is insufficient.
681    pub fn replace_range<R: RangeBounds<usize>>(&mut self, range: R, replace_with: &str) {
682        self.try_replace_range(range, replace_with).expect("remaining space is insufficient");
683    }
684}
685
686impl<S: Storage<ArrayLayout<u8>>, I: Capacity> core::ops::Deref for String<S, I> {
687    type Target = str;
688
689    #[inline]
690    fn deref(&self) -> &str {
691        unsafe { str::from_utf8_unchecked(&self.vec) }
692    }
693}
694
695impl<S: Storage<ArrayLayout<u8>>, I: Capacity> core::ops::DerefMut for String<S, I> {
696    #[inline]
697    fn deref_mut(&mut self) -> &mut str {
698        unsafe { str::from_utf8_unchecked_mut(&mut *self.vec) }
699    }
700}
701
702impl<S: Storage<ArrayLayout<u8>>, I: Capacity> core::convert::AsRef<str> for String<S, I> {
703    #[inline]
704    fn as_ref(&self) -> &str {
705        self.as_str()
706    }
707}
708
709impl<S: Storage<ArrayLayout<u8>>, I: Capacity> core::convert::AsMut<str> for String<S, I> {
710    #[inline]
711    fn as_mut(&mut self) -> &mut str {
712        self.as_mut_str()
713    }
714}
715
716impl<S: Storage<ArrayLayout<u8>>, I: Capacity> core::convert::AsRef<[u8]> for String<S, I> {
717    #[inline]
718    fn as_ref(&self) -> &[u8] {
719        self.vec.as_slice()
720    }
721}
722
723impl<S: Storage<ArrayLayout<u8>>, I: Capacity> Clone for String<S, I> where Vec<u8, S, I>: Clone {
724    #[inline]
725    fn clone(&self) -> Self {
726        String { vec: self.vec.clone() }
727    }
728}
729
730impl<S: Storage<ArrayLayout<u8>>, I: Capacity> core::iter::Extend<char> for String<S, I> {
731    #[inline]
732    fn extend<It: IntoIterator<Item = char>>(&mut self, iter: It) {
733        for ch in iter {
734            self.push(ch);
735        }
736    }
737}
738
739impl<'a, S: Storage<ArrayLayout<u8>>, I: Capacity> core::iter::Extend<&'a char> for String<S, I> {
740    #[inline]
741    fn extend<It: IntoIterator<Item = &'a char>>(&mut self, iter: It) {
742        for ch in iter {
743            self.push(*ch);
744        }
745    }
746}
747
748impl<'a, S: Storage<ArrayLayout<u8>>, I: Capacity> core::iter::Extend<&'a str> for String<S, I> {
749    #[inline]
750    fn extend<It: IntoIterator<Item = &'a str>>(&mut self, iter: It) {
751        for s in iter {
752            self.push_str(s);
753        }
754    }
755}
756
757impl<S1: Storage<ArrayLayout<u8>>, I1: Capacity, S2: Storage<ArrayLayout<u8>>, I2: Capacity> PartialEq<String<S2, I2>> for String<S1, I1> {
758    #[inline]
759    fn eq(&self, other: &String<S2, I2>) -> bool {
760        self.as_str() == other.as_str()
761    }
762}
763
764impl<S: Storage<ArrayLayout<u8>>, I: Capacity> Eq for String<S, I> {}
765
766impl<S: Storage<ArrayLayout<u8>>, I: Capacity> PartialEq<str> for String<S, I> {
767    #[inline]
768    fn eq(&self, other: &str) -> bool {
769        self.as_str() == other
770    }
771}
772
773impl<S: Storage<ArrayLayout<u8>>, I: Capacity> PartialEq<&str> for String<S, I> {
774    #[inline]
775    fn eq(&self, other: &&str) -> bool {
776        self.as_str() == *other
777    }
778}
779
780impl<S1: Storage<ArrayLayout<u8>>, I1: Capacity, S2: Storage<ArrayLayout<u8>>, I2: Capacity> PartialOrd<String<S2, I2>> for String<S1, I1> {
781    #[inline]
782    fn partial_cmp(&self, other: &String<S2, I2>) -> Option<core::cmp::Ordering> {
783        self.as_str().partial_cmp(other.as_str())
784    }
785}
786
787impl<S: Storage<ArrayLayout<u8>>, I: Capacity> Ord for String<S, I> {
788    #[inline]
789    fn cmp(&self, other: &Self) -> core::cmp::Ordering {
790        self.as_str().cmp(other.as_str())
791    }
792}
793
794impl<S: Storage<ArrayLayout<u8>>, I: Capacity> fmt::Display for String<S, I> {
795    #[inline]
796    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
797        fmt::Display::fmt(&**self, f)
798    }
799}
800
801impl<S: Storage<ArrayLayout<u8>>, I: Capacity> fmt::Debug for String<S, I> {
802    #[inline]
803    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
804        fmt::Debug::fmt(&**self, f)
805    }
806}
807
808impl<S: Storage<ArrayLayout<u8>>, I: Capacity> fmt::Write for String<S, I> {
809    #[inline]
810    fn write_str(&mut self, s: &str) -> fmt::Result {
811        self.try_push_str(s).map_err(|_| fmt::Error)
812    }
813
814    #[inline]
815    fn write_char(&mut self, c: char) -> fmt::Result {
816        self.try_push(c).map_err(|_| fmt::Error)
817    }
818}
819
820impl<S: Storage<ArrayLayout<u8>>, I: Capacity> core::hash::Hash for String<S, I> {
821    #[inline]
822    fn hash<H: core::hash::Hasher>(&self, hasher: &mut H) {
823        (**self).hash(hasher);
824    }
825}
826
827impl<S: Storage<ArrayLayout<u8>>, I: Capacity> core::ops::Add<&str> for String<S, I> {
828    type Output = Self;
829
830    #[inline]
831    fn add(mut self, other: &str) -> Self {
832        self.push_str(other);
833        self
834    }
835}
836
837impl<S: Storage<ArrayLayout<u8>>, I: Capacity> core::ops::AddAssign<&str> for String<S, I> {
838    #[inline]
839    fn add_assign(&mut self, rhs: &str) {
840        self.push_str(rhs);
841    }
842}
843
844impl<'a, I: Capacity> crate::ArenaString<'a, I> {
845    /// Converts the given boxed `str` slice into a `String`.
846    /// 
847    /// # Examples
848    /// ```
849    /// use coca::arena::Arena;
850    /// use core::mem::MaybeUninit;
851    ///
852    /// # fn test() -> Option<()> {
853    /// let mut backing_region = [MaybeUninit::uninit(); 1024];
854    /// let mut arena = Arena::from(&mut backing_region[..]);
855    /// 
856    /// let boxed_str = coca::fmt!(arena, "{}", 1234567890)?;
857    /// let mut string = coca::ArenaString::<'_, usize>::from_boxed_str(boxed_str);
858    /// 
859    /// string.retain(|c| (c as u8) % 2 == 1);
860    /// assert_eq!(string, "13579");
861    /// # Some(()) }
862    /// # assert!(test().is_some());
863    /// ```
864    pub fn from_boxed_str(mut string: crate::arena::Box<'a, str>) -> Self {
865        let length = string.len();
866        unsafe { 
867            let buf = ArenaStorage::from_raw_parts(string.as_mut_ptr(), length).unwrap_unchecked();
868            Self::from_raw_parts(buf, I::from_usize(length))
869        }
870    }
871
872    /// Converts the `ArenaString` into an owned `str` slice.
873    /// 
874    /// # Examples
875    /// ```
876    /// use coca::arena::Arena;
877    /// use core::mem::MaybeUninit;
878    ///
879    /// # fn test() -> Option<()> {
880    /// let mut backing_region = [MaybeUninit::uninit(); 1024];
881    /// let mut arena = Arena::from(&mut backing_region[..]);
882    /// 
883    /// let mut string = arena.string_with_capacity_from(16usize, "Hello, ");
884    /// string.push('W');
885    /// string.push_str("orld!");
886    /// 
887    /// let boxed_str = string.into_boxed_str();
888    /// assert_eq!(boxed_str.as_ref(), "Hello, World!");
889    /// # Some(()) }
890    /// # assert!(test().is_some());
891    /// ```
892    pub fn into_boxed_str(self) -> crate::arena::Box<'a, str> {
893        let (mut buf, len) = self.into_raw_parts();
894        let ptr = core::ptr::slice_from_raw_parts_mut(buf.get_mut_ptr(), len.as_usize());
895        unsafe {
896            let str_ptr = core::str::from_utf8_unchecked_mut(&mut *ptr);
897            crate::arena::Box::new_unchecked(str_ptr as *mut str)
898        }
899    }
900}
901
902#[cfg(feature = "alloc")]
903#[cfg_attr(docs_rs, doc(cfg(feature = "alloc")))]
904impl<I: Capacity> FromStr for String::<crate::storage::AllocStorage<ArrayLayout<u8>>, I> {
905    type Err = core::convert::Infallible;
906
907    /// Creates a new `AllocString` with the given contents, and zero excess capacity.
908    /// 
909    /// # Examples
910    /// ```
911    /// use core::str::FromStr;
912    /// let s = coca::AllocString::<usize>::from_str("abcde").unwrap();
913    /// assert_eq!(s.capacity(), s.len());
914    /// ```
915    fn from_str(string: &str) -> Result<Self, Self::Err> {
916        let mut buf = Self::with_capacity(I::from_usize(string.len()));
917        buf.push_str(string);
918        Ok(buf)
919    }
920}
921
922#[cfg(feature = "alloc")]
923#[cfg_attr(docs_rs, doc(cfg(feature = "alloc")))]
924impl<I: Capacity> String<crate::storage::AllocStorage<ArrayLayout<u8>>, I> {
925    /// Creates a new, empty `AllocString` with the specified capacity.
926    pub fn with_capacity(capacity: I) -> Self {
927        Self::from(crate::storage::AllocStorage::with_capacity(capacity.as_usize()))
928    }
929
930    /// Creates a new `AllocString` with the given capacity, and initializes it with the given content.
931    /// 
932    /// Returns [`Err`] if the given string is longer (in bytes) than `capacity`.
933    /// 
934    /// # Examples
935    /// ```
936    /// let s = coca::AllocString::try_from_str_with_capacity("abcde", 8usize).unwrap();
937    /// assert_eq!(s.capacity(), 8);
938    /// assert_eq!(s, "abcde");
939    /// 
940    /// assert!(coca::AllocString::try_from_str_with_capacity("abcde", 4usize).is_err());
941    /// ```
942    pub fn try_from_str_with_capacity(string: &str, capacity: I) -> crate::Result<Self> {
943        let cap = capacity.as_usize();
944        if string.len() > cap { return CapacityError::new(); }
945
946        let mut buf = Self::with_capacity(capacity);
947        buf.push_str(string);
948        Ok(buf)
949    }
950
951    /// Creates a new `AllocString` with the given capacity, and initializes it with the given content.
952    /// 
953    /// # Panics
954    /// Panics if the given string is longer (in bytes) than `capacity`.
955    /// See [`try_from_str_with_capacity`](String::try_from_str_with_capacity)
956    /// for a checked version that never panics.
957    pub fn from_str_with_capacity(string: &str, capacity: I) -> Self {
958        Self::try_from_str_with_capacity(string, capacity).expect("given string is longer than capacity")
959    }
960}
961
962impl<I: Capacity, const C: usize> String<InlineStorage<u8, C>, I> {
963    /// Constructs a new, empty `String` backed by an inline array.
964    pub fn new() -> Self {
965        String { vec: Vec::new() }
966    }
967}
968
969impl<I: Capacity, const C: usize> FromStr for String<InlineStorage<u8, C>, I> {
970    type Err = CapacityError;
971    /// Constructs a new `String` backed by an inline array, initialized with the given contents.
972    /// 
973    /// Returns [`Err`] if the given string is longer than `C` bytes.
974    /// 
975    /// # Examples
976    /// ```
977    /// use core::str::FromStr;
978    /// let s = coca::InlineString::<8>::from_str("abcde").unwrap();
979    /// assert_eq!(s.capacity(), 8);
980    /// assert_eq!(s, "abcde");
981    /// 
982    /// assert!(coca::InlineString::<4>::from_str("abcde").is_err());
983    /// ```
984    fn from_str(string: &str) -> Result<Self, Self::Err> {
985        if string.len() <= C {
986            let mut result = Self::new();
987            result.push_str(string);
988            Ok(result)
989        } else {
990            CapacityError::new()
991        }
992    }
993}
994
995impl<I: Capacity, const C: usize> Default for String<InlineStorage<u8, C>, I> {
996    fn default() -> Self {
997        Self::new()
998    }
999}
1000
1001/// A draining iterator for [`String`].
1002/// 
1003/// This struct is created by the [`drain`](String::drain) method on `String`.
1004/// See its documentation for more.
1005pub struct Drain<'a, S: Storage<ArrayLayout<u8>>, I: Capacity> {
1006    parent: *mut String<S, I>,
1007    target_range: Range<I>,
1008    iter: str::Chars<'a>,
1009}
1010
1011impl<S: Storage<ArrayLayout<u8>>, I: Capacity> Drain<'_, S, I> {
1012    /// Returns the remaining (sub)string of this iterator as a slice.
1013    pub fn as_str(&self) -> &str {
1014        self.iter.as_str()
1015    }
1016}
1017
1018impl<S: Storage<ArrayLayout<u8>>, I: Capacity> fmt::Debug for Drain<'_, S, I> {
1019    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1020        f.debug_tuple("Drain").field(&self.as_str()).finish()
1021    }
1022}
1023
1024impl<S: Storage<ArrayLayout<u8>>, I: Capacity> AsRef<str> for Drain<'_, S, I> {
1025    fn as_ref(&self) -> &str {
1026        self.as_str()
1027    }
1028}
1029
1030impl<S: Storage<ArrayLayout<u8>>, I: Capacity> AsRef<[u8]> for Drain<'_, S, I> {
1031    fn as_ref(&self) -> &[u8] {
1032        self.iter.as_str().as_bytes()
1033    }
1034}
1035
1036impl<S: Storage<ArrayLayout<u8>>, I: Capacity> Iterator for Drain<'_, S, I> {
1037    type Item = char;
1038
1039    #[inline]
1040    fn next(&mut self) -> Option<char> {
1041        self.iter.next()
1042    }
1043
1044    #[inline]
1045    fn size_hint(&self) -> (usize, Option<usize>) {
1046        self.iter.size_hint()
1047    }
1048
1049    #[inline]
1050    fn last(mut self) -> Option<char> {
1051        self.next_back()
1052    }
1053}
1054
1055impl<S: Storage<ArrayLayout<u8>>, I: Capacity> DoubleEndedIterator for Drain<'_, S, I> {
1056    #[inline]
1057    fn next_back(&mut self) -> Option<char> {
1058        self.iter.next_back()
1059    }
1060}
1061
1062impl<S: Storage<ArrayLayout<u8>>, I: Capacity> core::iter::FusedIterator for Drain<'_, S, I> {}
1063
1064impl<S: Storage<ArrayLayout<u8>>, I: Capacity> Drop for Drain<'_, S, I> {
1065    fn drop(&mut self) {
1066        unsafe {
1067            let vec = (*self.parent).as_mut_vec();
1068            vec.drain(self.target_range.clone());
1069        }
1070    }
1071}