16个版本 (10个稳定版)
3.1.0 | 2022年9月2日 |
---|---|
3.0.3 | 2021年5月27日 |
3.0.2 | 2020年11月22日 |
3.0.1 | 2020年10月30日 |
0.0.3 | 2020年7月14日 |
#204 in 数据结构
9,695 每月下载量
用于 36 个crate (6 个直接使用)
155KB
2.5K SLoC
typed-index-collections
typed-index-collections
crate提供了TiSlice
和TiVec
结构体,它们是Rust的slice
和std::vec::Vec
类型的类型索引版本。
简介
在优化、面向数据设计和使用数组结构体时,大量使用切片和向量而不是引用和智能指针可能是有用的。但是,在处理大量切片和向量时,很容易错误地使用错误的索引,这是常见的错误来源。
关于
此crate提供了TiSlice<K, V>
和TiVec<K, V>
容器,这些容器只能通过指定的索引类型K
进行索引。这些容器是围绕切片原语[V]
和容器std::vec::Vec<V>
的包装。crate容器映射匹配Rust容器的稳定API,尽可能转发。
TiSlice
和 TiVec
可以通过使用 From
、Into
、AsRef
和 AsMut
特性,轻松转换为匹配的 Rust 容器以及反向转换。此外,它们还公开了原始数据类型的 raw
属性。容器只需要实现 From<usize>
和 Into<usize>
特性,这可以通过 derive_more
crate 和 #[derive(From, Into)]
轻松完成。
用法
首先,将以下内容添加到您的 Cargo.toml
[dependencies]
typed-index-collections = "3.1.0"
此 crate 默认依赖于标准库,这对调试和一些额外功能很有用。要在 #![no_std]
上下文中使用此 crate,请在您的 Cargo.toml
中使用 default-features = false
,如下所示
[dependencies.typed-index-collections]
version = "3.1.0"
default-features = false
features = ["alloc"]
如果您想使用 derive_more
为 From<usize>
和 Into<usize>
实现添加它到您的 Cargo.toml
,如下所示
[dependencies]
derive_more = "0.99"
typed-index-collections = "3.1.0"
示例
使用 derive_more
的简单示例
use typed_index_collections::TiVec;
use derive_more::{From, Into};
#[derive(From, Into)]
struct FooId(usize);
let mut ti_vec: TiVec<FooId, usize> = std::vec![10, 11, 13].into();
ti_vec.insert(FooId(2), 12);
assert_eq!(ti_vec[FooId(2)], 12);
如果使用了错误的索引类型,编译将失败
use typed_index_collections::TiVec;
use derive_more::{From, Into};
#[derive(From, Into)]
struct FooId(usize);
#[derive(From, Into)]
struct BarId(usize);
let mut ti_vec: TiVec<FooId, usize> = std::vec![10, 11, 13].into();
ti_vec.insert(BarId(2), 12);
// ^^^^^^^^ expected struct `FooId`, found struct `BarId`
assert_eq!(ti_vec[BarId(2)], 12);
// ^^^^^^^^^^^^^^^^ the trait ... is not implemented for `BarId`
另一个带有 derive_more
的更详细的示例
use typed_index_collections::{TiSlice, TiVec};
use derive_more::{From, Into};
#[derive(Clone, Copy, Debug, From, Into, Eq, PartialEq)]
struct FooId(usize);
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
struct Foo {
value: usize,
}
let first = Foo { value: 1 };
let second = Foo { value: 2 };
let slice_ref = &[first, second][..];
let vec = std::vec![first, second];
let boxed_slice = std::vec![first, second].into_boxed_slice();
let ti_slice_ref: &TiSlice<FooId, Foo> = slice_ref.as_ref();
let ti_vec: TiVec<FooId, Foo> = vec.into();
let ti_boxed_slice: std::boxed::Box<TiSlice<FooId, Foo>> = boxed_slice.into();
assert_eq!(ti_vec[FooId(1)], second);
assert_eq!(ti_vec.raw[1], second);
assert_eq!(ti_vec.last(), Some(&second));
assert_eq!(ti_vec.last_key_value(), Some((FooId(1), &second)));
assert_eq!(ti_vec.iter_enumerated().next(), Some((FooId(0), &first)));
let _slice_ref: &[Foo] = ti_slice_ref.as_ref();
let _vec: std::vec::Vec<Foo> = ti_vec.into();
let _boxed_slice: std::boxed::Box<[Foo]> = ti_boxed_slice.into();
文档
功能标志
alloc
(默认启用):启用需要内存分配的类型和函数。std
(默认启用):启用所有std
功能,例如内存分配、std::error::Error
特性和std::panic::UnwindSafe
特性实现。serde
:为Serialize
trait实现了对TiSlice
和TiVec
容器。serde-alloc
:启用alloc
和serde/alloc
功能,并实现了对Box
<
TiSlice
>
和TiVec
的Deserialize
trait。serde-std
:启用std
和serde/std
功能,并实现了对Box
<
TiSlice
>
和TiVec
的Deserialize
trait。
类似包
typed_index_collection
提供了一个API非常有限的Vec
包装器。索引是u32的包装器,不可定制,只能索引特定类型的容器。indexed_vec
是来自librustc_index
的IndexVec
结构的最近副本,但其API与标准Ruststd::vec::Vec
不同,并且没有类型化的切片slice
替代方案。index_vec
提供了slice
和std::vec::Vec
包装器,API更接近标准API。但它隐式允许您在get方法和索引表达式中使用usize
,这会降低类型安全性,并且使用宏define_index_type!
生成一个新的类型化索引结构,隐式实现了许多我认为只有在需要时才应该使用特定于此的crates实现的trait,例如derive_more
。
许可证
在以下任一许可证下授权
- Apache License,版本2.0(LICENSE-APACHE或https://apache.ac.cn/licenses/LICENSE-2.0)
- MIT许可证(LICENSE-MIT或https://opensource.org/licenses/MIT)
由您选择。
贡献
除非您明确声明,否则根据Apache-2.0许可证定义,您有意提交以包含在作品中的任何贡献,均应作为上述双许可处理,不附加任何额外条款或条件。
依赖项
~170KB