1use std::{
2 borrow::{Borrow, Cow},
3 cmp::Ordering,
4 ffi::OsStr,
5 fmt::{self, Debug, Display},
6 hash::{Hash, Hasher},
7 ops::{Deref, Index},
8 path::Path,
9 slice::SliceIndex,
10 str::Utf8Error,
11};
12
13use bytes::Bytes;
14
15use crate::BytesString;
16
17#[derive(Clone, Default, PartialEq, Eq)]
19pub struct BytesStr {
20 pub(crate) bytes: Bytes,
21}
22
23impl BytesStr {
24 pub fn new() -> Self {
36 Self {
37 bytes: Bytes::new(),
38 }
39 }
40
41 pub fn from_static(bytes: &'static str) -> Self {
48 Self {
49 bytes: Bytes::from_static(bytes.as_bytes()),
50 }
51 }
52
53 pub fn from_utf8(bytes: Bytes) -> Result<Self, Utf8Error> {
66 std::str::from_utf8(&bytes)?;
67
68 Ok(Self { bytes })
69 }
70
71 pub fn from_utf8_slice(bytes: &[u8]) -> Result<Self, Utf8Error> {
84 std::str::from_utf8(bytes)?;
85
86 Ok(Self {
87 bytes: Bytes::copy_from_slice(bytes),
88 })
89 }
90
91 pub fn from_static_utf8_slice(bytes: &'static [u8]) -> Result<Self, Utf8Error> {
103 std::str::from_utf8(bytes)?;
104
105 Ok(Self {
106 bytes: Bytes::from_static(bytes),
107 })
108 }
109
110 pub fn as_str(&self) -> &str {
122 unsafe { std::str::from_utf8_unchecked(&self.bytes) }
123 }
124}
125
126impl Deref for BytesStr {
127 type Target = str;
128
129 fn deref(&self) -> &Self::Target {
130 self.as_ref()
131 }
132}
133
134impl AsRef<str> for BytesStr {
135 fn as_ref(&self) -> &str {
136 self.as_str()
137 }
138}
139
140impl From<String> for BytesStr {
141 fn from(s: String) -> Self {
142 Self {
143 bytes: Bytes::from(s),
144 }
145 }
146}
147
148impl From<&'static str> for BytesStr {
149 fn from(s: &'static str) -> Self {
150 Self {
151 bytes: Bytes::from_static(s.as_bytes()),
152 }
153 }
154}
155
156impl From<BytesStr> for BytesString {
157 fn from(s: BytesStr) -> Self {
158 Self {
159 bytes: s.bytes.into(),
160 }
161 }
162}
163
164impl From<BytesString> for BytesStr {
165 fn from(s: BytesString) -> Self {
166 Self {
167 bytes: s.bytes.into(),
168 }
169 }
170}
171
172impl AsRef<[u8]> for BytesStr {
173 fn as_ref(&self) -> &[u8] {
174 self.bytes.as_ref()
175 }
176}
177
178impl AsRef<Bytes> for BytesStr {
179 fn as_ref(&self) -> &Bytes {
180 &self.bytes
181 }
182}
183
184impl AsRef<OsStr> for BytesStr {
185 fn as_ref(&self) -> &OsStr {
186 OsStr::new(self.as_str())
187 }
188}
189
190impl AsRef<Path> for BytesStr {
191 fn as_ref(&self) -> &Path {
192 Path::new(self.as_str())
193 }
194}
195
196impl Borrow<str> for BytesStr {
197 fn borrow(&self) -> &str {
198 self.as_str()
199 }
200}
201
202impl Debug for BytesStr {
203 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
204 Debug::fmt(self.as_str(), f)
205 }
206}
207
208impl Display for BytesStr {
209 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
210 Display::fmt(self.as_str(), f)
211 }
212}
213
214impl Extend<BytesStr> for BytesString {
215 fn extend<T: IntoIterator<Item = BytesStr>>(&mut self, iter: T) {
216 self.bytes.extend(iter.into_iter().map(|s| s.bytes));
217 }
218}
219
220impl<I> Index<I> for BytesStr
221where
222 I: SliceIndex<str>,
223{
224 type Output = I::Output;
225
226 fn index(&self, index: I) -> &Self::Output {
227 self.as_str().index(index)
228 }
229}
230
231impl PartialEq<str> for BytesStr {
232 fn eq(&self, other: &str) -> bool {
233 self.as_str() == other
234 }
235}
236
237impl PartialEq<&'_ str> for BytesStr {
238 fn eq(&self, other: &&str) -> bool {
239 self.as_str() == *other
240 }
241}
242
243impl PartialEq<Cow<'_, str>> for BytesStr {
244 fn eq(&self, other: &Cow<'_, str>) -> bool {
245 self.as_str() == *other
246 }
247}
248
249impl PartialEq<BytesStr> for str {
250 fn eq(&self, other: &BytesStr) -> bool {
251 self == other.as_str()
252 }
253}
254
255impl PartialEq<BytesStr> for &'_ str {
256 fn eq(&self, other: &BytesStr) -> bool {
257 *self == other.as_str()
258 }
259}
260
261impl PartialEq<BytesStr> for Bytes {
262 fn eq(&self, other: &BytesStr) -> bool {
263 self == other.as_bytes()
264 }
265}
266
267impl PartialEq<String> for BytesStr {
268 fn eq(&self, other: &String) -> bool {
269 self.as_str() == other
270 }
271}
272
273impl PartialEq<BytesStr> for String {
274 fn eq(&self, other: &BytesStr) -> bool {
275 self == other.as_str()
276 }
277}
278
279impl Ord for BytesStr {
280 fn cmp(&self, other: &Self) -> Ordering {
281 self.as_str().cmp(other.as_str())
282 }
283}
284
285impl PartialOrd for BytesStr {
286 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
287 Some(self.cmp(other))
288 }
289}
290
291impl Hash for BytesStr {
293 fn hash<H: Hasher>(&self, state: &mut H) {
294 self.as_str().hash(state);
295 }
296}
297
298impl TryFrom<&'static [u8]> for BytesStr {
299 type Error = Utf8Error;
300
301 fn try_from(value: &'static [u8]) -> Result<Self, Self::Error> {
302 Self::from_static_utf8_slice(value)
303 }
304}