1mod traits;
4
5#[unstable(feature = "bstr_internals", issue = "none")]
6pub use traits::{impl_partial_eq, impl_partial_eq_n, impl_partial_eq_ord};
7
8use crate::borrow::{Borrow, BorrowMut};
9use crate::fmt;
10use crate::ops::{Deref, DerefMut, DerefPure};
11
12#[unstable(feature = "bstr", issue = "134915")]
42#[repr(transparent)]
43#[doc(alias = "BStr")]
44pub struct ByteStr(pub [u8]);
45
46impl ByteStr {
47 #[inline]
66 #[unstable(feature = "bstr", issue = "134915")]
67 pub fn new<B: ?Sized + AsRef<[u8]>>(bytes: &B) -> &Self {
68 ByteStr::from_bytes(bytes.as_ref())
69 }
70
71 #[doc(hidden)]
72 #[unstable(feature = "bstr_internals", issue = "none")]
73 #[inline]
74 pub fn from_bytes(slice: &[u8]) -> &Self {
75 unsafe { &*(slice as *const [u8] as *const Self) }
78 }
79
80 #[doc(hidden)]
81 #[unstable(feature = "bstr_internals", issue = "none")]
82 #[inline]
83 pub fn from_bytes_mut(slice: &mut [u8]) -> &mut Self {
84 unsafe { &mut *(slice as *mut [u8] as *mut Self) }
87 }
88
89 #[doc(hidden)]
90 #[unstable(feature = "bstr_internals", issue = "none")]
91 #[inline]
92 pub fn as_bytes(&self) -> &[u8] {
93 &self.0
94 }
95
96 #[doc(hidden)]
97 #[unstable(feature = "bstr_internals", issue = "none")]
98 #[inline]
99 pub fn as_bytes_mut(&mut self) -> &mut [u8] {
100 &mut self.0
101 }
102}
103
104#[unstable(feature = "bstr", issue = "134915")]
105impl Deref for ByteStr {
106 type Target = [u8];
107
108 #[inline]
109 fn deref(&self) -> &[u8] {
110 &self.0
111 }
112}
113
114#[unstable(feature = "bstr", issue = "134915")]
115impl DerefMut for ByteStr {
116 #[inline]
117 fn deref_mut(&mut self) -> &mut [u8] {
118 &mut self.0
119 }
120}
121
122#[unstable(feature = "deref_pure_trait", issue = "87121")]
123unsafe impl DerefPure for ByteStr {}
124
125#[unstable(feature = "bstr", issue = "134915")]
126impl fmt::Debug for ByteStr {
127 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
128 write!(f, "\"")?;
129 for chunk in self.utf8_chunks() {
130 for c in chunk.valid().chars() {
131 match c {
132 '\0' => write!(f, "\\0")?,
133 '\x01'..='\x7f' => write!(f, "{}", (c as u8).escape_ascii())?,
134 _ => write!(f, "{}", c.escape_debug())?,
135 }
136 }
137 write!(f, "{}", chunk.invalid().escape_ascii())?;
138 }
139 write!(f, "\"")?;
140 Ok(())
141 }
142}
143
144#[unstable(feature = "bstr", issue = "134915")]
145impl fmt::Display for ByteStr {
146 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
147 fn fmt_nopad(this: &ByteStr, f: &mut fmt::Formatter<'_>) -> fmt::Result {
148 for chunk in this.utf8_chunks() {
149 f.write_str(chunk.valid())?;
150 if !chunk.invalid().is_empty() {
151 f.write_str("\u{FFFD}")?;
152 }
153 }
154 Ok(())
155 }
156
157 let Some(align) = f.align() else {
158 return fmt_nopad(self, f);
159 };
160 let nchars: usize = self
161 .utf8_chunks()
162 .map(|chunk| {
163 chunk.valid().chars().count() + if chunk.invalid().is_empty() { 0 } else { 1 }
164 })
165 .sum();
166 let padding = f.width().unwrap_or(0).saturating_sub(nchars);
167 let fill = f.fill();
168 let (lpad, rpad) = match align {
169 fmt::Alignment::Left => (0, padding),
170 fmt::Alignment::Right => (padding, 0),
171 fmt::Alignment::Center => {
172 let half = padding / 2;
173 (half, half + padding % 2)
174 }
175 };
176 for _ in 0..lpad {
177 write!(f, "{fill}")?;
178 }
179 fmt_nopad(self, f)?;
180 for _ in 0..rpad {
181 write!(f, "{fill}")?;
182 }
183
184 Ok(())
185 }
186}
187
188#[unstable(feature = "bstr", issue = "134915")]
189impl AsRef<[u8]> for ByteStr {
190 #[inline]
191 fn as_ref(&self) -> &[u8] {
192 &self.0
193 }
194}
195
196#[unstable(feature = "bstr", issue = "134915")]
197impl AsRef<ByteStr> for ByteStr {
198 #[inline]
199 fn as_ref(&self) -> &ByteStr {
200 self
201 }
202}
203
204#[unstable(feature = "bstr", issue = "134915")]
207impl AsRef<ByteStr> for str {
208 #[inline]
209 fn as_ref(&self) -> &ByteStr {
210 ByteStr::new(self)
211 }
212}
213
214#[unstable(feature = "bstr", issue = "134915")]
215impl AsMut<[u8]> for ByteStr {
216 #[inline]
217 fn as_mut(&mut self) -> &mut [u8] {
218 &mut self.0
219 }
220}
221
222#[unstable(feature = "bstr", issue = "134915")]
229impl Borrow<[u8]> for ByteStr {
230 #[inline]
231 fn borrow(&self) -> &[u8] {
232 &self.0
233 }
234}
235
236#[unstable(feature = "bstr", issue = "134915")]
239impl BorrowMut<[u8]> for ByteStr {
240 #[inline]
241 fn borrow_mut(&mut self) -> &mut [u8] {
242 &mut self.0
243 }
244}
245
246#[unstable(feature = "bstr", issue = "134915")]
247impl<'a> Default for &'a ByteStr {
248 fn default() -> Self {
249 ByteStr::from_bytes(b"")
250 }
251}
252
253#[unstable(feature = "bstr", issue = "134915")]
254impl<'a> Default for &'a mut ByteStr {
255 fn default() -> Self {
256 ByteStr::from_bytes_mut(&mut [])
257 }
258}
259
260#[unstable(feature = "bstr", issue = "134915")]
307impl<'a> TryFrom<&'a ByteStr> for &'a str {
308 type Error = crate::str::Utf8Error;
309
310 #[inline]
311 fn try_from(s: &'a ByteStr) -> Result<Self, Self::Error> {
312 crate::str::from_utf8(&s.0)
313 }
314}
315
316#[unstable(feature = "bstr", issue = "134915")]
317impl<'a> TryFrom<&'a mut ByteStr> for &'a mut str {
318 type Error = crate::str::Utf8Error;
319
320 #[inline]
321 fn try_from(s: &'a mut ByteStr) -> Result<Self, Self::Error> {
322 crate::str::from_utf8_mut(&mut s.0)
323 }
324}