musli_common/str.rs
1//! Functions for working with strings. The exported implementations change
2//! depending on if the `simdutf8` feature is enabled.
3
4#[cfg(feature = "alloc")]
5use alloc::string::String;
6#[cfg(feature = "alloc")]
7use alloc::vec::Vec;
8
9use core::fmt;
10
11#[cfg(not(feature = "simdutf8"))]
12#[doc(inline)]
13pub use core::str::from_utf8;
14#[cfg(feature = "simdutf8")]
15#[doc(inline)]
16pub use simdutf8::basic::from_utf8;
17
18/// Error raised in case the UTF-8 sequence could not be decoded.
19#[non_exhaustive]
20#[derive(Debug)]
21pub struct Utf8Error;
22
23#[cfg(feature = "std")]
24impl std::error::Error for Utf8Error {}
25
26impl fmt::Display for Utf8Error {
27 #[inline]
28 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
29 write!(f, "invalid or incomplete utf-8 sequence")
30 }
31}
32
33/// The same as [`String::from_utf8`], but the implementation can different
34/// depending on if the `simdutf8` feature is enabled.
35///
36/// [`String::from_utf8`]: alloc::string::String::from_utf8
37#[inline(always)]
38#[cfg(all(feature = "alloc", not(feature = "simdutf8")))]
39pub fn from_utf8_owned(bytes: Vec<u8>) -> Result<String, Utf8Error> {
40 match String::from_utf8(bytes) {
41 Ok(string) => Ok(string),
42 Err(..) => Err(Utf8Error),
43 }
44}
45
46/// The same as [`String::from_utf8`], but the implementation can different
47/// depending on if the `simdutf8` feature is enabled.
48///
49/// [`String::from_utf8`]: alloc::string::String::from_utf8
50#[inline(always)]
51#[cfg(all(feature = "alloc", feature = "simdutf8"))]
52pub fn from_utf8_owned(bytes: Vec<u8>) -> Result<String, Utf8Error> {
53 if from_utf8(&bytes).is_err() {
54 return Err(Utf8Error);
55 }
56
57 // SAFETY: String was checked above.
58 Ok(unsafe { String::from_utf8_unchecked(bytes) })
59}