generic_str/
convert.rs

1use core::str::Utf8Error;
2
3use crate::string_base::StringBase;
4
5/// Converts a slice of bytes to a string slice.
6///
7/// A string slice ([`&str`]) is made of bytes ([`u8`]), and a byte slice
8/// ([`&[u8]`][byteslice]) is made of bytes, so this function converts between
9/// the two. Not all byte slices are valid string slices, however: [`&str`] requires
10/// that it is valid UTF-8. `from_utf8()` checks to ensure that the bytes are valid
11/// UTF-8, and then does the conversion.
12///
13/// [`&str`]: crate::str
14/// [byteslice]: slice
15///
16/// If you are sure that the byte slice is valid UTF-8, and you don't want to
17/// incur the overhead of the validity check, there is an unsafe version of
18/// this function, [`from_utf8_unchecked`], which has the same
19/// behavior but skips the check.
20///
21/// If you need a `String` instead of a `&str`, consider
22/// [`String::from_utf8`][string].
23///
24/// [string]: StringBase::from_utf8
25///
26/// Because you can stack-allocate a `[u8; N]`, and you can take a
27/// [`&[u8]`][byteslice] of it, this function is one way to have a
28/// stack-allocated string. There is an example of this in the
29/// examples section below.
30///
31/// [byteslice]: slice
32///
33/// # Errors
34///
35/// Returns `Err` if the slice is not UTF-8 with a description as to why the
36/// provided slice is not UTF-8.
37///
38/// # Examples
39///
40/// Basic usage:
41///
42/// ```
43/// # use generic_str::str;
44/// // some bytes, in a vector
45/// let sparkle_heart = vec![240, 159, 146, 150];
46///
47/// // We know these bytes are valid, so just use `unwrap()`.
48/// let sparkle_heart = generic_str::from_utf8(&sparkle_heart).unwrap();
49///
50/// assert_eq!(sparkle_heart, <&str>::from("💖"));
51/// ```
52///
53/// Incorrect bytes:
54///
55/// ```
56/// // some invalid bytes, in a vector
57/// let sparkle_heart = vec![0, 159, 146, 150];
58///
59/// assert!(generic_str::from_utf8(&sparkle_heart).is_err());
60/// ```
61///
62/// See the docs for [`Utf8Error`] for more details on the kinds of
63/// errors that can be returned.
64///
65/// A "stack allocated string":
66///
67/// ```
68/// # use generic_str::str;
69/// // some bytes, in a stack-allocated array
70/// let sparkle_heart = [240, 159, 146, 150];
71///
72/// // We know these bytes are valid, so just use `unwrap()`.
73/// let sparkle_heart = generic_str::from_utf8(&sparkle_heart).unwrap();
74///
75/// assert_eq!(sparkle_heart, <&str>::from("💖"));
76/// ```
77pub fn from_utf8(v: &[u8]) -> Result<&StringBase<[u8]>, Utf8Error> {
78    Ok(core::str::from_utf8(v)?.into())
79}
80
81/// Converts a mutable slice of bytes to a mutable string slice.
82///
83/// # Examples
84///
85/// Basic usage:
86///
87/// ```
88/// # use generic_str::str;
89/// // "Hello, Rust!" as a mutable vector
90/// let mut hellorust = vec![72, 101, 108, 108, 111, 44, 32, 82, 117, 115, 116, 33];
91///
92/// // As we know these bytes are valid, we can use `unwrap()`
93/// let outstr = generic_str::from_utf8_mut(&mut hellorust).unwrap();
94///
95/// assert_eq!(outstr, <&str>::from("Hello, Rust!"));
96/// ```
97///
98/// Incorrect bytes:
99///
100/// ```
101/// // Some invalid bytes in a mutable vector
102/// let mut invalid = vec![128, 223];
103///
104/// assert!(generic_str::from_utf8_mut(&mut invalid).is_err());
105/// ```
106/// See the docs for [`Utf8Error`] for more details on the kinds of
107/// errors that can be returned.
108pub fn from_utf8_mut(v: &mut [u8]) -> Result<&mut StringBase<[u8]>, Utf8Error> {
109    Ok(core::str::from_utf8_mut(v)?.into())
110}
111
112/// Converts a slice of bytes to a string slice without checking
113/// that the string contains valid UTF-8.
114///
115/// See the safe version, [`from_utf8`], for more information.
116///
117/// # Safety
118///
119/// This function is unsafe because it does not check that the bytes passed to
120/// it are valid UTF-8. If this constraint is violated, undefined behavior
121/// results, as the rest of Rust assumes that [`&str`]s are valid UTF-8.
122///
123/// [`&str`]: str
124///
125/// # Examples
126///
127/// Basic usage:
128///
129/// ```
130/// # use generic_str::str;
131/// // some bytes, in a vector
132/// let sparkle_heart = vec![240, 159, 146, 150];
133///
134/// let sparkle_heart = unsafe {
135///     generic_str::from_utf8_unchecked(&sparkle_heart)
136/// };
137///
138/// assert_eq!(sparkle_heart, <&str>::from("💖"));
139/// ```
140#[inline]
141pub const unsafe fn from_utf8_unchecked(v: &[u8]) -> &StringBase<[u8]> {
142    // SAFETY: the caller must guarantee that the bytes `v` are valid UTF-8.
143    // Also relies on `&str` and `&[u8]` having the same layout.
144    core::mem::transmute(v)
145}
146
147/// Converts a slice of bytes to a string slice without checking
148/// that the string contains valid UTF-8.
149///
150/// See the safe version, [`from_utf8`], for more information.
151///
152/// # Safety
153///
154/// This function is unsafe because it does not check that the bytes passed to
155/// it are valid UTF-8. If this constraint is violated, undefined behavior
156/// results, as the rest of Rust assumes that [`&str`]s are valid UTF-8.
157///
158/// [`&str`]: str
159///
160/// # Examples
161///
162/// Basic usage:
163///
164/// ```
165/// # use generic_str::str;
166/// // some bytes, in a vector
167/// let sparkle_heart = vec![240, 159, 146, 150];
168///
169/// let sparkle_heart = unsafe {
170///     generic_str::from_utf8_unchecked(&sparkle_heart)
171/// };
172///
173/// assert_eq!(sparkle_heart, <&str>::from("💖"));
174/// ```
175#[inline]
176pub const unsafe fn from_utf8_unchecked_mut(v: &mut [u8]) -> &mut StringBase<[u8]> {
177    // SAFETY: the caller must guarantee that the bytes `v` are valid UTF-8.
178    // Also relies on `&str` and `&[u8]` having the same layout.
179    core::mem::transmute(v)
180}