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)]
37#[cfg_attr(
38 feature = "rkyv",
39 derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)
40)]
41pub struct BytesStr {
42 pub(crate) bytes: Bytes,
43}
44
45impl BytesStr {
46 pub fn new() -> Self {
58 Self {
59 bytes: Bytes::new(),
60 }
61 }
62
63 pub fn from_static(bytes: &'static str) -> Self {
70 Self {
71 bytes: Bytes::from_static(bytes.as_bytes()),
72 }
73 }
74
75 pub fn from_utf8(bytes: Bytes) -> Result<Self, Utf8Error> {
88 std::str::from_utf8(&bytes)?;
89
90 Ok(Self { bytes })
91 }
92
93 pub fn from_utf8_vec(bytes: Vec<u8>) -> Result<Self, Utf8Error> {
106 std::str::from_utf8(&bytes)?;
107
108 Ok(Self {
109 bytes: Bytes::from(bytes),
110 })
111 }
112
113 pub unsafe fn from_utf8_unchecked(bytes: Bytes) -> Self {
121 Self { bytes }
122 }
123
124 pub unsafe fn from_utf8_vec_unchecked(bytes: Vec<u8>) -> Self {
133 Self::from_utf8_unchecked(Bytes::from(bytes))
134 }
135
136 pub fn from_utf8_slice(bytes: &[u8]) -> Result<Self, Utf8Error> {
149 std::str::from_utf8(bytes)?;
150
151 Ok(Self {
152 bytes: Bytes::copy_from_slice(bytes),
153 })
154 }
155
156 pub unsafe fn from_utf8_slice_unchecked(bytes: &[u8]) -> Self {
165 Self {
166 bytes: Bytes::copy_from_slice(bytes),
167 }
168 }
169
170 pub fn from_static_utf8_slice(bytes: &'static [u8]) -> Result<Self, Utf8Error> {
182 std::str::from_utf8(bytes)?;
183
184 Ok(Self {
185 bytes: Bytes::from_static(bytes),
186 })
187 }
188
189 pub unsafe fn from_static_utf8_slice_unchecked(bytes: &'static [u8]) -> Self {
198 Self {
199 bytes: Bytes::from_static(bytes),
200 }
201 }
202
203 pub fn as_str(&self) -> &str {
215 unsafe { std::str::from_utf8_unchecked(&self.bytes) }
216 }
217}
218
219impl Deref for BytesStr {
220 type Target = str;
221
222 fn deref(&self) -> &Self::Target {
223 self.as_ref()
224 }
225}
226
227impl AsRef<str> for BytesStr {
228 fn as_ref(&self) -> &str {
229 self.as_str()
230 }
231}
232
233impl From<String> for BytesStr {
234 fn from(s: String) -> Self {
235 Self {
236 bytes: Bytes::from(s),
237 }
238 }
239}
240
241impl From<&'static str> for BytesStr {
242 fn from(s: &'static str) -> Self {
243 Self {
244 bytes: Bytes::from_static(s.as_bytes()),
245 }
246 }
247}
248
249impl From<BytesStr> for BytesString {
250 fn from(s: BytesStr) -> Self {
251 Self {
252 bytes: s.bytes.into(),
253 }
254 }
255}
256
257impl From<BytesString> for BytesStr {
258 fn from(s: BytesString) -> Self {
259 Self {
260 bytes: s.bytes.into(),
261 }
262 }
263}
264
265impl AsRef<[u8]> for BytesStr {
266 fn as_ref(&self) -> &[u8] {
267 self.bytes.as_ref()
268 }
269}
270
271impl AsRef<Bytes> for BytesStr {
272 fn as_ref(&self) -> &Bytes {
273 &self.bytes
274 }
275}
276
277impl AsRef<OsStr> for BytesStr {
278 fn as_ref(&self) -> &OsStr {
279 OsStr::new(self.as_str())
280 }
281}
282
283impl AsRef<Path> for BytesStr {
284 fn as_ref(&self) -> &Path {
285 Path::new(self.as_str())
286 }
287}
288
289impl Borrow<str> for BytesStr {
290 fn borrow(&self) -> &str {
291 self.as_str()
292 }
293}
294
295impl Debug for BytesStr {
296 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
297 Debug::fmt(self.as_str(), f)
298 }
299}
300
301impl Display for BytesStr {
302 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
303 Display::fmt(self.as_str(), f)
304 }
305}
306
307impl Extend<BytesStr> for BytesString {
308 fn extend<T: IntoIterator<Item = BytesStr>>(&mut self, iter: T) {
309 self.bytes.extend(iter.into_iter().map(|s| s.bytes));
310 }
311}
312
313impl<I> Index<I> for BytesStr
314where
315 I: SliceIndex<str>,
316{
317 type Output = I::Output;
318
319 fn index(&self, index: I) -> &Self::Output {
320 self.as_str().index(index)
321 }
322}
323
324impl PartialEq<str> for BytesStr {
325 fn eq(&self, other: &str) -> bool {
326 self.as_str() == other
327 }
328}
329
330impl PartialEq<&'_ str> for BytesStr {
331 fn eq(&self, other: &&str) -> bool {
332 self.as_str() == *other
333 }
334}
335
336impl PartialEq<Cow<'_, str>> for BytesStr {
337 fn eq(&self, other: &Cow<'_, str>) -> bool {
338 self.as_str() == *other
339 }
340}
341
342impl PartialEq<BytesStr> for str {
343 fn eq(&self, other: &BytesStr) -> bool {
344 self == other.as_str()
345 }
346}
347
348impl PartialEq<BytesStr> for &'_ str {
349 fn eq(&self, other: &BytesStr) -> bool {
350 *self == other.as_str()
351 }
352}
353
354impl PartialEq<BytesStr> for Bytes {
355 fn eq(&self, other: &BytesStr) -> bool {
356 self == other.as_bytes()
357 }
358}
359
360impl PartialEq<String> for BytesStr {
361 fn eq(&self, other: &String) -> bool {
362 self.as_str() == other
363 }
364}
365
366impl PartialEq<BytesStr> for String {
367 fn eq(&self, other: &BytesStr) -> bool {
368 self == other.as_str()
369 }
370}
371
372impl Ord for BytesStr {
373 fn cmp(&self, other: &Self) -> Ordering {
374 self.as_str().cmp(other.as_str())
375 }
376}
377
378impl PartialOrd for BytesStr {
379 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
380 Some(self.cmp(other))
381 }
382}
383
384impl Hash for BytesStr {
386 fn hash<H: Hasher>(&self, state: &mut H) {
387 self.as_str().hash(state);
388 }
389}
390
391impl TryFrom<&'static [u8]> for BytesStr {
392 type Error = Utf8Error;
393
394 fn try_from(value: &'static [u8]) -> Result<Self, Self::Error> {
395 Self::from_static_utf8_slice(value)
396 }
397}
398
399#[cfg(feature = "serde")]
400mod serde_impl {
401 use serde::{Deserialize, Deserializer, Serialize, Serializer};
402
403 use super::*;
404
405 impl<'de> Deserialize<'de> for BytesStr {
406 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
407 where
408 D: Deserializer<'de>,
409 {
410 let s = String::deserialize(deserializer)?;
411 Ok(Self::from(s))
412 }
413 }
414
415 impl Serialize for BytesStr {
416 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
417 where
418 S: Serializer,
419 {
420 serializer.serialize_str(self.as_str())
421 }
422 }
423}