use crate::{c::c_char, Ustr, Ustring};
use std::{
ffi::{CStr, OsStr},
fmt,
fmt::{Debug, Display, Formatter},
ops::{Deref, DerefMut},
os::unix::ffi::OsStrExt,
path::Path,
str::Utf8Error,
};
#[repr(transparent)]
#[derive(Eq, Ord, PartialOrd, PartialEq, Hash)]
pub struct Bstr {
bytes: [u8],
}
impl Bstr {
pub fn empty() -> &'static Self {
static E: [u8; 0] = [];
Self::from_bytes(&E[..])
}
pub fn from_bytes(s: &[u8]) -> &Self {
unsafe { &*(s as *const _ as *const _) }
}
pub fn from_bytes_mut(s: &mut [u8]) -> &mut Self {
unsafe { &mut *(s as *mut _ as *mut _) }
}
#[allow(clippy::should_implement_trait)] pub fn from_str(s: &str) -> &Self {
Self::from_bytes(s.as_bytes())
}
pub fn from_os_str(s: &OsStr) -> &Self {
Self::from_bytes(s.as_bytes())
}
pub fn from_path(s: &Path) -> &Self {
Self::from_os_str(s.as_os_str())
}
pub fn as_bytes(&self) -> &[u8] {
&self.bytes
}
pub fn as_bytes_mut(&mut self) -> &mut [u8] {
&mut self.bytes
}
pub fn as_str(&self) -> Result<&str, Utf8Error> {
std::str::from_utf8(self.as_bytes())
}
pub fn as_os_str(&self) -> &OsStr {
OsStr::from_bytes(self.as_bytes())
}
pub fn as_path(&self) -> &Path {
Path::new(self.as_os_str())
}
pub fn as_ptr(&self) -> *const c_char {
self.as_bytes().as_ptr() as *const c_char
}
pub fn as_mut_ptr(&mut self) -> *mut c_char {
self.as_bytes_mut().as_mut_ptr() as *mut c_char
}
pub fn len(&self) -> usize {
self.bytes.len()
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
pub fn display(&self) -> impl Display + '_ {
self.as_path().display()
}
pub fn to_ustring(&self) -> Ustring {
let mut vec = Vec::with_capacity(self.len() + 1);
vec.extend_from_slice(self.as_bytes());
vec.push(0);
unsafe { Ustring::from_vec_with_nul_unchecked(vec) }
}
}
impl ToOwned for Bstr {
type Owned = Ustring;
fn to_owned(&self) -> Self::Owned {
self.to_ustring()
}
}
impl Deref for Bstr {
type Target = [u8];
fn deref(&self) -> &Self::Target {
self.as_bytes()
}
}
impl DerefMut for Bstr {
fn deref_mut(&mut self) -> &mut Self::Target {
self.as_bytes_mut()
}
}
impl AsRef<[u8]> for Bstr {
fn as_ref(&self) -> &[u8] {
self.as_bytes()
}
}
impl AsMut<[u8]> for Bstr {
fn as_mut(&mut self) -> &mut [u8] {
self.as_bytes_mut()
}
}
impl AsRef<Bstr> for CStr {
fn as_ref(&self) -> &Bstr {
Ustr::from_c_str(self).as_bstr()
}
}
impl AsRef<OsStr> for Bstr {
fn as_ref(&self) -> &OsStr {
self.as_os_str()
}
}
impl AsRef<Path> for Bstr {
fn as_ref(&self) -> &Path {
self.as_path()
}
}
impl Debug for Bstr {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
Debug::fmt(self.as_os_str(), f)
}
}