This repository has been archived on 2025-03-02. You can view files and clone it, but cannot push or open issues or pull requests.
neco/safe_libc/src/string.rs

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()))) }
}
}