1#![allow(
7 unreachable_pub,
8 clippy::allow_attributes,
9 clippy::style,
10 clippy::complexity,
11 clippy::perf,
12 clippy::suspicious,
13 clippy::pedantic,
14 clippy::nursery,
15 clippy::unwrap_used,
16 clippy::expect_used,
17 clippy::panic,
18 clippy::unreachable,
19 clippy::get_unwrap,
20 clippy::let_underscore_must_use,
21 clippy::multiple_unsafe_ops_per_block,
22 clippy::unnecessary_safety_comment,
23 dead_code,
24 unsafe_op_in_unsafe_fn
25)]
26
27use core::{ops, str};
28
29use crate::std::string::String;
30
31use bytes::Bytes;
32
33#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
34pub struct ByteStr {
35 bytes: Bytes,
37}
38
39impl ByteStr {
40 #[inline]
41 pub fn new() -> ByteStr {
42 ByteStr {
43 bytes: Bytes::new(),
45 }
46 }
47
48 #[inline]
49 pub const fn from_static(val: &'static str) -> ByteStr {
50 ByteStr {
51 bytes: Bytes::from_static(val.as_bytes()),
53 }
54 }
55
56 #[inline]
57 pub unsafe fn from_utf8_unchecked(bytes: Bytes) -> ByteStr {
64 if cfg!(debug_assertions) {
65 match str::from_utf8(&bytes) {
66 Ok(_) => (),
67 Err(err) => panic!(
68 "ByteStr::from_utf8_unchecked() with invalid bytes; error = {}, bytes = {:?}",
69 err, bytes
70 ),
71 }
72 }
73 ByteStr { bytes }
75 }
76
77 pub fn from_utf8(bytes: Bytes) -> Result<ByteStr, core::str::Utf8Error> {
78 str::from_utf8(&bytes)?;
79 Ok(ByteStr { bytes })
81 }
82}
83
84impl ops::Deref for ByteStr {
85 type Target = str;
86
87 #[inline]
88 fn deref(&self) -> &str {
89 let b: &[u8] = self.bytes.as_ref();
90 unsafe { str::from_utf8_unchecked(b) }
92 }
93}
94
95impl From<String> for ByteStr {
96 #[inline]
97 fn from(src: String) -> ByteStr {
98 ByteStr {
99 bytes: Bytes::from(src),
101 }
102 }
103}
104
105impl From<&str> for ByteStr {
106 #[inline]
107 fn from(src: &str) -> ByteStr {
108 ByteStr {
109 bytes: Bytes::copy_from_slice(src.as_bytes()),
111 }
112 }
113}
114
115impl From<ByteStr> for Bytes {
116 fn from(src: ByteStr) -> Self {
117 src.bytes
118 }
119}