#array-vec #array #vec #macro #literals #default-value

no-std array-lit

用于数组和 Vec 文字字面量的宏,具有超能力

2 个不稳定版本

0.2.0 2020年5月9日
0.1.0 2020年5月8日

#1984 in Rust 模式

Download history 5/week @ 2024-03-13 8/week @ 2024-03-27 6/week @ 2024-04-03 9/week @ 2024-05-22 64/week @ 2024-05-29 60/week @ 2024-06-05 54/week @ 2024-06-12 78/week @ 2024-06-19 64/week @ 2024-06-26

每月 270 次下载

MIT/Apache

16KB
153

array-lit

文档 · Crates.io · Lib.rs

Rust 宏,用于具有超能力的数组和 Vec 文字字面量。数组的宏名为 arr!Vec 的宏名为 vec!,它会覆盖标准库中的宏。

它们允许创建一个数组或 Vec,其中只指定了一些元素,其余设置为默认值。

以下宏指定了索引 0 上的三个连续值

let a = arr![0; 8; { [0]: [1, 2, 3] }];
assert_eq!(a, [1, 2, 3, 0, 0, 0, 0, 0]);

只有指定多个连续元素时才需要方括号

let a = arr![1; 8; { 6: 0 }];
assert_eq!(a, [1, 1, 1, 1, 1, 1, 0, 1]);

您可以根据需要指定任意数量的单个和连续值

let a = arr![0; 8; {
    6: 1,            // 1 at index 6
    [2]: [3, 4],     // 3 and 4 starting from index 2
    7: 5,            // 5 at index 7
}];
assert_eq!(a, [0, 0, 3, 4, 0, 0, 1, 5]);

支持熟悉的数组语法(arr![a; N]arr![a, b, c]),因此此存储库中的 vec! 宏是 std::vec! 的直接替代品。

它是如何工作的?

这些宏生成一个块,首先创建一个数组或 Vec,然后插入指定的值

arr![4; 10; { 0: 0, 1: 1 }]
// is expanded to
{
    let mut arr = [4; 10];  // in the vec! macro, std::vec! is used
    arr[0] = 0;
    arr[1] = 1;
    arr
}

如果插入的数组不是 [a, b, c, ..] 形式,则使用循环

arr![4; 10; { [1]: [2; 4] }]
// is expanded to
{
    let mut arr = [4; 10];
    let mut i = 1;
    let end = i + 4;
    while i < end {
        arr[i] = 2;
        i += 1;
    }
    arr
}

这甚至适用于在运行时创建的切片、数组和 Vec

let my_slice = &[1, 2, 3, 4];
arr![4; 10; { [1]: my_slice }];

数组的生命周期是什么?

在简单情况下,例如 arr![3; 5],数组字面量的生命周期被推断为 'static。这意味着它们与普通数组字面量的行为完全相同。

在其他情况下,不会推断 'static 生命周期。这意味着数组字面量是在运行时计算的,并且没有固定的内存位置。这也意味着以下

// does NOT compile!
fn return_temporary() -> &'static [i32; 4] {
    &arr![0; 4; { 0: 1 }]
}

会产生 error[E0515]: cannot return reference to temporary value。可以通过首先将字面量赋值给 conststatic 变量来解决此问题

fn return_temporary() -> &'static [i32; 4] {
    static ARR: &[i32; 4] = &arr![0; 4; { 0: 1 }];
    ARR
}

分配给 staticconst 变量的值必须是常量。由于编译器的限制,不允许在宏中展开为循环

// does NOT compile!

const ARR: [i32; 4] = arr![0; 16; { [0]: [1; 8] }];
// this is expanded to a loop ~~~~~~~~~~~^^^^^^

请注意,const 强制执行 const evaluation,这意味着整个数组都被包含在应用程序的二进制文件中。如果数组很大,这可能不是期望的行为。

用法

使用以下命令导入宏

use array_lit::{arr, vec};

如果您不想覆盖 std::vec!,则可以重命名宏

use array_lit::{arr, vec as vector};

也支持全局导入宏,尽管不推荐这样做

#[macro_use]
extern crate array_lit;

自定义索引

如果您想在这些宏中使用自己的 Index/IndexMut 实现,您可能需要额外的括号对

#[derive(Copy, Clone)]
struct S(bool);

/// Your custom index
struct Idx(usize);

impl std::ops::Index<Idx> for Vec<S> {
    type Output = bool;
    // etc.
}

impl std::ops::IndexMut<Idx> for Vec<S> {
    // etc.
}

vec![S(true); 1000; { (Idx(16)): false }];
// parens needed ~~~~~^~~~~~~~^

no_std 支持

如果禁用了默认功能,则此库支持 no_std。这使得 vec! 宏不可用。

最低要求的 Rust 版本

需要 Rust 1.33。

许可证

根据您的选择,许可协议为 MITApache 2.0

无运行时依赖

功能