https://github.com/tower120/any_vec
Rust type erased vector.
https://github.com/tower120/any_vec
any rust type-erasure vector
Last synced: 4 months ago
JSON representation
Rust type erased vector.
- Host: GitHub
- URL: https://github.com/tower120/any_vec
- Owner: tower120
- License: other
- Created: 2022-05-10T16:38:51.000Z (about 4 years ago)
- Default Branch: main
- Last Pushed: 2025-08-25T17:54:44.000Z (11 months ago)
- Last Synced: 2026-02-12T17:22:05.917Z (5 months ago)
- Topics: any, rust, type-erasure, vector
- Language: Rust
- Homepage:
- Size: 168 KB
- Stars: 22
- Watchers: 2
- Forks: 3
- Open Issues: 2
-
Metadata Files:
- Readme: Readme.md
- Changelog: CHANGELOG.md
- License: LICENSE-APACHE
Awesome Lists containing this project
README
[](https://crates.io/crates/any_vec)
[](#license)
[](https://docs.rs/any_vec)
[](https://github.com/tower120/any_vec/actions/workflows/ci.yml)
[](https://codecov.io/gh/tower120/any_vec)
Type erased vector. All elements have the same type.
Designed to be type-erased as far as possible - most operations do not know a concrete type.
For example, you can move or copy/clone items from one type-erased vector to another, without ever knowing
their type. Or you can erase, swap, move, copy elements inside type-erased vector, etc...
Only type-erased destruct and clone operations have additional overhead of indirect call.
# Usage
```rust
let mut vec: AnyVec = AnyVec::new::();
{
// Typed operations.
let mut vec = vec.downcast_mut::().unwrap();
vec.push(String::from("0"));
vec.push(String::from("1"));
vec.push(String::from("2"));
}
let mut other_vec: AnyVec = AnyVec::new::();
// 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(){
println!("{}", s);
}
```
See [documentation](https://docs.rs/any_vec) for more.
## Send, Sync, Clone
You can make `AnyVec` `Send`able, `Sync`able, `Clone`able:
```rust
use any_vec::AnyVec;
use any_vec::traits::*;
let v1: AnyVec = AnyVec::new::();
let v2 = v1.clone();
```
This constraints will be applied compiletime to element type:
```rust
// This will fail to compile.
let v1: AnyVec = AnyVec::new::>();
```
Non-Clonable `AnyVec` has a size 1 pointer smaller.
## LazyClone
Whenever possible, `any_vec` type erased elements can be lazily cloned:
```rust
let mut v1: AnyVec = AnyVec::new::();
v1.push(AnyValueWrapper::new(String::from("0")));
let mut v2: AnyVec = AnyVec::new::();
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`:
```rust
type FixedAnyVec = AnyVec>;
let mut any_vec: FixedAnyVec = AnyVec::new::();
// 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:
```rust
fn self_push_first_element(any_vec: &mut AnyVec){
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.
## no_std + no_alloc
This is `no_std` library, which can work without `alloc` too.
### Changelog
See [CHANGELOG.md](CHANGELOG.md) for version differences.
# Known alternatives
* [type_erased_vec](https://crates.io/crates/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](https://crates.io/crates/untyped_vec). Some operations like `len`, `capacity` performed without type
knowledge; but the rest - require concrete type.