Crate any_vec

source ·
Expand description

Type erased vector AnyVec. Allow to store elements of the same type. Have same performance and operations as std::vec::Vec.

You can downcast type erased AnyVec to concrete AnyVecTyped with downcast-family. Or use AnyVec type erased operations, which works with any_value.

    use any_vec::AnyVec;
    let mut vec: AnyVec = AnyVec::new::<String>();
    {
        // Typed operations.
        let mut vec = vec.downcast_mut::<String>().unwrap();
        vec.push(String::from("0"));
        vec.push(String::from("1"));
        vec.push(String::from("2"));
    }

    let mut other_vec: AnyVec = AnyVec::new::<String>();
    // Fully type erased element move from one vec to another
    // without intermediate mem-copies.
    let element = vec.swap_remove(0);
    other_vec.push(element);

    // Output 2 1
    for s in vec.downcast_ref::<String>().unwrap(){
        println!("{}", s);
    }

N.B. AnyVecTyped operations may be somewhat faster, due to the fact that compiler able to do better optimisation with full type knowledge.

§Send, Sync, Clone

You can make AnyVec Sendable, Syncable, Cloneable:

 use any_vec::AnyVec;
 use any_vec::traits::*;
 let v1: AnyVec<dyn Cloneable + Sync + Send> = AnyVec::new::<String>();
 let v2 = v1.clone();

This constraints will be applied compiletime to element type:

 let v1: AnyVec<dyn Sync + Send> = AnyVec::new::<Rc<usize>>();

§LazyClone

Whenever possible, any_vec types implement AnyValueCloneable, which can work with LazyClone:

 let mut v1: AnyVec<dyn Cloneable> = AnyVec::new::<String>();
 v1.push(AnyValueWrapper::new(String::from("0")));

 let mut v2: AnyVec<dyn Cloneable> = AnyVec::new::<String>();
 let e = v1.swap_remove(0);
 v2.push(e.lazy_clone());
 v2.push(e.lazy_clone());

§MemBuilder

MemBuilder + Mem works like Allocator for AnyVec. But unlike allocator, Mem container-specialized design allows to perform more optimizations. For example, it is possible to make stack-allocated FixedAnyVec and small-buffer-optimized(SBO) SmallAnyVec from AnyVec by just changing MemBuilder:


 type FixedAnyVec<Traits = dyn None> = AnyVec<Traits, Stack<512>>;
 let mut any_vec: FixedAnyVec = AnyVec::new::<String>();

 // This will be on stack, without any allocations.
 any_vec.push(AnyValueWrapper::new(String::from("0")))

With help of clone_empty_in you can use stack allocated, or SBO AnyVec as fast intermediate storage for values of unknown type:


 fn self_push_first_element<T: Trait + Cloneable>(any_vec: &mut AnyVec<T>){
    let mut tmp = any_vec.clone_empty_in(StackN::<1, 256>);
    tmp.push(any_vec.at(0).lazy_clone());
    any_vec.push(tmp.pop().unwrap());
 }

MemBuilder interface, being stateful, allow to make Mem, which can work with complex custom allocators.

§AnyValue

Being type erased, AnyVec needs a way to operate on untyped values safely. Instead of working with plain *mut u8, AnyVec operates with any_value.

AnyValue is a trait, that provide operations to work with type erased values. Any type that implements AnyValue can be used with AnyVec. AnyValue interface allows to perform postponed operations on consumption. This trick used heavily by AnyVec destructive operations, which instead of concrete type return AnyValue, which perform actual operation on value drop.

Implementing AnyValueMut and AnyValueCloneable makes type mutable and cloneable respectively.

§No alloc

This library is no_std and can work without alloc. For this - disable default alloc feature. mem::Heap will become unavailable after that, and you’ll have to specify MemBuilder for AnyVec. You can use mem::Stack, or specify your own Mem.

Modules§

Structs§

Traits§

Type Aliases§