rust Deref关联类型的自身生存期

m1m5dgzv  于 2023-03-12  发布在  其他
关注(0)|答案(1)|浏览(110)

我想为从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>]>
}
ibrsph3r

ibrsph3r1#

你不能写你想写的东西,因为Deref的定义方式不允许这样做。在一些类型T上有一个Deref impl允许你从&'a T&'a T::Target,对于T的借用的 * 任何 * 生存期'a,并且T::Target类型总是独立于'a。(如果DerefTarget类型是 * 泛型关联类型 *,则这可以实现,但是它不是并且不能使之如此)。

*如果*一个BufArray总是一个Buf指针数组,指向借用的数据(你并不想让BufArray充当缓冲区的一个 * 拥有者 * 容器,这样可以让缓冲区无限期地保持活动),那么struct BufArray<'a>定义是这个问题的一个完美的解决方案。

如果你 * 确实 * 想要拥有一个所属类型,那么你就不应该这样使用lifetime,因为lifetime是无意义的BufArray::new()允许创建具有 * 任意 * 生存期'aBufArray<'a>,该生存期可能比BufArray及其Buf本身更长。
如果BufArray拥有Buf,并且Buf拥有自己的字节片(与使用常量的示例相反),那么这里要做的事情就是使所有类型都没有生命周期参数(就像Rust原生类型Vec<Vec<u8>>一样,它在结构上与您的类型类似,没有任何生命周期参数)。

相关问题