Split Vecs in O(1) time.
You can split a [Vec
] into two using Vec::split_off
,
but since most allocators can't just go and split up an allocation, this needs to allocate space
for a second [Vec
] and, even worse, copy the relevant elements over, which takes O(n) time.
You could also split it into slices using Vec::split_at
or
Vec::split_at_mut
, but this will not give you owned
data you can move around or move out of at will.
This crate provides a way to split a [Vec
] into two owned [VecShard
]s that
behave similar to Vecs that takes constant time.
The catch is that the [VecShard
]s use reference counting to determine when the last of them is dropped.
Only then is the memory from the original [Vec
] deallocated.
The individual items in the shards, however, are dropped as soon as the shard is dropped.
This functionality is provided through an extension trait for [Vec
], ShardExt
.
```rust use vecshard::ShardExt;
let animals = vec!["penguin", "owl", "toucan", "turtle", "spider", "mosquitto"];
// split the vec into 2 shards let (coolanimals, uncoolanimals) = animals.splitinplaceat(4);
// shards can be indexed as usual asserteq!(coolanimals[3], "turtle"); asserteq!(uncoolanimals[0], "spider");
// ..including with a range as index asserteq!(coolanimals[1..3], ["owl", "toucan"]);
// they deref into slices, so you can use them as such: asserteq!(coolanimals.len(), 4); assert!(uncoolanimals.endswith(&["mosquitto"]));
// shards can also be split up again: let (coolbirds, coolreptiles) = coolanimals.splitinplaceat(3); asserteq!(cool_birds, ["penguin", "owl", "toucan"]); assert_eq!(cool_reptiles, ["turtle"]); ```
Shards can be freely converted both From
and Into
Vecs.
Note that the latter may need to allocate if there are other shards also using the shards allocation.
```rust
let vec = vec![1, 2, 3]; let shard = VecShard::from(vec); let vec2 : Vec<_> = shard.into(); ```
To iterate over a [VecShard
], you have several choices.
VecShard<T>
itself is a draining [Iterator
] and returns owned T
instances,
removing them from its own storage.
If you only need &T
or &mut T
, you can deref it to a slice and iterate over that.
Finally, if you need an owning [Iterator
] but do not want to drain the shard,
you can [clone
][std::clone::Clone::clone] the shard and iterate over that.
```rust let mut shard = VecShard::from(vec!['y', 'e', 'e', 't']);
asserteq!(Some('y'), shard.next()); asserteq!(Some('e'), shard.next());
assert_eq!(*shard, ['e', 't']); ```
License: CC0-1.0