我目前正在尝试将一个可变的切片/视图实现到支持安全地获取内存中消息遍历子切片的缓冲区中。一个最小的例子如下:
struct MutView<'s> {
data: &'s mut [u8]
}
impl<'s> MutView<'s> {
pub fn new(data: &'s mut [u8]) -> Self {
MutView { data }
}
pub fn subview<'a>(&'a mut self, start: usize, end: usize) -> MutView<'a> {
MutView::new(&mut self.data[start..end])
}
pub fn get<'a>(&'a mut self) -> &'a mut [u8] {
self.data
}
}
然而,这种设计存在一个问题,如果我在函数中本地创建了一个长度超过该函数作用域的
MutView<'s>
(例如 's = 'static),那么我就无法从函数返回子视图。类似下面的代码就会有问题:fn get_subview(data: &'s mut [u8]) -> MutView<'s> {
MutView::new(data).subview(0, 5)
}
由于
MutView::new(data)
是本地临时变量,因此会产生编译错误,显然由subview()
返回的MutView<'a>
不能从该函数返回。将
subview()
的签名更改为:pub fn subview<'a>(&'a mut self, start: usize, end: usize) -> MutView<'s> {
MutView::new(&mut self.data[start..end])
}
由于borrow checker抱怨返回的对象的生命周期必须长于 &'a mut self
,所以不可能。
我看到的问题是borrow checker被设置为处理subview()
返回由&'a mut self
拥有的数据的情况,而在这种情况下,我返回由某些底层缓存拥有并且比 lifetime 'a 更长的数据。因此出于安全原因,我仍然希望在返回子视图的lifetime期间进行&'a mut self
的可变借用,同时允许&'a mut self
在没有缩短子视图生命周期的情况下被丢弃。
我唯一看到的选项是添加一个消耗self的方法into_subview
和into_slice
。但是对于我的特定情况,我正在生成具有给定模式的消息读取get / set方法,这意味着我有针对消息体中每个字段的get / set方法,并且添加额外的into_*方法会导致大量额外的代码生成/编译,以及额外的使用复杂性。因此,如果可能的话,我想避免这种情况。
目前在Rust中有没有好的处理这种依赖关系的方法?
subview()
的正确签名应该是pub fn subview(&mut self, start: usize, end: usize) -> MutView<'s>
(因为它返回一个新的MutView
,它引用旧的数据)- 但是那个无法编译。我怀疑问题与使用生命周期不变的&mut
引用有关。修改后的代码 可以编译,使用共享引用。 - user4815162342