core/bstr/
mod.rs

1//! The `ByteStr` type and trait implementations.
2
3mod traits;
4
5#[unstable(feature = "bstr_internals", issue = "none")]
6pub use traits::{impl_partial_eq, impl_partial_eq_n, impl_partial_eq_ord};
7
8use crate::borrow::{Borrow, BorrowMut};
9use crate::fmt;
10use crate::ops::{Deref, DerefMut, DerefPure};
11
12/// A wrapper for `&[u8]` representing a human-readable string that's conventionally, but not
13/// always, UTF-8.
14///
15/// Unlike `&str`, this type permits non-UTF-8 contents, making it suitable for user input,
16/// non-native filenames (as `Path` only supports native filenames), and other applications that
17/// need to round-trip whatever data the user provides.
18///
19/// For an owned, growable byte string buffer, use
20/// [`ByteString`](../../std/bstr/struct.ByteString.html).
21///
22/// `ByteStr` implements `Deref` to `[u8]`, so all methods available on `[u8]` are available on
23/// `ByteStr`.
24///
25/// # Representation
26///
27/// A `&ByteStr` has the same representation as a `&str`. That is, a `&ByteStr` is a wide pointer
28/// which includes a pointer to some bytes and a length.
29///
30/// # Trait implementations
31///
32/// The `ByteStr` type has a number of trait implementations, and in particular, defines equality
33/// and comparisons between `&ByteStr`, `&str`, and `&[u8]`, for convenience.
34///
35/// The `Debug` implementation for `ByteStr` shows its bytes as a normal string, with invalid UTF-8
36/// presented as hex escape sequences.
37///
38/// The `Display` implementation behaves as if the `ByteStr` were first lossily converted to a
39/// `str`, with invalid UTF-8 presented as the Unicode replacement character (�).
40#[unstable(feature = "bstr", issue = "134915")]
41#[repr(transparent)]
42#[doc(alias = "BStr")]
43pub struct ByteStr(pub [u8]);
44
45impl ByteStr {
46    /// Creates a `ByteStr` slice from anything that can be converted to a byte slice.
47    ///
48    /// This is a zero-cost conversion.
49    ///
50    /// # Example
51    ///
52    /// You can create a `ByteStr` from a byte array, a byte slice or a string slice:
53    ///
54    /// ```
55    /// # #![feature(bstr)]
56    /// # use std::bstr::ByteStr;
57    /// let a = ByteStr::new(b"abc");
58    /// let b = ByteStr::new(&b"abc"[..]);
59    /// let c = ByteStr::new("abc");
60    ///
61    /// assert_eq!(a, b);
62    /// assert_eq!(a, c);
63    /// ```
64    #[inline]
65    #[unstable(feature = "bstr", issue = "134915")]
66    pub fn new<B: ?Sized + AsRef<[u8]>>(bytes: &B) -> &Self {
67        ByteStr::from_bytes(bytes.as_ref())
68    }
69
70    #[doc(hidden)]
71    #[unstable(feature = "bstr_internals", issue = "none")]
72    #[inline]
73    pub fn from_bytes(slice: &[u8]) -> &Self {
74        // SAFETY: `ByteStr` is a transparent wrapper around `[u8]`, so we can turn a reference to
75        // the wrapped type into a reference to the wrapper type.
76        unsafe { &*(slice as *const [u8] as *const Self) }
77    }
78
79    #[doc(hidden)]
80    #[unstable(feature = "bstr_internals", issue = "none")]
81    #[inline]
82    pub fn from_bytes_mut(slice: &mut [u8]) -> &mut Self {
83        // SAFETY: `ByteStr` is a transparent wrapper around `[u8]`, so we can turn a reference to
84        // the wrapped type into a reference to the wrapper type.
85        unsafe { &mut *(slice as *mut [u8] as *mut Self) }
86    }
87
88    #[doc(hidden)]
89    #[unstable(feature = "bstr_internals", issue = "none")]
90    #[inline]
91    pub fn as_bytes(&self) -> &[u8] {
92        &self.0
93    }
94
95    #[doc(hidden)]
96    #[unstable(feature = "bstr_internals", issue = "none")]
97    #[inline]
98    pub fn as_bytes_mut(&mut self) -> &mut [u8] {
99        &mut self.0
100    }
101}
102
103#[unstable(feature = "bstr", issue = "134915")]
104impl Deref for ByteStr {
105    type Target = [u8];
106
107    #[inline]
108    fn deref(&self) -> &[u8] {
109        &self.0
110    }
111}
112
113#[unstable(feature = "bstr", issue = "134915")]
114impl DerefMut for ByteStr {
115    #[inline]
116    fn deref_mut(&mut self) -> &mut [u8] {
117        &mut self.0
118    }
119}
120
121#[unstable(feature = "deref_pure_trait", issue = "87121")]
122unsafe impl DerefPure for ByteStr {}
123
124#[unstable(feature = "bstr", issue = "134915")]
125impl fmt::Debug for ByteStr {
126    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
127        write!(f, "\"")?;
128        for chunk in self.utf8_chunks() {
129            for c in chunk.valid().chars() {
130                match c {
131                    '\0' => write!(f, "\\0")?,
132                    '\x01'..='\x7f' => write!(f, "{}", (c as u8).escape_ascii())?,
133                    _ => write!(f, "{}", c.escape_debug())?,
134                }
135            }
136            write!(f, "{}", chunk.invalid().escape_ascii())?;
137        }
138        write!(f, "\"")?;
139        Ok(())
140    }
141}
142
143#[unstable(feature = "bstr", issue = "134915")]
144impl fmt::Display for ByteStr {
145    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
146        fn fmt_nopad(this: &ByteStr, f: &mut fmt::Formatter<'_>) -> fmt::Result {
147            for chunk in this.utf8_chunks() {
148                f.write_str(chunk.valid())?;
149                if !chunk.invalid().is_empty() {
150                    f.write_str("\u{FFFD}")?;
151                }
152            }
153            Ok(())
154        }
155
156        let Some(align) = f.align() else {
157            return fmt_nopad(self, f);
158        };
159        let nchars: usize = self
160            .utf8_chunks()
161            .map(|chunk| {
162                chunk.valid().chars().count() + if chunk.invalid().is_empty() { 0 } else { 1 }
163            })
164            .sum();
165        let padding = f.width().unwrap_or(0).saturating_sub(nchars);
166        let fill = f.fill();
167        let (lpad, rpad) = match align {
168            fmt::Alignment::Left => (0, padding),
169            fmt::Alignment::Right => (padding, 0),
170            fmt::Alignment::Center => {
171                let half = padding / 2;
172                (half, half + padding % 2)
173            }
174        };
175        for _ in 0..lpad {
176            write!(f, "{fill}")?;
177        }
178        fmt_nopad(self, f)?;
179        for _ in 0..rpad {
180            write!(f, "{fill}")?;
181        }
182
183        Ok(())
184    }
185}
186
187#[unstable(feature = "bstr", issue = "134915")]
188impl AsRef<[u8]> for ByteStr {
189    #[inline]
190    fn as_ref(&self) -> &[u8] {
191        &self.0
192    }
193}
194
195#[unstable(feature = "bstr", issue = "134915")]
196impl AsRef<ByteStr> for ByteStr {
197    #[inline]
198    fn as_ref(&self) -> &ByteStr {
199        self
200    }
201}
202
203// `impl AsRef<ByteStr> for [u8]` omitted to avoid widespread inference failures
204
205#[unstable(feature = "bstr", issue = "134915")]
206impl AsRef<ByteStr> for str {
207    #[inline]
208    fn as_ref(&self) -> &ByteStr {
209        ByteStr::new(self)
210    }
211}
212
213#[unstable(feature = "bstr", issue = "134915")]
214impl AsMut<[u8]> for ByteStr {
215    #[inline]
216    fn as_mut(&mut self) -> &mut [u8] {
217        &mut self.0
218    }
219}
220
221// `impl AsMut<ByteStr> for [u8]` omitted to avoid widespread inference failures
222
223// `impl Borrow<ByteStr> for [u8]` omitted to avoid widespread inference failures
224
225// `impl Borrow<ByteStr> for str` omitted to avoid widespread inference failures
226
227#[unstable(feature = "bstr", issue = "134915")]
228impl Borrow<[u8]> for ByteStr {
229    #[inline]
230    fn borrow(&self) -> &[u8] {
231        &self.0
232    }
233}
234
235// `impl BorrowMut<ByteStr> for [u8]` omitted to avoid widespread inference failures
236
237#[unstable(feature = "bstr", issue = "134915")]
238impl BorrowMut<[u8]> for ByteStr {
239    #[inline]
240    fn borrow_mut(&mut self) -> &mut [u8] {
241        &mut self.0
242    }
243}
244
245#[unstable(feature = "bstr", issue = "134915")]
246impl<'a> Default for &'a ByteStr {
247    fn default() -> Self {
248        ByteStr::from_bytes(b"")
249    }
250}
251
252#[unstable(feature = "bstr", issue = "134915")]
253impl<'a> Default for &'a mut ByteStr {
254    fn default() -> Self {
255        ByteStr::from_bytes_mut(&mut [])
256    }
257}
258
259// Omitted due to inference failures
260//
261// #[unstable(feature = "bstr", issue = "134915")]
262// impl<'a, const N: usize> From<&'a [u8; N]> for &'a ByteStr {
263//     #[inline]
264//     fn from(s: &'a [u8; N]) -> Self {
265//         ByteStr::from_bytes(s)
266//     }
267// }
268//
269// #[unstable(feature = "bstr", issue = "134915")]
270// impl<'a> From<&'a [u8]> for &'a ByteStr {
271//     #[inline]
272//     fn from(s: &'a [u8]) -> Self {
273//         ByteStr::from_bytes(s)
274//     }
275// }
276
277// Omitted due to slice-from-array-issue-113238:
278//
279// #[unstable(feature = "bstr", issue = "134915")]
280// impl<'a> From<&'a ByteStr> for &'a [u8] {
281//     #[inline]
282//     fn from(s: &'a ByteStr) -> Self {
283//         &s.0
284//     }
285// }
286//
287// #[unstable(feature = "bstr", issue = "134915")]
288// impl<'a> From<&'a mut ByteStr> for &'a mut [u8] {
289//     #[inline]
290//     fn from(s: &'a mut ByteStr) -> Self {
291//         &mut s.0
292//     }
293// }
294
295// Omitted due to inference failures
296//
297// #[unstable(feature = "bstr", issue = "134915")]
298// impl<'a> From<&'a str> for &'a ByteStr {
299//     #[inline]
300//     fn from(s: &'a str) -> Self {
301//         ByteStr::from_bytes(s.as_bytes())
302//     }
303// }
304
305#[unstable(feature = "bstr", issue = "134915")]
306impl<'a> TryFrom<&'a ByteStr> for &'a str {
307    type Error = crate::str::Utf8Error;
308
309    #[inline]
310    fn try_from(s: &'a ByteStr) -> Result<Self, Self::Error> {
311        crate::str::from_utf8(&s.0)
312    }
313}
314
315#[unstable(feature = "bstr", issue = "134915")]
316impl<'a> TryFrom<&'a mut ByteStr> for &'a mut str {
317    type Error = crate::str::Utf8Error;
318
319    #[inline]
320    fn try_from(s: &'a mut ByteStr) -> Result<Self, Self::Error> {
321        crate::str::from_utf8_mut(&mut s.0)
322    }
323}
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy