#![cfg_attr(not(feature="std"),no_std)] //! This crate provides "checked" raw pointers. //! //! We found ourselves to be experiencing a lot of cognitive overhead when //! doing FFI interactions. A non-insignificant portion of them came from raw //! pointers, `as_ptr`, `as_mut_ptr`, and the like. This removes that cognitive //! overhead. use core::cell::UnsafeCell; use core::marker::PhantomData; use core::ops::Range; /// The actual impls. mod impls; /// `*const T` with a lifetime. /// /// # Examples /// /// Rust doesn't catch incorrect `as_ptr` usage (tho there is a lint for it): /// /// ```no_run /// use std::ffi::{CString, CStr}; /// use std::os::raw::c_char; /// /// extern "C" { /// fn my_ffi_function(data: *const c_char); /// } /// let str = CString::new("world!").unwrap().as_ptr(); /// // oops! CString dropped here! ^ /// unsafe { my_ffi_function(str) } // crashes at runtime /// ``` /// /// but we can use a `ConstLtPtr` to make it do so: /// /// ```compile_fail /// use std::ffi::{CString, CStr}; /// use std::os::raw::c_char; /// use ltptr::*; /// /// extern "C" { /// fn my_ffi_function(data: ConstLtPtr<'_, c_char>); /// } /// let str = CString::new("world!").unwrap().as_lt_ptr(); /// unsafe { my_ffi_function(str) } /// // error[E0716]: temporary value dropped while borrowed /// ``` /// /// which we can then fix: /// /// ```no_run /// use std::ffi::{CString, CStr}; /// use std::os::raw::c_char; /// use ltptr::*; /// /// extern "C" { /// fn my_ffi_function(data: ConstLtPtr<'_, c_char>); /// } /// let str = CString::new("world!").unwrap(); /// unsafe { my_ffi_function(str.as_lt_ptr()) } /// ``` /// /// /// and if we call the wrong thing, it fails to compile: /// /// ```compile_fail /// use std::ffi::{CString, CStr}; /// use std::os::raw::c_char; /// use ltptr::*; /// /// extern "C" { /// fn my_ffi_function(data: ConstLtPtr<'_, c_char>); /// } /// let str = CString::new("world!").unwrap(); /// unsafe { my_ffi_function(str.as_ptr()) } // should be as_lt_ptr! /// ``` #[repr(transparent)] pub struct ConstLtPtr<'a, T: ?Sized> { raw: *const T, _lt: PhantomData<&'a T>, } /// `*mut T` with a lifetime. #[repr(transparent)] pub struct MutLtPtr<'a, T: ?Sized> { raw: *mut T, _lt: PhantomData<&'a UnsafeCell>, } /// Trait for conversion into a [`ConstLtPtr`]. pub trait AsLtPtr { type Target: ?Sized; /// Returns a pointer as if by `as_ptr` on a type that implements this, but /// with a bound lifetime. fn as_lt_ptr<'a>(&'a self) -> ConstLtPtr<'a, Self::Target>; } /// 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 /// with a bound lifetime. fn as_mut_lt_ptr<'a>(&'a mut self) -> MutLtPtr<'a, Self::Target>; } /// Additional slice methods. pub trait SliceExt: impls::slice::Sealed { /// Returns the two raw pointers spanning the slice. /// /// See [`[T]::as_ptr_range`] for extended documentation. /// /// The pointers returned by this function have bound lifetimes. fn as_lt_ptr_range<'a>(&'a self) -> Range>; /// Returns the two unsafe mutable pointers spanning the slice. /// /// See [`[T]::as_mut_ptr_range`] for extended documentation. /// /// The pointers returned by this function have bound lifetimes. fn as_mut_lt_ptr_range<'a>(&'a mut self) -> Range>; } impl<'a, T: ?Sized> ConstLtPtr<'a, T> { /// Creates a new `ConstLtPtr` from the given raw pointer. /// /// # Safety /// /// This function is unsafe as an advisory: the returned `ConstLtPtr` has /// an arbitrary lifetime `'a`, so using this function directly doesn't /// help reduce cognitive overhead. #[inline] pub const unsafe fn from_raw(raw: *const T) -> Self { Self { raw: raw, _lt: PhantomData, } } } impl<'a, T: ?Sized> MutLtPtr<'a, T> { /// Creates a new `MutLtPtr` from the given raw pointer. /// /// # Safety /// /// This function is unsafe as an advisory: the returned `MutLtPtr` has /// an arbitrary lifetime `'a`, so using this function directly doesn't /// help reduce cognitive overhead. #[inline] pub const unsafe fn from_raw(raw: *mut T) -> Self { Self { raw: raw, _lt: PhantomData, } } }