#vec #slice #nightly #heap #interface #array #std

no-std generic-vec

适用于no_std环境的向量实现

3个版本

0.1.2 2020年12月4日
0.1.1 2020年12月4日
0.1.0-alpha2020年12月2日

#190内存管理

MIT/Apache

170KB
3K SLoC

Crates.io Docs.rs Workflow Status Maintenance

generic-vec

可以存储任何位置的项目:切片、数组或堆中的向量!

GenericVecVec完全兼容,甚至提供了一些仅在std上的nightly版本中存在的功能(如GenericVec::drain_filter),或者更宽松的接口如GenericVec::retain。实际上,您可以轻松地将一个Vec转换为HeapVec并返回!

此crate与no_std兼容,只需关闭所有默认功能即可。

特性

  • std(默认)- 允许您使用分配器,并且
  • alloc - 允许您使用分配器,用于堆分配存储(如Vec
  • nightly - 允许您使用基于数组的存储([T; N]

基本用法

SliceVecInitSliceVec

SliceVecInitSliceVec非常相似,您向它们提供一个切片缓冲区,并将它们的所有值存储在该缓冲区中。但它们之间有三个主要区别。

  • 您可以将未初始化的缓冲区传递给SliceVec
  • 您只能使用Copy类型与InitSliceVec
  • 只要您保持在容量范围内(您传递的切片的长度),您就可以自由设置InitSliceVec的长度
use generic_vec::{SliceVec, InitSliceVec, uninit_array};

let mut uninit_buffer = uninit_array!(16);
let mut slice_vec = SliceVec::new(&mut uninit_buffer);

assert!(slice_vec.is_empty());
slice_vec.push(10);
assert_eq!(slice_vec, [10]);
let mut init_buffer = [0xae; 16];
let mut slice_vec = InitSliceVec::new(&mut init_buffer);

assert!(slice_vec.is_full());
assert_eq!(slice_vec.pop(), 0xae);
slice_vec.set_len(16);
assert!(slice_vec.is_full());

当然,如果您尝试超出*SliceVec的容量(您传递的切片的长度),则它将恐慌。

let mut init_buffer = [0xae; 16];
let mut slice_vec = InitSliceVec::new(&mut init_buffer);
slice_vec.push(0);

类型Vec

TypeVec 是一个拥有缓冲区。你可以这样使用:

use generic_vec::{TypeVec, gvec};
let mut vec: TypeVec<u32, [u32; 4]> = gvec![1, 2, 3, 4];

assert_eq!(vec, [1, 2, 3, 4]);

vec.try_push(5).expect_err("Tried to push past capacity!");

第二个参数指定缓冲区类型,可以是任何你想要的类型。只关心类型的大小。还有一个默认的第三个参数,但只有在了解 UninitBuffer 文档后才能使用。

这个框架的一个巧妙副作用是,你也可以为空大小的类型获得高效的 GenericVec,大小仅为 usize!这个功能可以在稳定版本的 no_std 上使用。

ArrayVecInitArrayVec

ArrayVecInitArrayVec 与切片版本类似,但由于它们拥有自己的数据,因此可以自由移动,不受限制。你也可以不传递现有缓冲区就创建一个新的 ArrayVec,这与切片版本不同。

在稳定版本中,你可以使用 ArrayVecInitArrayVec 来构建类型。在 nightly 中,你可以使用类型别名 ArrayVecInitArrayVec。一旦 min_const_generics 进入稳定版,这些宏将被弃用。

在稳定版本中,唯一限制是只能使用 InitArrayVec 的容量达到 32。即 InitArrayVec![i32; 33] 不起作用。ArrayVec 没有这个限制,因为它建立在 TypeVec 之上。

use generic_vec::ArrayVec;

let mut array_vec = ArrayVec::<i32, 16>::new();

array_vec.push(10);
array_vec.push(20);
array_vec.push(30);

assert_eq!(array_vec, [10, 20, 30]);

ArrayVecInitArrayVec 之间的区别与它们的切片版本相同。

ZSVec

use generic_vec::ZSVec;

struct MyType;

let mut vec = ZSVec::new();

vec.push(MyType);
vec.push(MyType);
vec.push(MyType);

assert_eq!(vec.len(), 3);
assert_eq!(std::mem::size_of_val(&vec), std::mem::size_of::<usize>());

alloc

HeapVec 只是 Vec,但建立在 GenericVec 之上,这意味着你可以免费获得 GenericVec 的所有功能!但这就需要启用 allocstd 功能。

use generic_vec::{HeapVec, gvec};
let mut vec: HeapVec<u32> = gvec![1, 2, 3, 4];
assert_eq!(vec.capacity(), 4);
vec.extend(&[5, 6, 7, 8]);

assert_eq!(vec, [1, 2, 3, 4, 5, 6, 7, 8]);

vec.try_push(5).expect_err("Tried to push past capacity!");

nightly

nightly

  • InitArrayVec 长度的限制消失了。
  • 许多函数/方法变为 const fn 类型
  • 启用了一些优化
  • 一些诊断变得更好

关于文档的说明:如果功能存在于 Vec 中,则文档要么与 Vec 完全相同,要么略作修改以更好地适应 GenericVec

关于实现的说明:实现的大部分内容直接来自 Vec,所以感谢出色的参考 std

当前版本:0.1.2

许可证:MIT/Apache-2.0

无运行时依赖