http/
byte_str.rs

1use bytes::Bytes;
2
3use std::{ops, str};
4
5#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
6pub(crate) struct ByteStr {
7    // Invariant: bytes contains valid UTF-8
8    bytes: Bytes,
9}
10
11impl ByteStr {
12    #[inline]
13    pub fn new() -> ByteStr {
14        ByteStr {
15            // Invariant: the empty slice is trivially valid UTF-8.
16            bytes: Bytes::new(),
17        }
18    }
19
20    #[inline]
21    pub fn from_static(val: &'static str) -> ByteStr {
22        ByteStr {
23            // Invariant: val is a str so contains vaid UTF-8.
24            bytes: Bytes::from_static(val.as_bytes()),
25        }
26    }
27
28    #[inline]
29    /// ## Panics
30    /// In a debug build this will panic if `bytes` is not valid UTF-8.
31    ///
32    /// ## Safety
33    /// `bytes` must contain valid UTF-8. In a release build it is undefined
34    /// behaviour to call this with `bytes` that is not valid UTF-8.
35    pub unsafe fn from_utf8_unchecked(bytes: Bytes) -> ByteStr {
36        if cfg!(debug_assertions) {
37            match str::from_utf8(&bytes) {
38                Ok(_) => (),
39                Err(err) => panic!(
40                    "ByteStr::from_utf8_unchecked() with invalid bytes; error = {}, bytes = {:?}",
41                    err, bytes
42                ),
43            }
44        }
45        // Invariant: assumed by the safety requirements of this function.
46        ByteStr { bytes: bytes }
47    }
48}
49
50impl ops::Deref for ByteStr {
51    type Target = str;
52
53    #[inline]
54    fn deref(&self) -> &str {
55        let b: &[u8] = self.bytes.as_ref();
56        // Safety: the invariant of `bytes` is that it contains valid UTF-8.
57        unsafe { str::from_utf8_unchecked(b) }
58    }
59}
60
61impl From<String> for ByteStr {
62    #[inline]
63    fn from(src: String) -> ByteStr {
64        ByteStr {
65            // Invariant: src is a String so contains valid UTF-8.
66            bytes: Bytes::from(src),
67        }
68    }
69}
70
71impl<'a> From<&'a str> for ByteStr {
72    #[inline]
73    fn from(src: &'a str) -> ByteStr {
74        ByteStr {
75            // Invariant: src is a str so contains valid UTF-8.
76            bytes: Bytes::copy_from_slice(src.as_bytes()),
77        }
78    }
79}
80
81impl From<ByteStr> for Bytes {
82    fn from(src: ByteStr) -> Self {
83        src.bytes
84    }
85}