Skip to main content

musli_core/alloc/
string.rs

1use core::borrow::Borrow;
2use core::cmp::Ordering;
3use core::error::Error;
4use core::fmt;
5use core::marker::PhantomData;
6use core::ops::Deref;
7use core::str::{self, Utf8Error};
8
9#[cfg(feature = "alloc")]
10use rust_alloc::borrow::Cow;
11
12use crate::de::UnsizedVisitor;
13use crate::{Context, Decode, Decoder, Encode, Encoder};
14
15use super::{AllocError, Allocator, FromAllocator, GlobalAllocator, Vec};
16
17/// Collect a string into a string buffer.
18#[inline]
19pub(crate) fn collect_string<A>(alloc: A, value: impl fmt::Display) -> Result<String<A>, AllocError>
20where
21    A: Allocator,
22{
23    use core::fmt::Write;
24
25    let mut string = String::new_in(alloc);
26
27    if write!(string, "{value}").is_err() {
28        return Err(AllocError);
29    }
30
31    Ok(string)
32}
33
34/// A Müsli-allocated UTF-8–encoded, growable string.
35///
36/// `String` is the most common string type. It has ownership over the contents
37/// of the string, stored in a allocated buffer. It is closely related to its
38/// borrowed counterpart, the primitive [`str`].
39///
40/// This is a [`String`][alloc-string] style type capable of using the
41/// [`Allocator`] provided through a [`Context`]. Therefore it can be safely
42/// used in no-alloc environments.
43///
44/// [alloc-string]: rust_alloc::string::String
45/// [`str`]: prim@str
46pub struct String<A>
47where
48    A: Allocator,
49{
50    vec: Vec<u8, A>,
51}
52
53/// A possible error value when converting a `String` from a UTF-8 byte vector.
54///
55/// This type is the error type for the [`from_utf8`] method on [`String`]. It
56/// is designed in such a way to carefully avoid reallocations: the
57/// [`into_bytes`] method will give back the byte vector that was used in the
58/// conversion attempt.
59///
60/// [`from_utf8`]: String::from_utf8
61/// [`into_bytes`]: FromUtf8Error::into_bytes
62///
63/// The [`Utf8Error`] type provided by [`std::str`] represents an error that may
64/// occur when converting a slice of [`u8`]s to a [`&str`]. In this sense, it's
65/// an analogue to `FromUtf8Error`, and you can get one from a `FromUtf8Error`
66/// through the [`utf8_error`] method.
67///
68/// [`Utf8Error`]: str::Utf8Error "std::str::Utf8Error"
69/// [`std::str`]: core::str "std::str"
70/// [`&str`]: prim@str "&str"
71/// [`utf8_error`]: FromUtf8Error::utf8_error
72///
73/// # Examples
74///
75/// ```
76/// // some invalid bytes, in a vector
77/// let bytes = vec![0, 159];
78///
79/// let value = String::from_utf8(bytes);
80///
81/// assert!(value.is_err());
82/// assert_eq!(vec![0, 159], value.unwrap_err().into_bytes());
83/// ```
84pub struct FromUtf8Error<A>
85where
86    A: Allocator,
87{
88    bytes: Vec<u8, A>,
89    error: Utf8Error,
90}
91
92impl<A> String<A>
93where
94    A: Allocator,
95{
96    /// Creates a new empty `String`.
97    ///
98    /// Given that the `String` is empty, this will not allocate any initial
99    /// buffer. While that means that this initial operation is very
100    /// inexpensive, it may cause excessive allocation later when you add data.
101    /// If you have an idea of how much data the `String` will hold, consider
102    /// the [`with_capacity_in`] method to prevent excessive re-allocation.
103    ///
104    /// [`with_capacity_in`]: String::with_capacity_in
105    ///
106    /// # Examples
107    ///
108    /// ```
109    /// use musli::alloc::{AllocError, String};
110    ///
111    /// musli::alloc::default(|alloc| {
112    ///     _ = String::new_in(alloc);
113    ///     Ok::<_, AllocError>(())
114    /// });
115    /// # Ok::<_, AllocError>(())
116    /// ```
117    #[inline]
118    pub fn new_in(alloc: A) -> Self {
119        Self {
120            vec: Vec::new_in(alloc),
121        }
122    }
123
124    /// Creates a new empty `String` with at least the specified capacity.
125    ///
126    /// `String`s have an internal buffer to hold their data. The capacity is
127    /// the length of that buffer, and can be queried with the [`capacity`]
128    /// method. This method creates an empty `String`, but one with an initial
129    /// buffer that can hold at least `capacity` bytes. This is useful when you
130    /// may be appending a bunch of data to the `String`, reducing the number of
131    /// reallocations it needs to do.
132    ///
133    /// [`capacity`]: String::capacity
134    ///
135    /// If the given capacity is `0`, no allocation will occur, and this method
136    /// is identical to the [`new_in`] method.
137    ///
138    /// [`new_in`]: String::new_in
139    ///
140    /// # Examples
141    ///
142    /// ```
143    /// use musli::alloc::{AllocError, String};
144    ///
145    /// musli::alloc::default(|alloc| {
146    ///     let mut s = String::with_capacity_in(10, alloc)?;
147    ///
148    ///     // The String contains no chars, even though it has capacity for more
149    ///     assert_eq!(s.len(), 0);
150    ///
151    ///     // These are all done without reallocating...
152    ///     let cap = s.capacity();
153    ///
154    ///     for _ in 0..10 {
155    ///         s.push('a')?;
156    ///     }
157    ///
158    ///     assert_eq!(s.capacity(), cap);
159    ///
160    ///     // ...but this may make the string reallocate
161    ///     s.push('a')?;
162    ///     Ok::<_, AllocError>(())
163    /// })?;
164    /// # Ok::<_, AllocError>(())
165    /// ```
166    #[inline]
167    pub fn with_capacity_in(capacity: usize, alloc: A) -> Result<Self, AllocError> {
168        Ok(Self {
169            vec: Vec::with_capacity_in(capacity, alloc)?,
170        })
171    }
172
173    /// Coerce into a std string.
174    #[cfg(feature = "alloc")]
175    pub fn into_std(self) -> Result<rust_alloc::string::String, Self> {
176        match self.vec.into_std() {
177            Ok(vec) => {
178                // SAFETY: The buffer is guaranteed to be valid utf-8.
179                unsafe { Ok(rust_alloc::string::String::from_utf8_unchecked(vec)) }
180            }
181            Err(vec) => Err(Self { vec }),
182        }
183    }
184
185    /// Converts a vector of bytes to a `String`.
186    ///
187    /// A string ([`String`]) is made of bytes ([`u8`]), and a vector of bytes
188    /// ([`Vec<u8>`]) is made of bytes, so this function converts between the
189    /// two. Not all byte slices are valid `String`s, however: `String` requires
190    /// that it is valid UTF-8. `from_utf8()` checks to ensure that the bytes
191    /// are valid UTF-8, and then does the conversion.
192    ///
193    /// If you are sure that the byte slice is valid UTF-8, and you don't want
194    /// to incur the overhead of the validity check, there is an unsafe version
195    /// of this function, [`from_utf8_unchecked`], which has the same behavior
196    /// but skips the check.
197    ///
198    /// This method will take care to not copy the vector, for efficiency's
199    /// sake.
200    ///
201    /// If you need a [`&str`] instead of a `String`, consider
202    /// [`str::from_utf8`].
203    ///
204    /// The inverse of this method is [`into_bytes`].
205    ///
206    /// # Errors
207    ///
208    /// Returns [`Err`] if the slice is not UTF-8 with a description as to why
209    /// the provided bytes are not UTF-8. The vector you moved in is also
210    /// included.
211    ///
212    /// # Examples
213    ///
214    /// Basic usage:
215    ///
216    /// ```
217    /// use musli::alloc::{AllocError, Vec, String};
218    ///
219    /// musli::alloc::default(|alloc| {
220    ///     let mut sparkle_heart = Vec::<u8, _>::new_in(alloc);
221    ///     // some bytes, in a vector
222    ///     sparkle_heart.extend_from_slice(&[240, 159, 146, 150])?;
223    ///
224    ///     let sparkle_heart = String::from_utf8(sparkle_heart).unwrap();
225    ///
226    ///     assert_eq!("💖", sparkle_heart);
227    ///     Ok::<_, AllocError>(())
228    /// });
229    /// # Ok::<_, AllocError>(())
230    /// ```
231    ///
232    /// Incorrect bytes:
233    ///
234    /// ```
235    /// use musli::alloc::{AllocError, Vec, String};
236    ///
237    /// musli::alloc::default(|alloc| {
238    ///     let mut sparkle_heart = Vec::<u8, _>::new_in(alloc);
239    ///     // some bytes, in a vector
240    ///     sparkle_heart.extend_from_slice(&[0, 159, 146, 150])?;
241    ///
242    ///     assert!(String::from_utf8(sparkle_heart).is_err());
243    ///     Ok::<_, AllocError>(())
244    /// });
245    /// # Ok::<_, AllocError>(())
246    /// ```
247    ///
248    /// See the docs for [`FromUtf8Error`] for more details on what you can do
249    /// with this error.
250    ///
251    /// [`from_utf8_unchecked`]: String::from_utf8_unchecked
252    /// [`Vec<u8>`]: crate::alloc::Vec "Vec"
253    /// [`&str`]: prim@str "&str"
254    /// [`into_bytes`]: String::into_bytes
255    #[inline]
256    pub fn from_utf8(vec: Vec<u8, A>) -> Result<String<A>, FromUtf8Error<A>> {
257        match str::from_utf8(&vec) {
258            Ok(..) => Ok(String { vec }),
259            Err(e) => Err(FromUtf8Error {
260                bytes: vec,
261                error: e,
262            }),
263        }
264    }
265
266    /// Converts a vector of bytes to a `String` without checking that the
267    /// string contains valid UTF-8.
268    ///
269    /// See the safe version, [`from_utf8`], for more details.
270    ///
271    /// [`from_utf8`]: String::from_utf8
272    ///
273    /// # Safety
274    ///
275    /// This function is unsafe because it does not check that the bytes passed
276    /// to it are valid UTF-8. If this constraint is violated, it may cause
277    /// memory unsafety issues with future users of the `String`, as the rest of
278    /// the standard library assumes that `String`s are valid UTF-8.
279    ///
280    /// # Examples
281    ///
282    /// ```
283    /// use musli::alloc::{AllocError, Vec, String};
284    ///
285    /// musli::alloc::default(|alloc| {
286    ///     let mut sparkle_heart = Vec::<u8, _>::new_in(alloc);
287    ///     // some bytes, in a vector
288    ///     sparkle_heart.extend_from_slice(&[240, 159, 146, 150])?;
289    ///
290    ///     let sparkle_heart = unsafe {
291    ///         String::from_utf8_unchecked(sparkle_heart)
292    ///     };
293    ///
294    ///     assert_eq!("💖", sparkle_heart);
295    ///     Ok::<_, AllocError>(())
296    /// });
297    /// # Ok::<_, AllocError>(())
298    /// ```
299    #[inline]
300    #[must_use]
301    pub unsafe fn from_utf8_unchecked(vec: Vec<u8, A>) -> String<A> {
302        String { vec }
303    }
304
305    /// Converts a `String` into a byte vector.
306    ///
307    /// This consumes the `String`, so we do not need to copy its contents.
308    ///
309    /// # Examples
310    ///
311    /// ```
312    /// use musli::alloc::{AllocError, String};
313    ///
314    /// musli::alloc::default(|alloc| {
315    ///     let mut s = String::new_in(alloc);
316    ///     s.push_str("hello")?;
317    ///     let bytes = s.into_bytes();
318    ///
319    ///     assert_eq!(&[104, 101, 108, 108, 111][..], &bytes[..]);
320    ///     Ok::<_, AllocError>(())
321    /// });
322    /// # Ok::<_, AllocError>(())
323    /// ```
324    #[inline]
325    #[must_use = "`self` will be dropped if the result is not used"]
326    pub fn into_bytes(self) -> Vec<u8, A> {
327        self.vec
328    }
329
330    /// Extracts a string slice containing the entire `String`.
331    ///
332    /// # Examples
333    ///
334    /// ```
335    /// use musli::alloc::{AllocError, String};
336    ///
337    /// musli::alloc::default(|alloc| {
338    ///     let mut s = String::new_in(alloc);
339    ///     s.push_str("foo")?;
340    ///     assert_eq!(s.as_str(), "foo");
341    ///     Ok::<_, AllocError>(())
342    /// });
343    /// # Ok::<_, AllocError>(())
344    /// ```
345    #[inline]
346    pub fn as_str(&self) -> &str {
347        // SAFETY: Interactions ensure that data is valid utf-8.
348        unsafe { str::from_utf8_unchecked(self.vec.as_slice()) }
349    }
350
351    /// Appends the given [`char`] to the end of this `String`.
352    ///
353    /// # Examples
354    ///
355    /// ```
356    /// use musli::alloc::{AllocError, String};
357    ///
358    /// musli::alloc::default(|alloc| {
359    ///     let mut s = String::new_in(alloc);
360    ///
361    ///     s.push_str("abc")?;
362    ///
363    ///     s.push('1')?;
364    ///     s.push('2')?;
365    ///     s.push('3')?;
366    ///
367    ///     assert_eq!("abc123", s);
368    ///     Ok::<_, AllocError>(())
369    /// });
370    /// # Ok::<_, AllocError>(())
371    /// ```
372    #[inline]
373    pub fn push(&mut self, c: char) -> Result<(), AllocError> {
374        self.vec
375            .extend_from_slice(c.encode_utf8(&mut [0; 4]).as_bytes())
376    }
377
378    /// Appends a given string slice onto the end of this `String`.
379    ///
380    /// # Examples
381    ///
382    /// ```
383    /// use musli::alloc::{AllocError, String};
384    ///
385    /// musli::alloc::default(|alloc| {
386    ///     let mut a = String::new_in(alloc);
387    ///
388    ///     a.push_str("Hello")?;
389    ///     a.push_str(" World")?;
390    ///
391    ///     assert_eq!(a.as_str(), "Hello World");
392    ///     Ok::<_, AllocError>(())
393    /// });
394    /// # Ok::<_, AllocError>(())
395    /// ```
396    #[inline]
397    pub fn push_str(&mut self, s: &str) -> Result<(), AllocError> {
398        self.vec.extend_from_slice(s.as_bytes())
399    }
400
401    /// Returns this `String`'s capacity, in bytes.
402    ///
403    /// # Examples
404    ///
405    /// ```
406    /// use musli::alloc::{AllocError, String};
407    ///
408    /// musli::alloc::default(|alloc| {
409    ///     let s = String::with_capacity_in(10, alloc)?;
410    ///
411    ///     assert!(s.capacity() >= 10);
412    ///     Ok::<_, AllocError>(())
413    /// });
414    /// # Ok::<_, AllocError>(())
415    /// ```
416    #[inline]
417    #[must_use]
418    pub fn capacity(&self) -> usize {
419        self.vec.capacity()
420    }
421
422    /// Returns the length of this `String`, in bytes, not [`char`]s or
423    /// graphemes. In other words, it might not be what a human considers the
424    /// length of the string.
425    ///
426    /// # Examples
427    ///
428    /// ```
429    /// use musli::alloc::{AllocError, String};
430    ///
431    /// musli::alloc::default(|alloc| {
432    ///     let mut a = String::new_in(alloc);
433    ///     a.push_str("foo")?;
434    ///     assert_eq!(a.len(), 3);
435    ///
436    ///     let mut fancy_f = String::new_in(alloc);
437    ///     fancy_f.push_str("ƒoo")?;
438    ///     assert_eq!(fancy_f.len(), 4);
439    ///     assert_eq!(fancy_f.chars().count(), 3);
440    ///     Ok::<_, AllocError>(())
441    /// })?;
442    /// # Ok::<_, AllocError>(())
443    /// ```
444    #[inline]
445    #[must_use]
446    pub fn len(&self) -> usize {
447        self.vec.len()
448    }
449
450    /// Returns `true` if this `String` has a length of zero, and `false`
451    /// otherwise.
452    ///
453    /// # Examples
454    ///
455    /// ```
456    /// use musli::alloc::{AllocError, String};
457    ///
458    /// musli::alloc::default(|alloc| {
459    ///     let mut v = String::new_in(alloc);
460    ///     assert!(v.is_empty());
461    ///
462    ///     v.push('a')?;
463    ///     assert!(!v.is_empty());
464    ///     Ok::<_, AllocError>(())
465    /// })?;
466    /// # Ok::<_, AllocError>(())
467    /// ```
468    #[inline]
469    #[must_use]
470    pub fn is_empty(&self) -> bool {
471        self.len() == 0
472    }
473}
474
475impl<A> Clone for String<A>
476where
477    A: GlobalAllocator,
478{
479    #[inline]
480    fn clone(&self) -> Self {
481        Self {
482            vec: self.vec.clone(),
483        }
484    }
485}
486
487impl<A> fmt::Write for String<A>
488where
489    A: Allocator,
490{
491    #[inline]
492    fn write_char(&mut self, c: char) -> fmt::Result {
493        self.push(c).map_err(|_| fmt::Error)
494    }
495
496    #[inline]
497    fn write_str(&mut self, s: &str) -> fmt::Result {
498        self.push_str(s).map_err(|_| fmt::Error)
499    }
500}
501
502impl<A> Deref for String<A>
503where
504    A: Allocator,
505{
506    type Target = str;
507
508    #[inline]
509    fn deref(&self) -> &str {
510        unsafe { str::from_utf8_unchecked(self.vec.as_slice()) }
511    }
512}
513
514impl<A> fmt::Display for String<A>
515where
516    A: Allocator,
517{
518    #[inline]
519    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
520        self.as_str().fmt(f)
521    }
522}
523
524impl<A> fmt::Debug for String<A>
525where
526    A: Allocator,
527{
528    #[inline]
529    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
530        self.as_str().fmt(f)
531    }
532}
533
534impl<A> AsRef<str> for String<A>
535where
536    A: Allocator,
537{
538    #[inline]
539    fn as_ref(&self) -> &str {
540        self.as_str()
541    }
542}
543
544impl<A> PartialEq for String<A>
545where
546    A: Allocator,
547{
548    #[inline]
549    fn eq(&self, other: &Self) -> bool {
550        self.as_str().eq(other.as_str())
551    }
552}
553
554impl<A> Eq for String<A> where A: Allocator {}
555
556impl<A> PartialOrd for String<A>
557where
558    A: Allocator,
559{
560    #[inline]
561    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
562        Some(self.cmp(other))
563    }
564}
565
566impl<A> Ord for String<A>
567where
568    A: Allocator,
569{
570    #[inline]
571    fn cmp(&self, other: &Self) -> Ordering {
572        self.as_str().cmp(other.as_str())
573    }
574}
575
576impl<A> Borrow<str> for String<A>
577where
578    A: Allocator,
579{
580    #[inline]
581    fn borrow(&self) -> &str {
582        self
583    }
584}
585
586macro_rules! impl_eq {
587    ($lhs:ty, $rhs: ty) => {
588        #[allow(unused_lifetimes)]
589        impl<'a, 'b, A> PartialEq<$rhs> for $lhs
590        where
591            A: Allocator,
592        {
593            #[inline]
594            fn eq(&self, other: &$rhs) -> bool {
595                PartialEq::eq(&self[..], &other[..])
596            }
597
598            #[inline]
599            #[allow(clippy::partialeq_ne_impl)]
600            fn ne(&self, other: &$rhs) -> bool {
601                PartialEq::ne(&self[..], &other[..])
602            }
603        }
604
605        #[allow(unused_lifetimes)]
606        impl<'a, 'b, A> PartialEq<$lhs> for $rhs
607        where
608            A: Allocator,
609        {
610            #[inline]
611            fn eq(&self, other: &$lhs) -> bool {
612                PartialEq::eq(&self[..], &other[..])
613            }
614
615            #[inline]
616            #[allow(clippy::partialeq_ne_impl)]
617            fn ne(&self, other: &$lhs) -> bool {
618                PartialEq::ne(&self[..], &other[..])
619            }
620        }
621    };
622}
623
624impl_eq! { String<A>, str }
625impl_eq! { String<A>, &'a str }
626#[cfg(feature = "alloc")]
627impl_eq! { Cow<'a, str>, String<A> }
628
629/// Conversion from a std [`String`][std-string] to a Müsli-allocated [`String`]
630/// in a [`GlobalAllocator`] allocator.
631///
632/// [std-string]: rust_alloc::string::String
633///
634/// # Examples
635///
636/// ```
637/// use musli::alloc::{String, Global};
638///
639/// let value = std::string::String::from("Hello World");
640/// let value2 = String::<Global>::from(value);
641/// ```
642#[cfg(feature = "alloc")]
643#[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))]
644impl<A> From<rust_alloc::string::String> for String<A>
645where
646    A: GlobalAllocator,
647{
648    #[inline]
649    fn from(value: rust_alloc::string::String) -> Self {
650        Self {
651            vec: Vec::from(value.into_bytes()),
652        }
653    }
654}
655
656impl<A> fmt::Display for FromUtf8Error<A>
657where
658    A: Allocator,
659{
660    #[inline]
661    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
662        fmt::Display::fmt(&self.error, f)
663    }
664}
665
666impl<A> Error for FromUtf8Error<A> where A: Allocator {}
667
668impl<A, B> PartialEq<FromUtf8Error<B>> for FromUtf8Error<A>
669where
670    A: Allocator,
671    B: Allocator,
672{
673    #[inline]
674    fn eq(&self, other: &FromUtf8Error<B>) -> bool {
675        self.bytes == other.bytes && self.error == other.error
676    }
677}
678
679impl<A> fmt::Debug for FromUtf8Error<A>
680where
681    A: Allocator,
682{
683    #[inline]
684    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
685        f.debug_struct("FromUtf8Error")
686            .field("bytes", &self.bytes)
687            .field("error", &self.error)
688            .finish()
689    }
690}
691
692impl<A> FromUtf8Error<A>
693where
694    A: Allocator,
695{
696    /// Returns a slice of [`u8`]s bytes that were attempted to convert to a
697    /// `String`.
698    ///
699    /// # Examples
700    ///
701    /// ```
702    /// use musli::alloc::{AllocError, Vec, String};
703    ///
704    /// musli::alloc::default(|alloc| {
705    ///     let mut bytes = Vec::new_in(alloc);
706    ///     // some invalid bytes, in a vector
707    ///     bytes.extend_from_slice(&[0, 159])?;
708    ///
709    ///     let value = String::from_utf8(bytes);
710    ///
711    ///     assert_eq!(&[0, 159], value.unwrap_err().as_bytes());
712    ///     Ok::<_, AllocError>(())
713    /// });
714    /// # Ok::<_, AllocError>(())
715    /// ```
716    #[inline]
717    #[must_use]
718    pub fn as_bytes(&self) -> &[u8] {
719        &self.bytes[..]
720    }
721
722    /// Returns the bytes that were attempted to convert to a `String`.
723    ///
724    /// This method is carefully constructed to avoid allocation. It will
725    /// consume the error, moving out the bytes, so that a copy of the bytes
726    /// does not need to be made.
727    ///
728    /// # Examples
729    ///
730    /// ```
731    /// use musli::alloc::{AllocError, Vec, String};
732    ///
733    /// musli::alloc::default(|alloc| {
734    ///     let mut bytes = Vec::new_in(alloc);
735    ///     // some invalid bytes, in a vector
736    ///     bytes.extend_from_slice(&[0, 159])?;
737    ///
738    ///     let value = String::from_utf8(bytes);
739    ///
740    ///     assert_eq!(&[0, 159], value.unwrap_err().into_bytes());
741    ///     Ok::<_, AllocError>(())
742    /// });
743    /// # Ok::<_, AllocError>(())
744    /// ```
745    #[inline]
746    #[must_use = "`self` will be dropped if the result is not used"]
747    pub fn into_bytes(self) -> Vec<u8, A> {
748        self.bytes
749    }
750
751    /// Fetch a `Utf8Error` to get more details about the conversion failure.
752    ///
753    /// The [`Utf8Error`] type provided by [`std::str`] represents an error that
754    /// may occur when converting a slice of [`u8`]s to a [`&str`]. In this
755    /// sense, it's an analogue to `FromUtf8Error`. See its documentation for
756    /// more details on using it.
757    ///
758    /// [`std::str`]: core::str "std::str"
759    /// [`&str`]: prim@str "&str"
760    ///
761    /// # Examples
762    ///
763    /// ```
764    /// use musli::alloc::{AllocError, Vec, String};
765    ///
766    /// musli::alloc::default(|alloc| {
767    ///     let mut bytes = Vec::new_in(alloc);
768    ///     // some invalid bytes, in a vector
769    ///     bytes.extend_from_slice(&[0, 159])?;
770    ///
771    ///     let value = String::from_utf8(bytes);
772    ///
773    ///     let error = value.unwrap_err().utf8_error();
774    ///     // the first byte is invalid here
775    ///     assert_eq!(1, error.valid_up_to());
776    ///     Ok::<_, AllocError>(())
777    /// });
778    /// # Ok::<_, AllocError>(())
779    /// ```
780    #[inline]
781    #[must_use]
782    pub fn utf8_error(&self) -> Utf8Error {
783        self.error
784    }
785}
786
787impl<M, A> Encode<M> for String<A>
788where
789    A: Allocator,
790{
791    type Encode = str;
792
793    const IS_BITWISE_ENCODE: bool = false;
794
795    #[inline]
796    fn encode<E>(&self, encoder: E) -> Result<(), E::Error>
797    where
798        E: Encoder<Mode = M>,
799    {
800        self.as_str().encode(encoder)
801    }
802
803    #[inline]
804    fn as_encode(&self) -> &Self::Encode {
805        self
806    }
807}
808
809/// Decode implementation for a Müsli-allocated [`String`].
810///
811/// A `String<B>` can be decoded by a decoder using any allocator `A` that `B`
812/// can be obtained from through [`FromAllocator`]. So a field of type
813/// `String<Global>` can be decoded regardless of which allocator the decoder
814/// uses.
815///
816/// # Examples
817///
818/// ```
819/// use musli::alloc::String;
820/// use musli::{Allocator, Decode};
821///
822/// #[derive(Decode)]
823/// struct Struct<A> where A: Allocator {
824///     field: String<A>
825/// }
826/// ```
827///
828/// Holding a `String<Global>` requires no attributes:
829///
830/// ```
831/// use musli::alloc::{Global, String};
832/// use musli::{Decode, Encode};
833///
834/// #[derive(Encode, Decode)]
835/// struct Struct {
836///     field: String<Global>,
837/// }
838/// ```
839impl<'de, M, A, B> Decode<'de, M, A> for String<B>
840where
841    A: Allocator,
842    B: Allocator + FromAllocator<A>,
843{
844    const IS_BITWISE_DECODE: bool = false;
845
846    #[inline]
847    fn decode<D>(decoder: D) -> Result<Self, D::Error>
848    where
849        D: Decoder<'de, Mode = M, Allocator = A>,
850    {
851        struct Visitor<B>(PhantomData<B>);
852
853        #[crate::trait_defaults(crate)]
854        impl<C, B> UnsizedVisitor<'_, C, str> for Visitor<B>
855        where
856            C: Context,
857            B: Allocator + FromAllocator<C::Allocator>,
858        {
859            type Ok = String<B>;
860
861            #[inline]
862            fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
863                write!(f, "string")
864            }
865
866            #[inline]
867            fn visit_owned(
868                self,
869                cx: C,
870                value: String<Self::Allocator>,
871            ) -> Result<Self::Ok, C::Error> {
872                match B::__from_vec(value.into_bytes()) {
873                    // SAFETY: The bytes come from a string, so they are valid
874                    // UTF-8.
875                    Ok(vec) => Ok(unsafe { String::from_utf8_unchecked(vec) }),
876                    Err(vec) => {
877                        // SAFETY: The bytes come from a string, so they are
878                        // valid UTF-8.
879                        let string = unsafe { str::from_utf8_unchecked(vec.as_slice()) };
880                        self.visit_ref(cx, string)
881                    }
882                }
883            }
884
885            #[inline]
886            fn visit_ref(self, cx: C, string: &str) -> Result<Self::Ok, C::Error> {
887                let mut s = String::new_in(B::from_allocator(cx.alloc()));
888                s.push_str(string).map_err(cx.map())?;
889                Ok(s)
890            }
891        }
892
893        decoder.decode_string(Visitor(PhantomData))
894    }
895}