From f0b3d5166ef1255fac880b146875ef46d2599a13 Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Sat, 4 Apr 2020 13:22:18 +0200 Subject: Reorganize --- safe_libc/src/string.rs | 151 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 151 insertions(+) create mode 100644 safe_libc/src/string.rs (limited to 'safe_libc/src/string.rs') diff --git a/safe_libc/src/string.rs b/safe_libc/src/string.rs new file mode 100644 index 0000000..c85f788 --- /dev/null +++ b/safe_libc/src/string.rs @@ -0,0 +1,151 @@ +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 } + +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()))) + } + } +} -- cgit v1.2.3