49个版本 (25个重大更改)
新版本 0.25.0 | 2024年8月23日 |
---|---|
0.23.1 | 2024年8月6日 |
0.22.1 | 2024年7月28日 |
0.11.0 | 2024年3月30日 |
0.1.0 | 2023年7月27日 |
在 编程语言 中排名 #974
每月下载量 240,862
用于 20 个crate(6个直接使用)
80KB
1.5K SLoC
该crate是 index_vec
的分支,https://github.com/thomcc/index_vec 它帮助定义围绕 usize
(或其他整数)的 "newtype"-style包装器,Vec<T>
和 [T]
,以便在不增加成本的情况下获得一些额外的类型安全性。
示例/概述
use index_vec::{IndexVec, IndexSlice, index_vec};
index_vec::define_index_type! {
// Define StrIdx to use only 32 bits internally (you can use usize, u16,
// and even u8).
pub struct StrIdx = u32;
// The defaults are very reasonable, but this macro can let
// you customize things quite a bit:
// By default, creating a StrIdx would check an incoming `usize against
// `u32::max_value()`, as u32 is the wrapped index type. Lets imagine that
// StrIdx has to interface with an external system that uses signed ints.
// We can change the checking behavior to complain on i32::max_value()
// instead:
MAX_INDEX = i32::max_value() as usize;
// We can also disable checking all-together if we are more concerned with perf
// than any overflow problems, or even do so, but only for debug builds: Quite
// pointless here, but an okay example
DISABLE_MAX_INDEX_CHECK = cfg!(not(debug_assertions));
// And more too, see this macro's docs for more info.
}
// Create a vector which can be accessed using `StrIdx`s.
let mut strs: IndexVec<StrIdx, &'static str> = index_vec!["strs", "bar", "baz"];
// l is a `StrIdx`
let l = strs.last_idx();
assert_eq!(strs[l], "baz");
let new_i = strs.push("quux");
assert_eq!(strs[new_i], "quux");
// The slice APIs are wrapped as well.
let s: &IndexSlice<StrIdx, [&'static str]> = &strs[StrIdx::new(1)..];
assert_eq!(s[0], "bar");
// Indices are mostly interoperable with `usize`, and support
// a lot of what you might want to do to an index.
// Comparison
assert_eq!(StrIdx::new(0), 0usize);
// Addition
assert_eq!(StrIdx::new(0) + 1, 1usize);
// Subtraction
assert_eq!(StrIdx::new(1) - 1, 0usize);
// Wrapping
assert_eq!(StrIdx::new(5) % strs.len(), 1usize);
// ...
背景
目标是帮助使用 type FooIdx = usize
来访问 Vec<Foo>
,通过某种可以静态地防止在 Vec<Bar>
中使用 FooIdx
的方式。如果你有一堆引用不同类型向量的索引,这将非常有用。
代码最初基于 rustc
的 IndexVec
代码,但是除了简单的情况(例如Vec包装器)外,几乎全部重写了。
其他crate
该 indexed_vec
crate 之前就存在,并且是 rustc
代码的一个更接近的副本。不幸的是,这意味着它不能在稳定版上编译。
如果您正在寻找介于 vec 和 map 之间的东西,您可能会发现 handy
、slotmap
或 slab
更符合您的需求。
常见问题解答
define_index_type
作为过程宏不是更好吗?
可能吧。它不是过程宏,因为我总是尽量避免使用过程宏,以尽量减少编译时间。如果过程宏的编译时间问题得到解决,那么我会重新考虑这个问题。
我可能还会添加一个不是必需的过程宏特性,但可以避免一些不必要的东西。
define_index_type
做得太多吗?
可能吧。它定义了一个类型,实现了该类型上的一组函数,以及相当多的特质。但它的目的是让从 Vec<T>
+ usize
到 IndexVec<I, T>
的过程尽可能不痛苦。如果让它由开发者来完成这些事情,那么使用它可能会变得非常麻烦,以至于不值得使用。
define_index_type
的选项语法很糟糕。
我愿意听取建议。
它支持 no_std 吗?
是的,尽管它当然使用了 extern crate alloc;
。
它支持 serde 吗?
是的,但前提是您必须启用 serialize
特性。
计划添加哪些特性?
虽然“计划”这个词用得有点夸张,但我认为以下这些功能将会很有用。
- 支持切片/vec API 的任何剩余部分。
- 为 SmallVec/ArrayVec 添加类型安全的包装器(当然,通过 cargo
feature
实现)。 - 为
define_index_type
宏提供更好的语法(目前还没有具体想法)。 - 允许生成的类型是元组结构体,或者使用特定的字段名。
- 允许使用索引类型,如 NonZeroU32 等,如果可以做到合理的话。
- 允许索引类型,如 NonZeroU32 等,如果可以做到合理的话。
- ...
依赖关系
~170KB