1use bytes::Bytes;
2
3use std::{ops, str};
4
5#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
6pub(crate) struct ByteStr {
7    bytes: Bytes,
9}
10
11impl ByteStr {
12    #[inline]
13    pub fn new() -> ByteStr {
14        ByteStr {
15            bytes: Bytes::new(),
17        }
18    }
19
20    #[inline]
21    pub const fn from_static(val: &'static str) -> ByteStr {
22        ByteStr {
23            bytes: Bytes::from_static(val.as_bytes()),
25        }
26    }
27
28    #[inline]
29    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        ByteStr { bytes }
47    }
48
49    pub(crate) fn from_utf8(bytes: Bytes) -> Result<ByteStr, std::str::Utf8Error> {
50        str::from_utf8(&bytes)?;
51        Ok(ByteStr { bytes })
53    }
54}
55
56impl ops::Deref for ByteStr {
57    type Target = str;
58
59    #[inline]
60    fn deref(&self) -> &str {
61        let b: &[u8] = self.bytes.as_ref();
62        unsafe { str::from_utf8_unchecked(b) }
64    }
65}
66
67impl From<String> for ByteStr {
68    #[inline]
69    fn from(src: String) -> ByteStr {
70        ByteStr {
71            bytes: Bytes::from(src),
73        }
74    }
75}
76
77impl<'a> From<&'a str> for ByteStr {
78    #[inline]
79    fn from(src: &'a str) -> ByteStr {
80        ByteStr {
81            bytes: Bytes::copy_from_slice(src.as_bytes()),
83        }
84    }
85}
86
87impl From<ByteStr> for Bytes {
88    fn from(src: ByteStr) -> Self {
89        src.bytes
90    }
91}