use crate::{self as libc, util}; use alloc::boxed::Box; use core::{ops::{Deref, DerefMut}, slice}; //pub struct FromBytesWithNulError {} #[repr(transparent)] pub struct CStr { inner: libc::c_char, } impl CStr { #[inline] pub unsafe fn from_ptr<'a>(p: *const libc::c_char) -> &'a CStr { &*p.cast() } #[inline] pub unsafe fn from_mut_ptr<'a>(p: *mut libc::c_char) -> &'a mut CStr { &mut *p.cast() } #[inline] pub unsafe fn from_bytes_with_nul_unchecked(bytes: &[u8]) -> &CStr { CStr::from_ptr(bytes.as_ptr().cast()) } // TODO //pub fn from_bytes_with_nul(bytes: &[u8]) -> Result<&CStr, FromBytesWithNulError> { //} #[inline] pub fn len(&self) -> usize { unsafe { libc::strlen(self.as_ptr()) } } #[inline] pub const fn as_ptr(&self) -> *const libc::c_char { &self.inner } #[inline] pub fn as_mut_ptr(&mut self) -> *mut libc::c_char { &mut self.inner } #[inline] pub fn to_bytes(&self) -> &[u8] { unsafe { slice::from_raw_parts(self.as_ptr().cast(), self.len()) } } #[inline] pub fn to_mut_bytes(&mut self) -> &mut [u8] { unsafe { slice::from_raw_parts_mut(self.as_mut_ptr().cast(), self.len()) } } #[inline] pub fn to_str(&self) -> Result<&str, core::str::Utf8Error> { core::str::from_utf8(self.to_bytes()) } #[inline] pub fn to_mut_str(&mut self) -> Result<&mut str, core::str::Utf8Error> { core::str::from_utf8_mut(self.to_mut_bytes()) } #[inline] pub fn to_owned(self: &CStr) -> CString { CString::from(self) } } #[macro_export] macro_rules! cstr { ($s:expr) => { unsafe { $crate::string::CStr::from_bytes_with_nul_unchecked(concat!($s, "\0").as_bytes()) } }; } pub struct CString { inner: Box, } impl CString { #[inline] pub unsafe fn from_raw(p: *mut libc::c_char) -> CString { CString { inner: Box::from_raw(p), } } #[inline] pub fn into_raw(self) -> *mut libc::c_char { Box::into_raw(self.inner) } } impl Deref for CString { type Target = CStr; #[inline] fn deref(&self) -> &CStr { unsafe { CStr::from_ptr(&*self.inner) } } } impl DerefMut for CString { #[inline] fn deref_mut(&mut self) -> &mut CStr { unsafe { CStr::from_mut_ptr(&mut *self.inner) } } } impl From<&[u8]> for CString { fn from(s: &[u8]) -> CString { unsafe { CString::from_raw(util::must_succeed(libc::strndup( s.as_ptr().cast(), s.len(), ))) } } } impl From<&str> for CString { #[inline] fn from(s: &str) -> CString { CString::from(s.as_bytes()) } } impl From<&CStr> for CString { #[inline] fn from(s: &CStr) -> CString { unsafe { CString::from_raw(util::must_succeed(libc::strdup(s.as_ptr()))) } } }