142 lines
2.6 KiB
Rust
142 lines
2.6 KiB
Rust
use crate::{self as libc, boxed::CBox, util};
|
|
|
|
use core::{mem, slice};
|
|
use core::ops::{Deref, DerefMut};
|
|
|
|
//pub struct FromBytesWithNulError {}
|
|
|
|
extern "C" {
|
|
type RawCStr;
|
|
}
|
|
|
|
#[repr(transparent)]
|
|
pub struct CStr(RawCStr);
|
|
|
|
impl CStr {
|
|
#[inline]
|
|
pub unsafe fn from_ptr<'a>(p: *const libc::c_char) -> &'a CStr {
|
|
&*(p as *const CStr)
|
|
}
|
|
|
|
#[inline]
|
|
pub unsafe fn from_mut_ptr<'a>(p: *mut libc::c_char) -> &'a mut CStr {
|
|
&mut *(p as *mut CStr)
|
|
}
|
|
|
|
#[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 as *const CStr).cast()
|
|
}
|
|
|
|
#[inline]
|
|
pub fn as_mut_ptr(&mut self) -> *mut libc::c_char {
|
|
(self as *mut CStr).cast()
|
|
}
|
|
|
|
#[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: CBox<CStr>,
|
|
}
|
|
|
|
impl CString {
|
|
#[inline]
|
|
pub unsafe fn from_raw(p: *mut libc::c_char) -> CString {
|
|
CString {
|
|
inner: CBox::from_raw_unchecked(p as *mut CStr)
|
|
}
|
|
}
|
|
|
|
#[inline]
|
|
pub fn into_raw(mut self) -> *mut libc::c_char {
|
|
let p = self.as_mut_ptr();
|
|
mem::forget(self);
|
|
p
|
|
}
|
|
}
|
|
|
|
impl Deref for CString {
|
|
type Target = CStr;
|
|
|
|
#[inline]
|
|
fn deref(&self) -> &CStr {
|
|
&*self.inner
|
|
}
|
|
}
|
|
|
|
impl DerefMut for CString {
|
|
#[inline]
|
|
fn deref_mut(&mut self) -> &mut CStr {
|
|
&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()))) }
|
|
}
|
|
}
|