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
2020-04-04 14:23:00 +02:00

151 lines
2.9 KiB
Rust

use crate as libc;
use crate::util;
use crate::boxed::CBox;
use core::slice;
use core::ops::{Deref, DerefMut};
//pub struct FromBytesWithNulError {}
pub struct CStr { inner: libc::c_char }
impl CStr {
#[inline]
pub unsafe fn from_ptr_unchecked<'a>(p: *const libc::c_char) -> &'a CStr {
&*(p as *const CStr)
}
#[inline]
pub unsafe fn from_ptr<'a>(p: *const libc::c_char) -> &'a CStr {
util::check_ptr(p, 1);
CStr::from_ptr_unchecked(p)
}
#[inline]
pub unsafe fn from_mut_ptr_unchecked<'a>(p: *mut libc::c_char) -> &'a mut CStr {
&mut *(p as *mut CStr)
}
#[inline]
pub unsafe fn from_mut_ptr<'a>(p: *mut libc::c_char) -> &'a mut CStr {
util::check_ptr(p, 1);
CStr::from_mut_ptr_unchecked(p)
}
#[inline]
pub unsafe fn from_bytes_with_nul_unchecked(bytes: &[u8]) -> &CStr {
CStr::from_ptr_unchecked(bytes.as_ptr() as *const libc::c_char)
}
// TODO
//pub fn from_bytes_with_nul(bytes: &[u8]) -> Result<&CStr, FromBytesWithNulError> {
//}
#[inline]
pub fn len(&self) -> usize {
unsafe { libc::strlen(self.as_ptr()) as usize }
}
#[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 as_bytes(&self) -> &[u8] {
unsafe { slice::from_raw_parts(
self.as_ptr() as *const u8,
self.len(),
) }
}
#[inline]
pub fn as_mut_bytes(&mut self) -> &mut [u8] {
unsafe { slice::from_raw_parts_mut(
self.as_mut_ptr() as *mut u8,
self.len(),
) }
}
#[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<libc::c_char> }
impl CString {
#[inline]
pub unsafe fn from_raw_unchecked(p: *mut libc::c_char) -> CString {
CString { inner: CBox::from_raw_unchecked(p) }
}
#[inline]
pub unsafe fn from_raw(p: *mut libc::c_char) -> CString {
util::check_ptr(p, 1);
CString::from_raw_unchecked(p)
}
#[inline]
pub fn into_raw(self) -> *mut libc::c_char {
self.inner.into_raw()
}
}
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_unchecked(
util::must_succeed(libc::strndup(
s.as_ptr() as *const libc::c_char,
s.len() as libc::size_t,
))
)
}
}
}
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_unchecked(util::must_succeed(libc::strdup(s.as_ptr())))
}
}
}