我正在创建一个宏来对由空格分隔的数字列表执行include_bytes!
次操作:
1 2 3 4 5
如何在编译时创建包含u64
个这样的数字的片段?我try 转换为字符串,然后调用split(" ")
,但split
迭代了它,而不是const
.
我正在创建一个宏来对由空格分隔的数字列表执行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");
}