我正在创建一个宏来对由空格分隔的数字列表执行include_bytes!次操作:

1 2 3 4 5

如何在编译时创建包含u64个这样的数字的片段?我try 转换为字符串,然后调用split(" "),但split迭代了它,而不是const.

推荐答案

users.rust-lang论坛的答案提供了一个可行的解决方案:(playground)

const fn to_u64(bytes: &[u8], start: usize, end: usize) -> u64 {
    let mut res: u64 = 0;
    let mut i = start;

    while i < end {
        res = 10 * res + (bytes[i] - b'0') as u64;

        i += 1;
    }

    res
}

const fn split_parse<const LEN: usize>(bytes: &[u8]) -> [u64; LEN] {
    let mut res = [0; LEN];

    let mut idx_start = 0;
    let mut idx_curr = 0;
    let mut i = 0;

    while i < LEN {
        while idx_curr < bytes.len() && bytes[idx_curr] != b' ' {
            idx_curr += 1;
        }
        res[i] = to_u64(bytes, idx_start, idx_curr);
        idx_curr += 1;
        idx_start = idx_curr;
        i += 1;
    }

    res
}

const fn split_len(bytes: &[u8]) -> usize {
    let mut len = 1;
    let mut i = 0;
    while i < bytes.len() {
        if bytes[i] == b' ' {
            len += 1;
        }
        i += 1;
    }
    len
}

const DATA: &[u8] = b"1 2 3 4 5";
// In the actual use case, you'd use include_bytes here
// const DATA: &[u8] = include_bytes!("numbers.txt");
const DATA_LEN: usize = split_len(DATA);
static DATA_INTS: [u64; DATA_LEN] = split_parse(DATA);

fn main() {
    println!("{:?}", DATA_INTS);
}

此解决方案使用常量函数而不是宏.它假定输入有效,但如果要验证输入,则可以使用panic.例如,在to_u64中,您可以判断字符是否为数字:

if b'0' > bytes[i] || b'9' < bytes[i] {
    panic!("Not an integer");
}

Rust相关问答推荐

为什么我的梅森素数代码的指数越大,速度就越快?

是否有可能同时避免不兼容的不透明类型和代码重复?

修改切片/引用数组

为什么std repeat trait绑定在impl块和关联函数之间?

无法将记录器向下转换回原始 struct

Rust类似功能是C++命名空间吗?

是否可以使用Rust宏来构建元组的项?

Trait bound i8:来自u8的不满意

在Rust中声明和定义一个 struct 体有什么区别

Windows 上 ndarray-linalg 与 mkl-stats 的链接时间错误

如何将 struct 数组放置在另一个 struct 的末尾而不进行内存分段

Nom 解析器无法消耗无效输入

Option<&T> 如何实现复制

如何获取模块树?

实现泛型的 Trait 方法中的文字

从 Rust 中的 if/else 中的引用创建 MappedRwLockWriteGuard

为什么我不能克隆可克隆构造函数的Vec?

将数据序列化为 struct 模型,其中两个字段的数据是根据 struct 中的其他字段计算的

传递 Option<&mut T> 时何时需要 mut

在传输不可复制的值时实现就地枚举修改