rust 连接字节数组而不分配

bzzcjhmw  于 2023-05-17  发布在  其他
关注(0)|答案(1)|浏览(148)

我想在一个字节片上附加一个“标记”字节,以确保在解析它时它以一个换行符结束。我觉得它应该是这样的:

fn parse(inp: &[u8]) {
    let workable_array = inp.basic_append(b'\n');
}

当一个字节被访问超过了原始输入的长度时,它将进入添加的字节。之后我将在纯只读上下文中使用新数组。
我知道切片上的concat方法,但这在内部分配了一个全新的向量,这似乎是不必要的代价。特别是当输入字符串可能非常大时。

yi0zb3m4

yi0zb3m41#

如果你要求一个操作接受一个&[u8]并返回另一个包含换行符字节的&[u8],而不重新分配,那么答案是这是不可能的。&[u8]always连续的内存,因此换行符字节必须物理上位于切片的末尾,这只能通过重新分配来实现。此外,使用&[u8]切片不可能做到这一点,因为它不支持mut
然而,你实际上可以用迭代器达到类似的效果。它不会分配,只是在所有其他字节产生后提供另一个换行符字节。

fn append_newline(data: impl Iterator<Item = u8>) -> impl Iterator<Item = u8> {
    data.chain(std::iter::once(b'\n'))
}

fn main() {
    let s = "Hello";
    let s_iter_with_newline = append_newline(s.bytes());
    for b in s_iter_with_newline {
        println!("{:?}", b as char);
    }
}
'H'
'e'
'l'
'l'
'o'
'\n'

当然,这与需要&[u8]作为参数的函数不兼容。
进一步说明:

  • 听起来你的输入有时包含换行符,有时不包含。从有换行符的行中去掉换行符要比把它加到没有换行符的行中容易得多。也许改变你的解析算法,这样它就要求输入不带换行符?
  • 这里使用的是&[u8],听起来像是字符串操作。请注意,Rust字符是而不是u8- Rust字符串是可变大小的UTF-8字符的列表。这就是&str/String类型存在的原因。使用它们来处理字符串,因为它们可以处理特殊字符,不像&[u8]。当然,您在这里遇到的'\n'问题仍然存在于str中,如果没有重新分配,它仍然是不可能的。

相关问题