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

Download history 1325/week @ 2024-05-03 1340/week @ 2024-05-10 3803/week @ 2024-05-17 2458/week @ 2024-05-24 56247/week @ 2024-05-31 66603/week @ 2024-06-07 50837/week @ 2024-06-14 84460/week @ 2024-06-21 78326/week @ 2024-06-28 61156/week @ 2024-07-05 62745/week @ 2024-07-12 59417/week @ 2024-07-19 69054/week @ 2024-07-26 62563/week @ 2024-08-02 49203/week @ 2024-08-09 46528/week @ 2024-08-16

每月下载量 240,862
用于 20 个crate(6个直接使用)

MIT 许可证

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 的方式。如果你有一堆引用不同类型向量的索引,这将非常有用。

代码最初基于 rustcIndexVec 代码,但是除了简单的情况(例如Vec包装器)外,几乎全部重写了。

其他crate

indexed_vec crate 之前就存在,并且是 rustc 代码的一个更接近的副本。不幸的是,这意味着它不能在稳定版上编译。

如果您正在寻找介于 vec 和 map 之间的东西,您可能会发现 handyslotmapslab 更符合您的需求。

常见问题解答

define_index_type 作为过程宏不是更好吗?

可能吧。它不是过程宏,因为我总是尽量避免使用过程宏,以尽量减少编译时间。如果过程宏的编译时间问题得到解决,那么我会重新考虑这个问题。

我可能还会添加一个不是必需的过程宏特性,但可以避免一些不必要的东西。

define_index_type 做得太多吗?

可能吧。它定义了一个类型,实现了该类型上的一组函数,以及相当多的特质。但它的目的是让从 Vec<T> + usizeIndexVec<I, T> 的过程尽可能不痛苦。如果让它由开发者来完成这些事情,那么使用它可能会变得非常麻烦,以至于不值得使用。

define_index_type 的选项语法很糟糕。

我愿意听取建议。

它支持 no_std 吗?

是的,尽管它当然使用了 extern crate alloc;

它支持 serde 吗?

是的,但前提是您必须启用 serialize 特性。

计划添加哪些特性?

虽然“计划”这个词用得有点夸张,但我认为以下这些功能将会很有用。

  • 支持切片/vec API 的任何剩余部分。
  • 为 SmallVec/ArrayVec 添加类型安全的包装器(当然,通过 cargo feature 实现)。
  • define_index_type 宏提供更好的语法(目前还没有具体想法)。
  • 允许生成的类型是元组结构体,或者使用特定的字段名。
  • 允许使用索引类型,如 NonZeroU32 等,如果可以做到合理的话。
  • 允许索引类型,如 NonZeroU32 等,如果可以做到合理的话。
  • ...

依赖关系

~170KB