我有一个外部类型(protobuf:::CodedInputStream
),它需要引用引用的特征对象(TcpStream
为&mut Read
)。
我想创建一个类型或函数Connection
将TcpStream
(取得所有权)与CodedInputStream
一起包装,以便使用它的功能,封装使用和所有权TcpStream作为内部细节。
然而,我无法弄清楚如何。我天真的尝试(伪生锈)
struct Connection {
stream: TcpStream,
coded_stream: CodedInputStream,
}
fn new_connection(s: TcpStream) -> Connection {
Connection {
stream: s,
// Invalid, `s` has been transferred to `stream` above
coded_stream: CodedInputStream::new(&mut s),
// Invalid, `stream` is an unresolved symbol here
coded_stream: CodedInputStream::new(&mut stream),
// Omitting and mutating fails, since `coded_stream`
// must have a value and there is no "0"-value.
}
}
我错过了一些明显的东西吗?这在Rust中通常是个坏主意吗?是否有其他一些模式来处理取得所有权和封装长寿对象?
在Why can't I store a value and a reference to that value in the same struct?中,有一个类似的问题涉及如何重构内部类型以解决问题。在这里,CodedInputStream
不受我的控制,需要一个不同的解决方案(我相信)。
答案 0 :(得分:1)
您不能执行此操作,因为在Rust的所有权规则下这并不安全。
这是一个自我引用的结构。自我引用结构存在两个问题:
所有拥有的类型都可以随时移动到另一个内存地址,并且通过设计始终像memcpy
一样简单,没有任何魔术。在您的情况下,这意味着一旦您返回Connection
,stream
的地址就会更改,并且coded_stream
中的引用将变得悬而未决。
借位检查器允许结构域被单独覆盖/替换。在您的情况下,这意味着它将允许stream
被新的覆盖,而coded_stream
会留下未使用的错误。
因此常规的借阅检查规则无法表达同时拥有和借用的两个字段之间的特殊关系。
有rental
条板箱可为这种情况提供一些解决方法。