mod.rs - source
Description: Source of the Rust file `library/core/src/bstr/mod.rs`.

#
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    #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
    67    pub const fn new<B: ?Sized + [const] AsRef<[u8]>>(bytes: &B) -> &Self {
    68        ByteStr::from_bytes(bytes.as_ref())
    69    }
    70
    71    /// Returns the same string as `&ByteStr`.
    72    ///
    73    /// This method is redundant when used directly on `&ByteStr`, but
    74    /// it helps dereferencing other "container" types,
    75    /// for example `Box<ByteStr>` or `Arc<ByteStr>`.
    76    #[inline]
    77    // #[unstable(feature = "str_as_str", issue = "130366")]
    78    #[unstable(feature = "bstr", issue = "134915")]
    79    pub const fn as_byte_str(&self) -> &ByteStr {
    80        self
    81    }
    82
    83    /// Returns the same string as `&mut ByteStr`.
    84    ///
    85    /// This method is redundant when used directly on `&mut ByteStr`, but
    86    /// it helps dereferencing other "container" types,
    87    /// for example `Box<ByteStr>` or `MutexGuard<ByteStr>`.
    88    #[inline]
    89    // #[unstable(feature = "str_as_str", issue = "130366")]
    90    #[unstable(feature = "bstr", issue = "134915")]
    91    pub const fn as_mut_byte_str(&mut self) -> &mut ByteStr {
    92        self
    93    }
    94
    95    #[doc(hidden)]
    96    #[unstable(feature = "bstr_internals", issue = "none")]
    97    #[inline]
    98    #[rustc_const_unstable(feature = "bstr_internals", issue = "none")]
    99    pub const fn from_bytes(slice: &[u8]) -> &Self {
    100        // SAFETY: `ByteStr` is a transparent wrapper around `[u8]`, so we can turn a reference to
    101        // the wrapped type into a reference to the wrapper type.
    102        unsafe { &*(slice as *const [u8] as *const Self) }
    103    }
    104
    105    #[doc(hidden)]
    106    #[unstable(feature = "bstr_internals", issue = "none")]
    107    #[inline]
    108    #[rustc_const_unstable(feature = "bstr_internals", issue = "none")]
    109    pub const fn from_bytes_mut(slice: &mut [u8]) -> &mut Self {
    110        // SAFETY: `ByteStr` is a transparent wrapper around `[u8]`, so we can turn a reference to
    111        // the wrapped type into a reference to the wrapper type.
    112        unsafe { &mut *(slice as *mut [u8] as *mut Self) }
    113    }
    114
    115    #[doc(hidden)]
    116    #[unstable(feature = "bstr_internals", issue = "none")]
    117    #[inline]
    118    #[rustc_const_unstable(feature = "bstr_internals", issue = "none")]
    119    pub const fn as_bytes(&self) -> &[u8] {
    120        &self.0
    121    }
    122
    123    #[doc(hidden)]
    124    #[unstable(feature = "bstr_internals", issue = "none")]
    125    #[inline]
    126    #[rustc_const_unstable(feature = "bstr_internals", issue = "none")]
    127    pub const fn as_bytes_mut(&mut self) -> &mut [u8] {
    128        &mut self.0
    129    }
    130}
    131
    132#[unstable(feature = "bstr", issue = "134915")]
    133#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
    134impl const Deref for ByteStr {
    135    type Target = [u8];
    136
    137    #[inline]
    138    fn deref(&self) -> &[u8] {
    139        &self.0
    140    }
    141}
    142
    143#[unstable(feature = "bstr", issue = "134915")]
    144#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
    145impl const DerefMut for ByteStr {
    146    #[inline]
    147    fn deref_mut(&mut self) -> &mut [u8] {
    148        &mut self.0
    149    }
    150}
    151
    152#[unstable(feature = "deref_pure_trait", issue = "87121")]
    153unsafe impl DerefPure for ByteStr {}
    154
    155#[unstable(feature = "bstr", issue = "134915")]
    156impl fmt::Debug for ByteStr {
    157    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
    158        write!(f, "\"")?;
    159        for chunk in self.utf8_chunks() {
    160            for c in chunk.valid().chars() {
    161                match c {
    162                    '\0' => write!(f, "\\0")?,
    163                    '\x01'..='\x7f' => write!(f, "{}", (c as u8).escape_ascii())?,
    164                    _ => write!(f, "{}", c.escape_debug())?,
    165                }
    166            }
    167            write!(f, "{}", chunk.invalid().escape_ascii())?;
    168        }
    169        write!(f, "\"")?;
    170        Ok(())
    171    }
    172}
    173
    174#[unstable(feature = "bstr", issue = "134915")]
    175impl fmt::Display for ByteStr {
    176    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
    177        fn fmt_nopad(this: &ByteStr, f: &mut fmt::Formatter<'_>) -> fmt::Result {
    178            for chunk in this.utf8_chunks() {
    179                f.write_str(chunk.valid())?;
    180                if !chunk.invalid().is_empty() {
    181                    f.write_str("\u{FFFD}")?;
    182                }
    183            }
    184            Ok(())
    185        }
    186
    187        let Some(align) = f.align() else {
    188            return fmt_nopad(self, f);
    189        };
    190        let nchars: usize = self
    191            .utf8_chunks()
    192            .map(|chunk| {
    193                chunk.valid().chars().count() + if chunk.invalid().is_empty() { 0 } else { 1 }
    194            })
    195            .sum();
    196        let padding = f.width().unwrap_or(0).saturating_sub(nchars);
    197        let fill = f.fill();
    198        let (lpad, rpad) = match align {
    199            fmt::Alignment::Left => (0, padding),
    200            fmt::Alignment::Right => (padding, 0),
    201            fmt::Alignment::Center => {
    202                let half = padding / 2;
    203                (half, half + padding % 2)
    204            }
    205        };
    206        for _ in 0..lpad {
    207            write!(f, "{fill}")?;
    208        }
    209        fmt_nopad(self, f)?;
    210        for _ in 0..rpad {
    211            write!(f, "{fill}")?;
    212        }
    213
    214        Ok(())
    215    }
    216}
    217
    218#[unstable(feature = "bstr", issue = "134915")]
    219#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
    220impl const AsRef<[u8]> for ByteStr {
    221    #[inline]
    222    fn as_ref(&self) -> &[u8] {
    223        &self.0
    224    }
    225}
    226
    227#[unstable(feature = "bstr", issue = "134915")]
    228#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
    229impl const AsRef<ByteStr> for ByteStr {
    230    #[inline]
    231    fn as_ref(&self) -> &ByteStr {
    232        self
    233    }
    234}
    235
    236// `impl AsRef<ByteStr> for [u8]` omitted to avoid widespread inference failures
    237
    238#[unstable(feature = "bstr", issue = "134915")]
    239#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
    240impl const AsRef<ByteStr> for str {
    241    #[inline]
    242    fn as_ref(&self) -> &ByteStr {
    243        ByteStr::new(self)
    244    }
    245}
    246
    247#[unstable(feature = "bstr", issue = "134915")]
    248#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
    249impl const AsMut<[u8]> for ByteStr {
    250    #[inline]
    251    fn as_mut(&mut self) -> &mut [u8] {
    252        &mut self.0
    253    }
    254}
    255
    256// `impl AsMut<ByteStr> for [u8]` omitted to avoid widespread inference failures
    257
    258// `impl Borrow<ByteStr> for [u8]` omitted to avoid widespread inference failures
    259
    260// `impl Borrow<ByteStr> for str` omitted to avoid widespread inference failures
    261
    262#[unstable(feature = "bstr", issue = "134915")]
    263#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
    264impl const Borrow<[u8]> for ByteStr {
    265    #[inline]
    266    fn borrow(&self) -> &[u8] {
    267        &self.0
    268    }
    269}
    270
    271// `impl BorrowMut<ByteStr> for [u8]` omitted to avoid widespread inference failures
    272
    273#[unstable(feature = "bstr", issue = "134915")]
    274#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
    275impl const BorrowMut<[u8]> for ByteStr {
    276    #[inline]
    277    fn borrow_mut(&mut self) -> &mut [u8] {
    278        &mut self.0
    279    }
    280}
    281
    282#[unstable(feature = "bstr", issue = "134915")]
    283impl<'a> Default for &'a ByteStr {
    284    fn default() -> Self {
    285        ByteStr::from_bytes(b"")
    286    }
    287}
    288
    289#[unstable(feature = "bstr", issue = "134915")]
    290impl<'a> Default for &'a mut ByteStr {
    291    fn default() -> Self {
    292        ByteStr::from_bytes_mut(&mut [])
    293    }
    294}
    295
    296// Omitted due to inference failures
    297//
    298// #[unstable(feature = "bstr", issue = "134915")]
    299// impl<'a, const N: usize> From<&'a [u8; N]> for &'a ByteStr {
    300//     #[inline]
    301//     fn from(s: &'a [u8; N]) -> Self {
    302//         ByteStr::from_bytes(s)
    303//     }
    304// }
    305//
    306// #[unstable(feature = "bstr", issue = "134915")]
    307// impl<'a> From<&'a [u8]> for &'a ByteStr {
    308//     #[inline]
    309//     fn from(s: &'a [u8]) -> Self {
    310//         ByteStr::from_bytes(s)
    311//     }
    312// }
    313
    314// Omitted due to slice-from-array-issue-113238:
    315//
    316// #[unstable(feature = "bstr", issue = "134915")]
    317// impl<'a> From<&'a ByteStr> for &'a [u8] {
    318//     #[inline]
    319//     fn from(s: &'a ByteStr) -> Self {
    320//         &s.0
    321//     }
    322// }
    323//
    324// #[unstable(feature = "bstr", issue = "134915")]
    325// impl<'a> From<&'a mut ByteStr> for &'a mut [u8] {
    326//     #[inline]
    327//     fn from(s: &'a mut ByteStr) -> Self {
    328//         &mut s.0
    329//     }
    330// }
    331
    332// Omitted due to inference failures
    333//
    334// #[unstable(feature = "bstr", issue = "134915")]
    335// impl<'a> From<&'a str> for &'a ByteStr {
    336//     #[inline]
    337//     fn from(s: &'a str) -> Self {
    338//         ByteStr::from_bytes(s.as_bytes())
    339//     }
    340// }
    341
    342#[unstable(feature = "bstr", issue = "134915")]
    343#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
    344impl<'a> const TryFrom<&'a ByteStr> for &'a str {
    345    type Error = crate::str::Utf8Error;
    346
    347    #[inline]
    348    fn try_from(s: &'a ByteStr) -> Result<Self, Self::Error> {
    349        crate::str::from_utf8(&s.0)
    350    }
    351}
    352
    353#[unstable(feature = "bstr", issue = "134915")]
    354#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
    355impl<'a> const TryFrom<&'a mut ByteStr> for &'a mut str {
    356    type Error = crate::str::Utf8Error;
    357
    358    #[inline]
    359    fn try_from(s: &'a mut ByteStr) -> Result<Self, Self::Error> {
    360        crate::str::from_utf8_mut(&mut s.0)
    361    }
    362}