1#[cfg(not(feature = "ferrocene_subset"))]
4mod traits;
5
6#[unstable(feature = "bstr_internals", issue = "none")]
7#[cfg(not(feature = "ferrocene_subset"))]
8pub use traits::{impl_partial_eq, impl_partial_eq_n, impl_partial_eq_ord};
9
10#[cfg(not(feature = "ferrocene_subset"))]
11use crate::borrow::{Borrow, BorrowMut};
12use crate::fmt;
13use crate::ops::{Deref, DerefMut, DerefPure};
14
15#[unstable(feature = "bstr", issue = "134915")]
44#[repr(transparent)]
45#[doc(alias = "BStr")]
46pub struct ByteStr(pub [u8]);
47
48impl ByteStr {
49 #[cfg(not(feature = "ferrocene_subset"))]
68 #[inline]
69 #[unstable(feature = "bstr", issue = "134915")]
70 #[rustc_const_unstable(feature = "const_convert", issue = "143773")]
71 pub const fn new<B: ?Sized + [const] AsRef<[u8]>>(bytes: &B) -> &Self {
72 ByteStr::from_bytes(bytes.as_ref())
73 }
74
75 #[cfg(not(feature = "ferrocene_subset"))]
81 #[inline]
82 #[unstable(feature = "bstr", issue = "134915")]
84 pub const fn as_byte_str(&self) -> &ByteStr {
85 self
86 }
87
88 #[cfg(not(feature = "ferrocene_subset"))]
94 #[inline]
95 #[unstable(feature = "bstr", issue = "134915")]
97 pub const fn as_mut_byte_str(&mut self) -> &mut ByteStr {
98 self
99 }
100
101 #[doc(hidden)]
102 #[unstable(feature = "bstr_internals", issue = "none")]
103 #[inline]
104 #[rustc_const_unstable(feature = "bstr_internals", issue = "none")]
105 pub const fn from_bytes(slice: &[u8]) -> &Self {
106 unsafe { &*(slice as *const [u8] as *const Self) }
109 }
110
111 #[cfg(not(feature = "ferrocene_subset"))]
112 #[doc(hidden)]
113 #[unstable(feature = "bstr_internals", issue = "none")]
114 #[inline]
115 #[rustc_const_unstable(feature = "bstr_internals", issue = "none")]
116 pub const fn from_bytes_mut(slice: &mut [u8]) -> &mut Self {
117 unsafe { &mut *(slice as *mut [u8] as *mut Self) }
120 }
121
122 #[cfg(not(feature = "ferrocene_subset"))]
123 #[doc(hidden)]
124 #[unstable(feature = "bstr_internals", issue = "none")]
125 #[inline]
126 #[rustc_const_unstable(feature = "bstr_internals", issue = "none")]
127 pub const fn as_bytes(&self) -> &[u8] {
128 &self.0
129 }
130
131 #[cfg(not(feature = "ferrocene_subset"))]
132 #[doc(hidden)]
133 #[unstable(feature = "bstr_internals", issue = "none")]
134 #[inline]
135 #[rustc_const_unstable(feature = "bstr_internals", issue = "none")]
136 pub const fn as_bytes_mut(&mut self) -> &mut [u8] {
137 &mut self.0
138 }
139}
140
141#[unstable(feature = "bstr", issue = "134915")]
142#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
143impl const Deref for ByteStr {
144 type Target = [u8];
145
146 #[inline]
147 fn deref(&self) -> &[u8] {
148 &self.0
149 }
150}
151
152#[unstable(feature = "bstr", issue = "134915")]
153#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
154impl const DerefMut for ByteStr {
155 #[inline]
156 fn deref_mut(&mut self) -> &mut [u8] {
157 &mut self.0
158 }
159}
160
161#[unstable(feature = "deref_pure_trait", issue = "87121")]
162unsafe impl DerefPure for ByteStr {}
163
164#[unstable(feature = "bstr", issue = "134915")]
165impl fmt::Debug for ByteStr {
166 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
167 write!(f, "\"")?;
168 for chunk in self.utf8_chunks() {
169 for c in chunk.valid().chars() {
170 match c {
171 '\0' => write!(f, "\\0")?,
172 '\x01'..='\x7f' => write!(f, "{}", (c as u8).escape_ascii())?,
173 _ => write!(f, "{}", c.escape_debug())?,
174 }
175 }
176 write!(f, "{}", chunk.invalid().escape_ascii())?;
177 }
178 write!(f, "\"")?;
179 Ok(())
180 }
181}
182
183#[cfg(not(feature = "ferrocene_subset"))]
184#[unstable(feature = "bstr", issue = "134915")]
185impl fmt::Display for ByteStr {
186 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
187 fn fmt_nopad(this: &ByteStr, f: &mut fmt::Formatter<'_>) -> fmt::Result {
188 for chunk in this.utf8_chunks() {
189 f.write_str(chunk.valid())?;
190 if !chunk.invalid().is_empty() {
191 f.write_str("\u{FFFD}")?;
192 }
193 }
194 Ok(())
195 }
196
197 let Some(align) = f.align() else {
198 return fmt_nopad(self, f);
199 };
200 let nchars: usize = self
201 .utf8_chunks()
202 .map(|chunk| {
203 chunk.valid().chars().count() + if chunk.invalid().is_empty() { 0 } else { 1 }
204 })
205 .sum();
206 let padding = f.width().unwrap_or(0).saturating_sub(nchars);
207 let fill = f.fill();
208 let (lpad, rpad) = match align {
209 fmt::Alignment::Left => (0, padding),
210 fmt::Alignment::Right => (padding, 0),
211 fmt::Alignment::Center => {
212 let half = padding / 2;
213 (half, half + padding % 2)
214 }
215 };
216 for _ in 0..lpad {
217 write!(f, "{fill}")?;
218 }
219 fmt_nopad(self, f)?;
220 for _ in 0..rpad {
221 write!(f, "{fill}")?;
222 }
223
224 Ok(())
225 }
226}
227
228#[cfg(not(feature = "ferrocene_subset"))]
229#[unstable(feature = "bstr", issue = "134915")]
230#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
231impl const AsRef<[u8]> for ByteStr {
232 #[inline]
233 fn as_ref(&self) -> &[u8] {
234 &self.0
235 }
236}
237
238#[cfg(not(feature = "ferrocene_subset"))]
239#[unstable(feature = "bstr", issue = "134915")]
240#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
241impl const AsRef<ByteStr> for ByteStr {
242 #[inline]
243 fn as_ref(&self) -> &ByteStr {
244 self
245 }
246}
247
248#[cfg(not(feature = "ferrocene_subset"))]
251#[unstable(feature = "bstr", issue = "134915")]
252#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
253impl const AsRef<ByteStr> for str {
254 #[inline]
255 fn as_ref(&self) -> &ByteStr {
256 ByteStr::new(self)
257 }
258}
259
260#[cfg(not(feature = "ferrocene_subset"))]
261#[unstable(feature = "bstr", issue = "134915")]
262#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
263impl const AsMut<[u8]> for ByteStr {
264 #[inline]
265 fn as_mut(&mut self) -> &mut [u8] {
266 &mut self.0
267 }
268}
269
270#[cfg(not(feature = "ferrocene_subset"))]
277#[unstable(feature = "bstr", issue = "134915")]
278#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
279impl const Borrow<[u8]> for ByteStr {
280 #[inline]
281 fn borrow(&self) -> &[u8] {
282 &self.0
283 }
284}
285
286#[cfg(not(feature = "ferrocene_subset"))]
289#[unstable(feature = "bstr", issue = "134915")]
290#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
291impl const BorrowMut<[u8]> for ByteStr {
292 #[inline]
293 fn borrow_mut(&mut self) -> &mut [u8] {
294 &mut self.0
295 }
296}
297
298#[cfg(not(feature = "ferrocene_subset"))]
299#[unstable(feature = "bstr", issue = "134915")]
300impl<'a> Default for &'a ByteStr {
301 fn default() -> Self {
302 ByteStr::from_bytes(b"")
303 }
304}
305
306#[cfg(not(feature = "ferrocene_subset"))]
307#[unstable(feature = "bstr", issue = "134915")]
308impl<'a> Default for &'a mut ByteStr {
309 fn default() -> Self {
310 ByteStr::from_bytes_mut(&mut [])
311 }
312}
313
314#[cfg(not(feature = "ferrocene_subset"))]
361#[unstable(feature = "bstr", issue = "134915")]
362#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
363impl<'a> const TryFrom<&'a ByteStr> for &'a str {
364 type Error = crate::str::Utf8Error;
365
366 #[inline]
367 fn try_from(s: &'a ByteStr) -> Result<Self, Self::Error> {
368 crate::str::from_utf8(&s.0)
369 }
370}
371
372#[cfg(not(feature = "ferrocene_subset"))]
373#[unstable(feature = "bstr", issue = "134915")]
374#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
375impl<'a> const TryFrom<&'a mut ByteStr> for &'a mut str {
376 type Error = crate::str::Utf8Error;
377
378 #[inline]
379 fn try_from(s: &'a mut ByteStr) -> Result<Self, Self::Error> {
380 crate::str::from_utf8_mut(&mut s.0)
381 }
382}