Skip to content

Commit

Permalink
Improve documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
djkoloski committed Aug 10, 2024
1 parent f55f98e commit 0c0a63b
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 121 deletions.
52 changes: 52 additions & 0 deletions ptr_meta/example.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
```rust
// Get the associated metadata for pointers
let str = "hello world";
assert_eq!(ptr_meta::metadata(str), str.len());

let slice = &[1, 2, 3, 4, 5] as &[i32];
assert_eq!(ptr_meta::metadata(slice), slice.len());

// Make your own wide pointers from data pointers and metadata
let bytes = [b'h', b'e', b'l', b'l', b'o'];
let ptr = ptr_meta::from_raw_parts::<str>(bytes.as_ptr().cast(), 5);
println!("{} world!", unsafe { &*ptr }); // prints "hello world!"

// Derive Pointee on your own types
#[derive(ptr_meta::Pointee)]
#[repr(transparent)]
struct CoolStr {
inner: str,
}

impl CoolStr {
fn print_cool(&self) {
println!("😎 {} 😎", &self.inner);
}
}

let ptr = ptr_meta::from_raw_parts::<CoolStr>(bytes.as_ptr().cast(), 5);
let cool = unsafe { &*ptr };
cool.print_cool(); // prints "😎 hello 😎"

// Implement Pointee for trait objects
#[ptr_meta::pointee]
trait Printable {
fn print(&self);
}

impl Printable for i32 {
fn print(&self) {
println!("i32: {self}");
}
}

let i32_vtable = ptr_meta::metadata(&0i32 as &dyn Printable);
let one_hundred = 100i32;
let printable = ptr_meta::from_raw_parts::<dyn Printable>(
(&one_hundred as *const i32).cast(),
i32_vtable,
);
unsafe {
(*printable).print(); // prints "i32: 100"
}
```
52 changes: 0 additions & 52 deletions ptr_meta/examples/readme.rs

This file was deleted.

113 changes: 44 additions & 69 deletions ptr_meta/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,40 +1,34 @@
//! A radioactive stabilization of the [`ptr_meta` RFC][rfc].
//!
//! `ptr_meta` provides the `Pointee` trait, `from_raw_parts` and `to_raw_parts`
//! functions, and proc macros for deriving `Pointee` for types and implementing
//! `Pointee` for trait objects.
//! This crate provides the [`Pointee`] trait, [`from_raw_parts`] and
//! [`to_raw_parts`] functions, and proc macros for deriving `Pointee` for
//! structs and implementing `Pointee` for trait objects.
//!
//! [rfc]: https://rust-lang.github.io/rfcs/2580-ptr-meta.html
//!
//! ## Provided impls
//!
//! `ptr_meta` provides inherent implementations for many builtin types:
//!
//! ### Sized types
//!
//! All [`Sized`] types implement [`Pointee`] via a blanket implementation. You
//! cannot write or derive [`Pointee`] implementations for these types.
//! # Usage
//!
//! ### `slice`s and `str`s
//! Raw pointers can be decomposed into the data address and metadata components
//! with [`to_raw_parts`] or [`to_raw_parts_mut`].
//!
//! These core types have implementations provided.
//! Alternatively, metadata alone can be extracted with the [`metadata`]
//! function. Although [`metadata`] accepts pointers, references can be passed
//! and will be implicitly coerced.
//!
//! ### `CStr` and `OsStr`
//! A pointer can be created from its address and metadata with
//! [`from_raw_parts`] or [`from_raw_parts_mut`].
//!
//! These `std` types have implementations provided when the `std` feature is
//! enabled.
//!
//! ### `dyn Any` (`+ Send`) (`+ Sync`)
//!
//! `dyn Any`, optionally with `+ Send` and/or `+ Sync`, have implementations
//! provided.
//! ## Provided impls
//!
//! ### `dyn Error` (`+ Send`) (`+ Sync`)
//! `ptr_meta` provides inherent implementations for many builtin types:
//!
//! `dyn Error`, optionally with `+ Send` and/or `+ Sync`, have implementations
//! provided when the `std` feature is enabled.
//! - All [`Sized`] types implement [`Pointee`] via a blanket implementation.
//! - `slice`s and `str`s
//! - `CStr` and `OsStr` (requires `std`)
//! - `dyn Any`, optionally with `+ Send` and/or `+ Sync`
//! - `dyn Error`, optionally with `+Send` and/or `+ Sync` (requires `std`)
//!
//! ### Structs with trailing DSTs
//! ## Structs with trailing DSTs
//!
//! You can derive [`Pointee`] for structs with trailing DSTs:
//!
Expand All @@ -54,7 +48,7 @@
//! required in these cases, with the generic parameter set (for example) a
//! slice, `str`, or specific trait object.
//!
//! ### Trait objects
//! ## Trait objects
//!
//! You can generate [`Pointee`] implementations for trait objects:
//!
Expand All @@ -69,7 +63,9 @@
//! ```
//!
//! Note that this will not produce implementations for `Trait + Send + Sync`.
//!
//! ## Example
#![doc = include_str!("../example.md")]
#![deny(
future_incompatible,
missing_docs,
Expand Down Expand Up @@ -101,13 +97,13 @@ pub use ptr_meta_derive::{pointee, Pointee};
///
/// # Pointer metadata
///
/// Pointer and reference types can be thought of as having two parts: a data
/// pointer which contains the memory address of the value, and some metadata.
/// Pointers and references can be thought of as having two parts: a data
/// address and some extra "pointer metadata".
///
/// Pointers to [statically-sized types](`Sized`) and `extern` types are
/// "narrow": their pointer metadata is `()`.
///
/// Pointers to [dynamically-sized types][dst] are wide: they have pointer
/// Pointers to [dynamically-sized types][dst] are "wide": they have pointer
/// metadata with a non-zero size. There are four classes of dynamically-sized
/// types currently available:
///
Expand All @@ -116,26 +112,14 @@ pub use ptr_meta_derive::{pointee, Pointee};
/// * Slices like `[i32]` have `usize` pointer metadata equal to the length of
/// the slice in items.
/// * Trait objects like `dyn SomeTrait` have [`DynMetadata`] pointer metadata,
/// which points to the trait object's virtual method table.
/// which point to the trait objects' virtual method tables.
/// * Structs with a trailing DST have the same metadata as the trailing DST.
///
/// In the future, Rust may add new kinds of types which have different pointer
/// metadata.
///
/// [dst]: https://doc.rust-lang.org/reference/dynamically-sized-types.html
///
/// # Usage
///
/// Raw pointers can be decomposed into the data address and metadata components
/// with [`to_raw_parts`] or [`to_raw_parts_mut`].
///
/// Alternatively, metadata alone can be extracted with the [`metadata`]
/// function. Although [`metadata`] accepts pointers, references can be passed
/// and will be implicitly coerced.
///
/// A pointer can be created from its address and metadata with
/// [`from_raw_parts`] or [`from_raw_parts_mut`].
///
/// # Safety
///
/// The associated `Metadata` type must be the pointer metadata type for the
Expand Down Expand Up @@ -185,9 +169,8 @@ unsafe impl Pointee for ::std::ffi::OsStr {
/// # Example
///
/// ```
/// use ptr_meta::metadata;
///
/// assert_eq!(metadata("foo"), 3_usize);
/// // String slices have pointer metadata equal to their size in bytes
/// assert_eq!(ptr_meta::metadata("foo"), 3_usize);
/// ```
#[inline]
pub const fn metadata<T: Pointee + ?Sized>(
Expand All @@ -207,9 +190,7 @@ pub const fn metadata<T: Pointee + ?Sized>(
/// # Example
///
/// ```
/// use ptr_meta::to_raw_parts;
///
/// let (data_address, metadata) = to_raw_parts("foo");
/// let (data_address, metadata) = ptr_meta::to_raw_parts("foo");
/// assert_ne!(data_address, core::ptr::null());
/// assert_eq!(metadata, 3);
/// ```
Expand All @@ -232,7 +213,7 @@ pub const fn to_raw_parts_mut<T: Pointee + ?Sized>(

/// Returns a raw pointer with the given data address and metadata.
///
/// This function is safe but the returned pointer is not necessarily safe to
/// This function is safe, but the returned pointer is not necessarily safe to
/// dereference. For slices, see the documentation of [`slice::from_raw_parts`]
/// for safety requirements. For trait objects, the metadata must come from a
/// a trait object with the same underlying type.
Expand Down Expand Up @@ -302,25 +283,19 @@ impl<T: Pointee + ?Sized> Clone for PtrComponents<T> {
}
}

/// The metadata for a `Dyn = dyn SomeTrait` trait object type.
///
/// It is a pointer to a vtable (virtual call table)
/// that represents all the necessary information
/// to manipulate the concrete type stored inside a trait object.
/// The vtable notably it contains:
/// The metadata for a trait object.
///
/// * type size
/// * type alignment
/// * a pointer to the type’s `drop_in_place` impl (may be a no-op for
/// plain-old-data)
/// * pointers to all the methods for the type’s implementation of the trait
/// This struct wraps a pointer to a vtable (virtual method table) which
/// contains all of the necessary information to manipulate the concrete type
/// stored inside of the trait object:
///
/// Note that the first three are special because they’re necessary to allocate,
/// drop, and deallocate any trait object.
/// * The size and alignment of the concrete type
/// * A function pointer to the type's `drop_in_place` impl
/// * Function pointers for each method in the concrete type's trait
/// implementation
///
/// It is possible to name this struct with a type parameter that is not a `dyn`
/// trait object (for example `DynMetadata<u64>`) but not to obtain a meaningful
/// value of that struct.
/// Providing a type argument that is not a `dyn` trait object is possible, but
/// does not correspond with a meaningful type.
pub struct DynMetadata<Dyn: ?Sized> {
vtable_ptr: &'static VTable,
phantom: core::marker::PhantomData<Dyn>,
Expand All @@ -331,7 +306,7 @@ pub struct DynMetadata<Dyn: ?Sized> {
struct VTable;

impl<Dyn: ?Sized> DynMetadata<Dyn> {
/// Returns the size of the type associated with this vtable.
/// Returns the size of the type associated with this metadata.
#[inline]
pub fn size_of(self) -> usize {
#[cfg(miri)]
Expand Down Expand Up @@ -360,7 +335,7 @@ impl<Dyn: ?Sized> DynMetadata<Dyn> {
}
}

/// Returns the alignment of the type associated with this vtable.
/// Returns the alignment of the type associated with this metadata.
#[inline]
pub fn align_of(self) -> usize {
#[cfg(miri)]
Expand All @@ -385,7 +360,7 @@ impl<Dyn: ?Sized> DynMetadata<Dyn> {
}
}

/// Returns the size and alignment together as a `Layout`
/// Returns the layout of the type associated with this metadata.
#[inline]
pub fn layout(self) -> core::alloc::Layout {
// SAFETY: the compiler emitted this vtable for a concrete Rust type
Expand Down

0 comments on commit 0c0a63b

Please sign in to comment.