use alloc::borrow::Cow;
use alloc::borrow::ToOwned;
use alloc::boxed::Box;
use alloc::rc::Rc;
use alloc::string::String;
use alloc::sync::Arc;
use core::fmt::{Formatter, Octal};
use core::{fmt, mem};
use super::*;
pub struct DaemonicSlice {
pub inner: [u8],
}
impl fmt::Debug for DaemonicSlice {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(&self.inner.utf8_chunks().debug(), f)
}
}
unsafe impl core::clone::CloneToUninit for DaemonicSlice {
unsafe fn clone_to_uninit(&self, dst: *mut u8) {
let bytes = self.as_encoded_bytes();
core::ptr::copy_nonoverlapping(
bytes.as_ptr(),
dst,
bytes.len(),
);
}
}
use core::fmt::Write;
impl fmt::Display for DaemonicSlice {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if self.inner.is_empty() {
return "".fmt(f);
}
for chunk in self.inner.utf8_chunks() {
let valid = chunk.valid();
if chunk.invalid().is_empty() {
return valid.fmt(f);
}
f.write_str(valid)?;
Formatter::write_char(f, char::REPLACEMENT_CHARACTER)?;
}
Ok(())
}
}
impl DaemonicSlice {
#[inline]
pub fn as_encoded_bytes(&self) -> &[u8] {
&self.inner
}
#[inline]
pub unsafe fn from_encoded_bytes_unchecked(s: &[u8]) -> &DaemonicSlice {
unsafe { mem::transmute(s) }
}
#[track_caller]
#[inline]
pub fn check_public_boundary(&self, index: usize) {
if index == 0 || index == self.inner.len() {
return;
}
if index < self.inner.len()
&& (self.inner[index - 1].is_ascii() || self.inner[index].is_ascii())
{
return;
}
slow_path(&self.inner, index);
#[track_caller]
#[inline(never)]
fn slow_path(bytes: &[u8], index: usize) {
let (before, after) = bytes.split_at(index);
let after = after.get(..4).unwrap_or(after);
match str::from_utf8(after) {
Ok(_) => return,
Err(err) if err.valid_up_to() != 0 => return,
Err(_) => (),
}
for len in 2..=4.min(index) {
let before = &before[index - len..];
if str::from_utf8(before).is_ok() {
return;
}
}
panic!("byte index {index} is not an DaemonicOsStr boundary");
}
}
#[inline]
pub fn from_str(s: &str) -> &DaemonicSlice {
unsafe { DaemonicSlice::from_encoded_bytes_unchecked(s.as_bytes()) }
}
#[inline]
pub fn to_str(&self) -> Result<&str, core::str::Utf8Error> {
str::from_utf8(&self.inner)
}
#[inline]
pub fn to_string_lossy(&self) -> Cow<'_, str> {
String::from_utf8_lossy(&self.inner)
}
#[inline]
pub fn to_owned(&self) -> DaemonicBuf {
DaemonicBuf { inner: self.inner.to_vec() }
}
#[inline]
pub fn clone_into(&self, buf: &mut DaemonicBuf) {
self.inner.clone_into(&mut buf.inner)
}
#[inline]
pub fn into_box(&self) -> Box<DaemonicSlice> {
let boxed: Box<[u8]> = self.inner.into();
unsafe { mem::transmute(boxed) }
}
#[inline]
pub fn empty_box() -> Box<DaemonicSlice> {
let boxed: Box<[u8]> = Default::default();
unsafe { mem::transmute(boxed) }
}
#[inline]
pub fn into_arc(&self) -> Arc<DaemonicSlice> {
let arc: Arc<[u8]> = Arc::from(&self.inner);
unsafe { Arc::from_raw(Arc::into_raw(arc) as *const DaemonicSlice) }
}
#[inline]
pub fn into_rc(&self) -> Rc<DaemonicSlice> {
let rc: Rc<[u8]> = Rc::from(&self.inner);
unsafe { Rc::from_raw(Rc::into_raw(rc) as *const DaemonicSlice) }
}
#[inline]
pub fn make_ascii_lowercase(&mut self) {
self.inner.make_ascii_lowercase()
}
#[inline]
pub fn make_ascii_uppercase(&mut self) {
self.inner.make_ascii_uppercase()
}
#[inline]
pub fn to_ascii_lowercase(&self) -> DaemonicBuf {
DaemonicBuf { inner: self.inner.to_ascii_lowercase() }
}
#[inline]
pub fn to_ascii_uppercase(&self) -> DaemonicBuf {
DaemonicBuf { inner: self.inner.to_ascii_uppercase() }
}
#[inline]
pub fn is_ascii(&self) -> bool {
self.inner.is_ascii()
}
#[inline]
pub fn eq_ignore_ascii_case(&self, other: &Self) -> bool {
self.inner.eq_ignore_ascii_case(&other.inner)
}
}