dync 0.5.5

An efficient alternative to `dyn Trait` for containerized types
Documentation

dync

An efficient alternative to dyn Trait for containerized types.

On crates.io On docs.rs Build status Coverage (codecov)

Overview

This crate aims to fill the gap in Rust's dynamic traits system by exposing the control over dynamic virtual function tables to the user in a safe API. This library is in prototype stage and is not recommended for production use.

Currently only untyped Vecs and Slices are implemented. Complementary Value types are provided for compatibility with traditional, typed containers like VecDeques and HashMaps.

Notably dync introduces the following types:

  • VecCopy<V> - a homogeneous collection of Copy types generic over the virtual function table,
  • VecDyn<V> - a homogeneous collection generic over the virtual function table,
  • SliceCopy<V> (and SliceCopyMut<V>) - a homogeneous slice (and mutable slice) of Copy types generic over the virtual function table,
  • Slice<V> (and SliceMut<V>) - a homogeneous slice (and mutable slice) of types generic over the virtual function table,
  • BoxValue<V> - an untyped boxed value of any size.
  • SmallValue<V> - an untyped value that fits into a usize.
  • ValueRef<V> (and ValueMut<V>) - an untyped value reference (and mutable reference).
  • CopyValueRef<V> (and CopyValueMut<V>) - an untyped value reference (and mutable reference) of a Copy type.

The main difference between the Copy variants of these is that they do not require a designated drop function pointer, which makes them simpler and potentially more performant. However, the benchmarks have not revealed any performance advantages in the Copy variants, so it is recommended to always use the fully dynamic variants (e.g. VecDyn instead of VecCopy and Slice instead of SliceCopy) by default. Furthermore the Copy variants may be deprecated in the future to simplify the API.

Examples

Create homogeneous untyped Vecs that store a single virtual function table for all contained elements:

use dync::VecDrop; // VecDyn<DropVTable>
// Create an untyped `Vec`.
let vec: VecDrop = vec![1_i32,2,3,4].into();
// Access elements either by downcasting to the underlying type.
for value_ref in vec.iter() {
    let int = value_ref.downcast::<i32>().unwrap();
    println!("{}", int);
}
// Or downcast the iterator directly for more efficient traversal.
for int in vec.iter_as::<i32>().unwrap() {
    println!("{}", int);
}

The VecDrop type above defaults to the empty virtual table (with the exception of the drop function), which is not terribly useful when the contained values need to be processed in some way. dync provides support for common standard library traits such as:

  • Drop
  • Clone
  • PartialEq
  • std::hash::Hash
  • std::fmt::Debug
  • Send and Sync
  • more to come

So to produce a VecDyn of a printable type, we could instead do

use dync::{VecDyn, traits::DebugVTable};
// Create an untyped `Vec` of `std::fmt::Debug` types.
let vec: VecDyn<DebugVTable> = vec![1_i32,2,3,4].into();
// We can now iterate and print value references (which inherit the VTable from the container)
// without needing a downcast.
for value_ref in vec.iter() {
    println!("{:?}", value_ref);
}

See the exmaples directory for more.

Caveats

This library does not include serialization/deserialization functionality for the provided types since these would need to handle serializing/deserializing functions in the virtual table, which is out of the scope of this library. For serialization/desrialization it is recommended to simply convert untyped collections to typed collections (e.g. VecDrop -> Vec<T>).

License

This repository is licensed under either of

at your option.