summaryrefslogtreecommitdiffstats
path: root/safe_libc/src/string.rs
diff options
context:
space:
mode:
Diffstat (limited to 'safe_libc/src/string.rs')
-rw-r--r--safe_libc/src/string.rs151
1 files changed, 151 insertions, 0 deletions
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<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())))
+ }
+ }
+}