我想为从FFI构造的缓冲区结构体数组实现Deref
。
但是,我不清楚如何用Self
来注解Deref
关联类型的生存期。
不管deref
方法的生存期省略规则如何,它不应该是安全的吗?
use std::ops::Deref;
use std::marker::PhantomData;
const FOO : &[u8] = b"foo";
const BAR : &[u8] = b"bar";
#[repr(C)]
struct Buf<'a> {
ptr: *const u8,
len: usize,
_mark: PhantomData<&'a [u8]>
}
impl<'a> From<&'a [u8]> for Buf<'a> {
fn from(b: &[u8]) -> Self {
Self{ ptr: b.as_ptr(), len: b.len(), _mark: PhantomData }
}
}
struct BufArray {
array: *const u8,
count: usize,
}
impl BufArray {
fn new() -> Self {
// Assume this array is constructed from FFI, fake one for brevity:
let v : Vec<Buf> = vec![FOO.into(), BAR.into()];
let v = std::mem::ManuallyDrop::new(v);
Self { array: v.as_ptr().cast(), count: v.len() }
}
}
impl Deref for BufArray {
type Target = [Buf<'_>]; // what to do here??
fn deref(&self) -> &Self::Target {
unsafe { std::slice::from_raw_parts(self.array.cast(), self.count) }
}
}
如果我这样注解BufArray
,它就可以工作,但我不确定这是不是正确的方法。
struct BufArray<'a> {
array: *const u8,
count: usize,
_mark: PhantomData<[Buf<'a>]>
}
1条答案
按热度按时间ibrsph3r1#
你不能写你想写的东西,因为
Deref
的定义方式不允许这样做。在一些类型T
上有一个Deref
impl允许你从&'a T
到&'a T::Target
,对于T
的借用的 * 任何 * 生存期'a
,并且T::Target
类型总是独立于'a
。(如果Deref
的Target
类型是 * 泛型关联类型 *,则这可以实现,但是它不是并且不能使之如此)。*如果*一个
BufArray
总是一个Buf
指针数组,指向借用的数据(你并不想让BufArray
充当缓冲区的一个 * 拥有者 * 容器,这样可以让缓冲区无限期地保持活动),那么struct BufArray<'a>
定义是这个问题的一个完美的解决方案。如果你 * 确实 * 想要拥有一个所属类型,那么你就不应该这样使用lifetime,因为lifetime是无意义的:
BufArray::new()
允许创建具有 * 任意 * 生存期'a
的BufArray<'a>
,该生存期可能比BufArray
及其Buf
本身更长。如果
BufArray
拥有Buf
,并且Buf
拥有自己的字节片(与使用常量的示例相反),那么这里要做的事情就是使所有类型都没有生命周期参数(就像Rust原生类型Vec<Vec<u8>>
一样,它在结构上与您的类型类似,没有任何生命周期参数)。