1 use bytes::Bytes; 2 3 use std::{ops, str}; 4 5 #[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] 6 pub(crate) struct ByteStr { 7 // Invariant: bytes contains valid UTF-8 8 bytes: Bytes, 9 } 10 11 impl ByteStr { 12 #[inline] new() -> ByteStr13 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] from_static(val: &'static str) -> ByteStr21 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. from_utf8_unchecked(bytes: Bytes) -> ByteStr35 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 50 impl ops::Deref for ByteStr { 51 type Target = str; 52 53 #[inline] deref(&self) -> &str54 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 61 impl From<String> for ByteStr { 62 #[inline] from(src: String) -> ByteStr63 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 71 impl<'a> From<&'a str> for ByteStr { 72 #[inline] from(src: &'a str) -> ByteStr73 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 81 impl From<ByteStr> for Bytes { from(src: ByteStr) -> Self82 fn from(src: ByteStr) -> Self { 83 src.bytes 84 } 85 } 86