背景
我是Rust的新手,我正在尝试写一个包解析器。它在一个没有堆的#[no_std]
环境中。
解析器的输入是对字节片的可变引用(&mut [u8]
),输出是包报头结构体的heapless::Vec
(实际上,每个结构体都只是一个结构体,带有对其片的引用和一些用于获取报头字段的函数)。
问题
我正在努力将最初提供的切片分割成单个包头所需的更小的切片。在函数中借用切片并使用slice.take_mut()
获取第一个切片似乎不会返回其余切片的权限,因此第二次调用该函数无法编译。
我还尝试了一个使用slice.split_at_mut()
的实现,也遇到了类似的问题。
我一直在努力理解生命以及它们如何融入这一切,这对我没有帮助。
示例
我试图将代码缩减为最小的示例,但这样做可能会遗漏一些重要的上下文。
#![feature(slice_take)]
fn main() {
let mut bytes: [u8; 30] = [
1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
];
let mut s1 = MyStruct::from_bytes(&mut bytes).unwrap();
let mut s2 = MyStruct::from_bytes(&mut bytes).unwrap();
println!("{:?}", s1);
println!("{:?}", s2);
println!("{:?}", bytes);
}
#[derive(Debug)]
struct MyStruct<'a> {
data: &'a mut [u8], // This should be a 10-byte slice.
}
impl<'a> MyStruct<'a> {
fn from_bytes(mut data: &'a mut [u8]) -> Result<MyStruct<'a>, &'static str> {
if data.len() < 10 {
return Err("Need 10 bytes.");
}
let struct_data = data.take_mut(..10).unwrap();
Ok(MyStruct{data: struct_data})
}
}
我期待的是:
MyStruct { data: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] }
MyStruct { data: [11, 12, 13, 14, 15, 16, 17, 18, 19, 20] }
[21, 22, 23, 24, 25, 26, 27, 28, 29, 30]
实际发生了什么:
error[E0499]: cannot borrow `bytes` as mutable more than once at a time
--> src\main.rs:10:39
|
9 | let mut s1 = MyStruct::from_bytes(&mut bytes).unwrap();
| ---------- first mutable borrow occurs here
10 | let mut s2 = MyStruct::from_bytes(&mut bytes).unwrap();
| ^^^^^^^^^^ second mutable borrow occurs here
11 | println!("{:?}", s1);
| -- first borrow later used here
2条答案
按热度按时间kb5ga3dv1#
你离这里很近,但你有两个问题。
第一个是
from_bytes
需要获取一个可变切片的可变引用,这允许它将调用者提供的切片设置为一个子区域。第二个是传入
&mut bytes
而不是slice --您需要传入一个slice的可变引用,以便from_bytes
可以调整该slice以指向一个子区域。解决这两个问题:
(Playground)
请注意,你可以在稳定的Rust上使用
split_at_mut
来实现这一点。这需要一些涉及std::mem::take()
的技巧--事实上,这正是take_mut
在后台实现的方式!(Playground)
vkc1a9a22#
我并不完全理解在no_std环境中的含义,但也许将不统一逻辑封装在另一个结构中会很有用。
playground