Type erased vector. All elements have the same type.

Overview

crates.io license Docs CI

Type erased vector. All elements have the same type.

Designed to be type-erased as far as possible - most of the operations does not know about concrete type.

Only destruct operations have additional overhead of indirect call.

Usage

(); // 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::().unwrap().as_slice(){ println!("{}", s); } ">
    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().as_slice(){
        println!("{}", s);
    }
    

Known alternatives

  • type_erased_vec. Allow to store Vec in type erased way, but you need to perform operations, you need to "cast" to concrete type first.
  • untyped_vec. Some operations like len, capacity performed without type knowledge; but the rest - require concrete type.
Comments
  • Element swap between untyped vec elements

    Element swap between untyped vec elements

    I'm naively trying to swap elements between two untyped AnyVec:

        #[test]
        fn anyvec_swap_sanity() {
            let mut a: AnyVec = AnyVec::new::<f32>();
            {
                let mut v = a.downcast_mut::<f32>().unwrap();
                v.push(0.0);
                v.push(1.0);
                v.push(2.0);
            }
    
            let mut b: AnyVec = AnyVec::new::<f32>();
            {
                let mut v = b.downcast_mut::<f32>().unwrap();
                v.push(10.0);
                v.push(11.0);
                v.push(12.0);
            }
    
            std::mem::swap(&mut a.at_mut(0), &mut b.at_mut(0));
    
            assert_eq!(10.0, *a.at(0).downcast_ref::<f32>().unwrap());
        }
    

    It seems it simply doesn't swap, or the swap is not doing what I expect. Is there a better way to do this?

    opened by schell 19
  • Use `NonNull`

    Use `NonNull`

    This allows Option<AnyVec> to have the same size as AnyVec. But the main reason I did this was to fix the null pointer deref that can occur when allocation fails by using the type-system to force us to handle that case with handle_alloc_error. Additionally, it fixes the UB of taking multiple unique references to ZST_SLICE by using NonNull::dangling() instead.

    opened by SabrinaJewson 9
  • Fix UB in `clear()` that happens if dropping panics

    Fix UB in `clear()` that happens if dropping panics

    Previously a panicking destructor would cause clear to return but the length not to be set to zero, allowing users to access a value that has been dropped. By prematurely setting the length to zero this problem is avoided.

    opened by SabrinaJewson 4
  • Miri test failure

    Miri test failure

    Hi, I'm trying to use this library to make some form of a type-erased map data structure. I am running cargo miri test on my tests, and I came across a failure that seems to originate from this crate. I've been able reproduce it with the following:

    let mut vec: AnyVec = AnyVec::new::<usize>();
    
    vec.push(AnyValueWrapper::new(1usize));
    
    let iter = vec.iter().map(|v| v.downcast_ref::<usize>().unwrap());
    assert!(iter.eq([&1]));
    

    The error miri outputs is:

    error: Undefined Behavior: trying to reborrow <untagged> for Unique permission at alloc86017[0x0], but that tag only grants SharedReadOnly permission for this location
       --> C:\Users\sgodw\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\core\src\ptr\non_null.rs:432:18
        |
    432 |         unsafe { &mut *self.as_ptr() }
        |                  ^^^^^^^^^^^^^^^^^^^
        |                  |
        |                  trying to reborrow <untagged> for Unique permission at alloc86017[0x0], but that tag only grants SharedReadOnly permission for this location
        |                  this error occurs as part of a reborrow at alloc86017[0x0..0x38]
        |
        = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental
        = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information
    help: tag was most recently created at offsets [0x0..0x38]
       --> src\lib.rs:18:17
        |
    18  |         assert!(iter.eq([&1]));
        |                 ^^^^^^^^^^^^^
    help: this tag was also created here at offsets [0x0..0x38]
       --> src\lib.rs:17:20
        |
    17  |         let iter = vec.iter().map(|v| v.downcast_ref::<usize>().unwrap());
        |                    ^^^^^^^^^^
        = note: inside `std::ptr::NonNull::<any_vec::any_vec_raw::AnyVecRaw<any_vec::mem::Heap>>::as_mut` at C:\Users\sgodw\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\core\src\ptr\non_null.rs:432:18
        = note: inside `any_vec::any_vec_ptr::utils::element_ptr_at::<any_vec::any_vec_ptr::AnyVecPtr<dyn any_vec::traits::None, any_vec::mem::Heap>>` at C:\Users\sgodw\.cargo\registry\src\github.com-1ecc6299db9ec823\any_vec-0.9.1\src\any_vec_ptr.rs:126:27
        = note: inside `<any_vec::Iter<any_vec::any_vec_ptr::AnyVecPtr<dyn any_vec::traits::None, any_vec::mem::Heap>, any_vec::iter::ElementRefIterItem<dyn any_vec::traits::None, any_vec::mem::Heap>> as std::iter::Iterator>::next` at C:\Users\sgodw\.cargo\registry\src\github.com-1ecc6299db9ec823\any_vec-0.9.1\src\iter.rs:83:31
        = note: inside `<std::iter::Map<any_vec::Iter<any_vec::any_vec_ptr::AnyVecPtr<dyn any_vec::traits::None, any_vec::mem::Heap>, any_vec::iter::ElementRefIterItem<dyn any_vec::traits::None, any_vec::mem::Heap>>, [closure@src\lib.rs:17:35: 17:73]> as std::iter::Iterator>::next` at C:\Users\sgodw\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\core\src\iter\adapters\map.rs:103:9
        = note: inside `<std::iter::Map<any_vec::Iter<any_vec::any_vec_ptr::AnyVecPtr<dyn any_vec::traits::None, any_vec::mem::Heap>, any_vec::iter::ElementRefIterItem<dyn any_vec::traits::None, any_vec::mem::Heap>>, [closure@src\lib.rs:17:35: 17:73]> as std::iter::Iterator>::eq_by::<[&usize; 1], [closure@<std::iter::Map<any_vec::Iter<any_vec::any_vec_ptr::AnyVecPtr<dyn any_vec::traits::None, any_vec::mem::Heap>, any_vec::iter::ElementRefIterItem<dyn any_vec::traits::None, any_vec::mem::Heap>>, [closure@src\lib.rs:17:35: 17:73]> as std::iter::Iterator>::eq<[&usize; 1]>::{closure#0}]>` at C:\Users\sgodw\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\core\src\iter\traits\iterator.rs:3538:27
        = note: inside `<std::iter::Map<any_vec::Iter<any_vec::any_vec_ptr::AnyVecPtr<dyn any_vec::traits::None, any_vec::mem::Heap>, any_vec::iter::ElementRefIterItem<dyn any_vec::traits::None, any_vec::mem::Heap>>, [closure@src\lib.rs:17:35: 17:73]> as std::iter::Iterator>::eq::<[&usize; 1]>` at C:\Users\sgodw\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\core\src\iter\traits\iterator.rs:3510:9
    note: inside `test::test` at src\lib.rs:18:17
       --> src\lib.rs:18:17
        |
    18  |         assert!(iter.eq([&1]));
        |                 ^^^^^^^^^^^^^
    note: inside closure at src\lib.rs:12:5
       --> src\lib.rs:12:5
        |
    11  |       #[test]
        |       ------- in this procedural macro expansion
    12  | /     fn test() {
    13  | |         let mut vec: AnyVec = AnyVec::new::<usize>();
    14  | |
    15  | |         vec.push(AnyValueWrapper::new(1usize));
    ...   |
    18  | |         assert!(iter.eq([&1]));
    19  | |     }
        | |_____^
        = note: this error originates in the attribute macro `test` (in Nightly builds, run with -Z macro-backtrace for more info)
    

    It looks like it's violating stacked borrows which are experimental (not too familiar with the details to be honest), so not sure if it's an actual problem at the moment.

    opened by sgodwincs 1
  • Don't allow unsoundly creating `&mut` from `&`

    Don't allow unsoundly creating `&mut` from `&`

    This fixes a soundness issue in as_mut_slice and as_mut_slice_unchecked where the API would allow users to create aliasing &muts to the same slice.

    opened by SabrinaJewson 1
Releases(v0.11.0)
  • v0.11.0(Aug 26, 2022)

    Added

    AnyValueUnknown

    • AnyValue split into AnyValueUnknown + AnyValue.
    • AnyValueMut split into AnyValueMutUnknown + AnyValueMut.
    • AnyVec::push_unchecked(AnyValueUnknown).
    • AnyVec::insert_unchecked(usize, AnyValueUnknown).
    • AnyValueRawUnknown.
    • mem::Empty.

    Raw parts

    • AnyVec::into_raw_parts / AnyVec::from_raw_parts / RawParts.
    • MemRawParts.
    • AnyVec::element_drop.
    • AnyVec::element_clone.

    Changed

    • HeapMem implements MemRawParts.

    Fixed

    • AnyVec::splice now check types.
    Source code(tar.gz)
    Source code(zip)
  • v0.10.0(Jul 10, 2022)

    Changed

    • AnyValue::bytes()->*const u8 and AnyValue::size()->usize replaced with AnyValue::as_bytes()->&[u8]. Same for AnyValueMut.
    • AnyValueWrapper now AnyValueMut.
    • AnyValueRaw now AnyValueMut.
    • AnyValue::as_bytes() now return &[u8].

    Added

    • Debug implemented for AnyVec, AnyVecTyped.
    • AnyValueMut::swap() added.
    • AnyVec/AnyVecTyped ::set_len() added.
    • AnyVec::as_bytes_mut added.
    • AnyVec::spare_bytes_mut added.
    • AnyVecTyped::spare_capacity_mut added.
    • mem::StackN added.

    Fixed

    • Stacked Borrow friendly now.
    • mem::Stack capacity fixed.
    Source code(tar.gz)
    Source code(zip)
  • v0.9.1(Jun 28, 2022)

    Changed

    • impls dependency dropped.
    • minimum rust version 1.61 requirement dropped.

    Fixed

    • Empty HeapMem used wrong aligned dangling pointer. Fixed.
    • AnyVec Send/Sync -ability now MemBuilder dependent.
    • Fixed UB with StackMem::as_ptr.
    Source code(tar.gz)
    Source code(zip)
  • v0.9.0(Jun 21, 2022)

  • v0.8.0(Jun 19, 2022)

    Added

    • Added AnyVec::at - ergonomic version of get.
    • AnyVecRef now cloneable.
    • ElementRef now cloneable.
    • non-consuming iterators now cloneable.
    • AnyVec::drain.
    • AnyVecTyped::drain.
    • AnyVec::slice.
    • AnyVecTyped::slice.
    • AnyVec iterators.
    • AnyVec::clone_empty, to construct AnyVec of the same type.
    • IntoIterator implemented.

    Changed

    • crate::refs being implementation details, hided.
    Source code(tar.gz)
    Source code(zip)
  • v0.7.0(Jun 8, 2022)

    Added

    • AnyValueClonable and LazyClone added.
    • AnyVec getters added.
    • AnyValueMut added. All remove operations now return AnyValueMut + AnyValueClonable.

    Changed

    • any_value::AnyValue::downcast<T> now return Option<T>.
    • traits::EmptyTrait renamed to traits::None.
    • AnyValue interface changed.

    Optimized

    • Performance of all remove operations slightly increased.
    Source code(tar.gz)
    Source code(zip)
  • v0.6.0(May 29, 2022)

    Added

    • AnyVec now can be Sync, Send, Clone.

    Changed

    • any_value::AnyValueTemp moved to ops::AnyValueTemp
    • any_vec::Unknown -> any_vec::any_value::Unknown

    Fixed

    • AnyVec::insert now check type again.
    • AnyValueWrapper::downcast UB fx.
    Source code(tar.gz)
    Source code(zip)
  • v0.5.0(May 22, 2022)

    Changed

    • Major type erased API change. All AnyVec operations now safe.

    Added

    • Introduced any_value family, which provide type erased safe operations.
    Source code(tar.gz)
    Source code(zip)
  • v0.4.0(May 18, 2022)

  • v0.3.0(May 17, 2022)

  • v0.2.2(May 13, 2022)

    Optimized

    • swap_remove further optimized.
    • swap_take on par with Vec::swap_remove now.

    Fixed

    • Fixed UB in swap_remove that happens if element destructor panics.
    Source code(tar.gz)
    Source code(zip)
  • v0.2.1(May 12, 2022)

    Optimized

    • All remove operations become faster. Destructor function is not called now, if type does not need drop.

    Changed

    • AnyVec is now Option-friendly. (by @SabrinaJewson)
    • It is now possible for AnyVec to have zero capacity.
    • AnyVec::new() now starts with zero capacity.

    Fixed

    • Fixed UB with construction with ZST. (by @SabrinaJewson)
    • Fixed UB in clear() that happens if dropping panics. (by @SabrinaJewson)
    • as_mut_slice family now take &mut self instead of &self. (by @SabrinaJewson)
    Source code(tar.gz)
    Source code(zip)
  • v0.2.0(May 11, 2022)

    Added

    • AnyVec::with_capacity added.
    • push benchmark added.

    Changed

    • AnyVec::element_size removed, AnyVec::element_layout added instead.

    Optimized

    • push family performance improved.

    Fixed

    • Fixed Zero-Size-Type memory allocation.
    Source code(tar.gz)
    Source code(zip)
  • v0.1.0(May 10, 2022)

Owner
null
A tool and library to losslessly join multiple .mp4 files shot with same camera and settings

mp4-merge A tool and library to losslessly join multiple .mp4 files shot with same camera and settings. This is useful to merge multiple files that ar

Gyroflow 7 Jan 2, 2023
Build database expression type checker and vectorized runtime executor in type-safe Rust

Typed Type Exercise in Rust Build database expression type checker and vectorized runtime executor in type-safe Rust. This project is highly inspired

Andy Lok 89 Dec 27, 2022
Powerful math lib for Vector, Matrix and Quaternion operations

An opinionated, powerful math lib for Vector2, Vector3, Matrix and Quaternion operations Vector2 Add, Sub, Div, Mul, Eq Distance Move towards target a

O(ʒ) 4 Mar 28, 2022
Powerful math lib for Vector, Matrix and Quaternion operations

An opinionated, powerful math lib for Vector2, Vector3, Matrix and Quaternion operations Vector2 Add, Sub, Div, Mul, Eq Distance Move towards target a

O(ʒ) 4 Mar 28, 2022
A HashMap/Vector hybrid: efficient, ordered key-value data storage in Rust.

hashvec A HashVec is a hash map / dictionary whose key-value pairs are stored (and can be iterated over) in a fixed order, by default the order in whi

Skye Terran 2 May 16, 2022
Compact, clone-on-write vector and string.

ecow Compact, clone-on-write vector and string. Types An EcoVec is a reference-counted clone-on-write vector. It takes up two words of space (= 2 usiz

Typst 78 Apr 18, 2023
Vemcache is an in-memory vector database.

Vemcache Vemcache is an in-memory vector database. Vemcache can be thought of as the Redis equivalent for vector databases. Getting Started Prerequisi

Faizaan Chishtie 8 May 21, 2023
The Fast Vector Similarity Library is designed to provide efficient computation of various similarity measures between vectors.

Fast Vector Similarity Library Introduction The Fast Vector Similarity Library is designed to provide efficient computation of various similarity meas

Jeff Emanuel 243 Sep 6, 2023
The first compute-centric vector graphic video game

??️ Vong This repository contains source code for the first native use of a compute-centric vector graphics video game, inspired by Pong. ✍️ Authors @

Spencer C. Imbleau 29 Nov 24, 2023
An AI-native lightweight, reliable, and high performance open-source vector database.

What is OasysDB? OasysDB is a vector database that can be used to store and query high-dimensional vectors. Our goal is to make OasysDB fast and easy

Oasys 3 Dec 25, 2023
Rust Vector for large amounts of data, that does not copy when growing, by using full `mmap`'d pages.

Large Vector Rust Vector for large amounts of data, that does not copy when growing, by using full mmap'd pages. Maturity I made ths to learn about mm

Wonko der Verständige 21 Apr 23, 2024
Rust Programming Fundamentals - one course to rule them all, one course to find them...

Ultimate Rust Crash Course This is the companion repository for the Ultimate Rust Crash Course published online, presented live at O'Reilly virtual ev

Nathan Stocks 1.3k Jan 8, 2023
OOLANG - an esoteric stack-based programming language where all instructions/commands are differnet unicode O characters

OOLANG is an esoteric stack-based programming language where all instructions/commands are differnet unicode O characters

RNM Enterprises 2 Mar 20, 2022
In this repository you can find modules with code and comments that explain rust syntax and all about Rust lang.

Learn Rust What is this? In this repository you can find modules with code and comments that explain rust syntax and all about Rust lang. This is usef

Domagoj Ratko 5 Nov 5, 2022
A simple library to get all pairs from any Dex and sync reserves.

pair_sync A simple library to get all pairs from any supported Dex and sync reserves. Crates.io Documentation in progress Filename: examples/sync-pair

null 116 Dec 30, 2022
A simple and convenient way to bundle owned data with a borrowing type.

A simple and convenient way to bundle owned data with a borrowing type. The Problem One of the main selling points of Rust is its borrow checker, whic

Dmitry Zamkov 20 Dec 21, 2022
An implementation of a predicative polymorphic language with bidirectional type inference and algebraic data types

Vinilla Lang Vanilla is a pure functional programming language based on System F, a classic but powerful type system. Merits Simple as it is, Vanilla

Zehao Chen 73 Aug 4, 2022
A statically-typed, interpreted programming language, with generics and type inference

Glide A programming language. Currently, this includes: Static typing Generics, with monomorphization Type inference on function calls func identity<T

Patrick Gu 1 Apr 10, 2022
A type-safe, high speed programming language for scalable systems

A type-safe, high speed programming language for scalable systems! (featuring a cheesy logo!) note: the compiler is unfinished and probably buggy. if

Hail 0 Sep 14, 2022