Skip to main content

Crate trait_obj_list

Crate trait_obj_list 

Source
Expand description

A list of objects that all implement a trait, stored in one buffer.

Provides the DynList data structure. This can be thought of a Vec<T> where T is some dyn Trait. Different implementors of the trait can be added to the vec, and iterating the vector will return dyn Trait references.

Unlike, for example, a Vec<Box<dyn Trait>>, a DynList will store all of the values in one flat array, allowing for more efficient allocation and iteration.

The tradeoff is that a DynList is not as flexible as a Vec in how it can be accessed. Because items in the list take up a variable amount of size, random access is not as efficient, and items can only be pushed onto the end of the list.

let mut list = DynList::<dyn Any>::new();
list.push(123i32);
list.push(String::from("Hello world!"));
list.push(true);

for item in list.iter() {
    if let Some(item) = item.downcast_ref::<i32>() {
        println!("{}", *item + 7);
    } else if let Some(item) = item.downcast_ref::<String>() {
        println!("Text: {item}");
    } else if let Some(item) = item.downcast_ref::<bool>() {
        println!("{}", !*item);
    }
}

§List Types

The second generic argument to DynList is the internal structure, to select the tradeoffs between storage size and access. The following types are available:

  • DoubleLinked: The default. Stores the trait metadata, trait data, and a length at the end. Allows iterating the list in both directions, but has slightly more overhead than SingleLinked.
  • SingleLinked: Stores the trait metadata and data, and nothing else. This is the most comapact representation, but only allows iteration in list order.

§Stable Rust Limitations

On stable Rust, the ptr_meta feature is required. This uses the ptr_meta crate to get the metadata of wide pointers, and so only works with traits that implement ptr_meta::Pointee. ptr_meta provides an implementation for Any and Error (plus their Send and Sync variants), but others will need to use the ptr_meta::pointee attribute.

Additionally, DynList::push requires that the pushed type implement FromImpl. The trait can be implemented for all sized types implementing a certain trait via the impl_from_impl macro.

On nightly Rust, the ptr_meta feature can be omitted, in which case the ptr_metadata and unsize unstable features are used to lift these limitations. In this case, DynList will work with any trait and type.

§Safety

This crate uses unsafe a lot, due to having to manage allocations manually and work with dynamically sized types. To help ensure soundness, the test suite is checked with miri, so that any unsound accesses are caught and fixed.

Re-exports§

pub use ::ptr_meta;

Modules§

iters
Iterators for DynList
types
DynList inner repesentations

Macros§

impl_from_impl
Implements FromImpl for all sized types implementing the specified trait.

Structs§

DynList
A list of objects that all implement a trait.

Traits§

FromImpl
Trait for converting a sized type to an unsized one.