summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--Cargo.toml2
-rw-r--r--src/impls/cstr.rs64
-rw-r--r--src/lib.rs8
3 files changed, 73 insertions, 1 deletions
diff --git a/Cargo.toml b/Cargo.toml
index bd6563a..5165718 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "ltptr"
-version = "0.1.3"
+version = "0.1.4"
 edition = "2021"
 license = "0BSD"
 description = "Checked raw pointers."
diff --git a/src/impls/cstr.rs b/src/impls/cstr.rs
index 5467963..700ae13 100644
--- a/src/impls/cstr.rs
+++ b/src/impls/cstr.rs
@@ -4,15 +4,79 @@ use std::os::raw::c_char;
 
 use crate::*;
 
+/// Conversion from [`CStr`] to [`ConstLtPtr`].
 impl AsLtPtr for CStr {
+    /// The target type of this conversion.
     type Target = c_char;
 
     /// Returns the inner pointer to this C string.
     ///
     /// The returned pointer points to a contiguous region of memory terminated
     /// with a 0 byte to represent the end of the string.
+    ///
+    /// # Examples
+    ///
+    /// `ltptr` protects you from dangling pointers: (adapted from
+    /// [`CStr::as_ptr`])
+    ///
+    /// ```rust compile_fail
+    /// use std::ffi::CString;
+    /// use ltptr::AsLtPtr;
+    ///
+    /// let ptr = CString::new("Hello").unwrap().as_lt_ptr();
+    /// unsafe {
+    ///     // would be dangling but the compiler prevents this from compiling
+    ///     ptr.as_raw();
+    /// }
+    /// ```
+    ///
+    /// Which you can fix by adding a binding:
+    ///
+    /// ```rust
+    /// use std::ffi::CString;
+    /// use ltptr::AsLtPtr;
+    ///
+    /// let hello = CString::new("Hello").unwrap();
+    /// let ptr = hello.as_lt_ptr();
+    /// unsafe {
+    ///     // perfectly fine
+    ///     ptr.as_raw();
+    /// }
+    /// ```
     #[inline]
     fn as_lt_ptr(&self) -> ConstLtPtr<'_, c_char> {
         unsafe { ConstLtPtr::from_raw(self.as_ptr()) }
     }
 }
+
+/// Conversion from [`ConstLtPtr`] of [`c_char`] to [`CStr`].
+impl FromLtPtr<c_char> for CStr {
+    /// Wraps a raw C string with a safe C string wrapper.
+    ///
+    /// # Safety
+    ///
+    /// See [`CStr::from_ptr`] for the safety requirements.
+    ///
+    /// # Examples
+    ///
+    /// ```rust
+    /// use std::ffi::CStr;
+    /// use std::ffi::CString;
+    /// use std::os::raw::c_char;
+    /// use ltptr::AsLtPtr;
+    /// use ltptr::ConstLtPtr;
+    /// use ltptr::FromLtPtr;
+    ///
+    /// unsafe fn foo(ptr: ConstLtPtr<'_, c_char>) {
+    ///     let first = unsafe { CStr::from_lt_ptr(ptr) }.to_str().to_owned();
+    /// }
+    ///
+    /// let hello = CString::new("Hello").unwrap();
+    /// let ptr = hello.as_lt_ptr();
+    /// unsafe { foo(ptr) };
+    /// ```
+    #[inline]
+    unsafe fn from_lt_ptr(ptr: ConstLtPtr<'_, c_char>) -> &CStr {
+        unsafe { CStr::from_ptr(ptr.as_raw()) }
+    }
+}
diff --git a/src/lib.rs b/src/lib.rs
index 90cef27..7ce25cb 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -2,6 +2,7 @@
 // SPDX-License-Identifier: 0BSD
 
 #![cfg_attr(not(feature="std"),no_std)]
+#![deny(unsafe_op_in_unsafe_fn)]
 
 //! This crate provides "checked" raw pointers.
 //!
@@ -107,6 +108,13 @@ pub trait AsLtPtr {
     fn as_lt_ptr<'a>(&'a self) -> ConstLtPtr<'a, Self::Target>;
 }
 
+/// Trait for conversion from a [`ConstLtPtr`] of the given `Source` type.
+pub trait FromLtPtr<Source> {
+    /// Returns a value as if by `from_ptr` on a type that implements this, but
+    /// with a bound lifetime.
+    unsafe fn from_lt_ptr<'a>(ptr: ConstLtPtr<'a, Source>) -> &'a Self;
+}
+
 /// Trait for conversion into a [`MutLtPtr`].
 pub trait AsMutLtPtr: AsLtPtr {
     /// Returns a pointer as if by `as_ptr` on a type that implements this, but