1use std::any::Any;
9use std::borrow::Cow;
10
11use super::bytes::AbstractBytes;
12use super::bytes::AbstractOwner;
13use super::bytes::SliceLike;
14use crate::Bytes;
15
16pub type Text = AbstractBytes<str>;
17pub trait TextOwner: AsRef<str> + Send + Sync + 'static {}
18
19impl<T: TextOwner> AbstractOwner<str> for T {
20 fn as_any_mut(&mut self) -> &mut dyn Any {
21 self
22 }
23}
24
25impl Text {
26 pub const fn from_static(slice: &'static str) -> Self {
28 Self {
29 ptr: slice.as_ptr(),
30 len: slice.len(),
31 owner: None,
32 }
33 }
34
35 pub fn from_utf8_lossy(bytes: Bytes) -> Self {
38 match String::from_utf8_lossy(bytes.as_slice()) {
39 Cow::Borrowed(..) => {
40 unsafe { Self::from_utf8_unchecked(bytes) }
42 }
43 Cow::Owned(s) => Self::from_owner(s),
44 }
45 }
46
47 pub unsafe fn from_utf8_unchecked(bytes: Bytes) -> Self {
50 struct Utf8Bytes(Bytes);
51 impl AsRef<str> for Utf8Bytes {
52 fn as_ref(&self) -> &str {
53 unsafe { std::str::from_utf8_unchecked(self.0.as_slice()) }
56 }
57 }
58 impl TextOwner for Utf8Bytes {}
59 Self::from_owner(Utf8Bytes(bytes))
60 }
61
62 #[inline]
63 pub(crate) fn as_slice(&self) -> &str {
64 let bytes = self.as_bytes();
65 unsafe { std::str::from_utf8_unchecked(bytes) }
67 }
68}
69
70impl Bytes {
71 pub fn into_text_lossy(self) -> Text {
73 Text::from_utf8_lossy(self)
74 }
75}
76
77impl SliceLike for str {
78 type Owned = String;
79 const EMPTY: &'static Self = "";
80
81 #[inline]
82 fn check_slice_bytes(bytes: &[u8], start: usize, end: usize) {
83 let s = unsafe { std::str::from_utf8_unchecked(bytes) };
85 let _ = s[start..end];
87 }
88 #[inline]
89 fn as_bytes(&self) -> &[u8] {
90 self.as_bytes()
91 }
92 #[inline]
93 fn to_owned(&self) -> Self::Owned {
94 self.to_string()
95 }
96}