【发布时间】:2016-05-17 21:21:26
【问题描述】:
我有一个外部类型 (protobuf:::CodedInputStream),它期望引用一个被引用的 trait-object (TcpStream as &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 不在我的控制范围内,需要不同的解决方案(我相信)。
【问题讨论】:
-
[do] 不要尝试将这些项目放在同一个结构中 — 似乎这同样适用于您的情况?您尝试使用owning_ref 的结果是什么?
-
它实际上并没有说不要尝试。它说最简单和最推荐的解决方案是不要尝试....问题是它确实不适用于我的情况,因为我无法更改外部 API。这类似于“无法完成,因为这不是 rust 的工作方式”的答案,这很好,但它仍然不是同一个问题,因为我的问题仍然涉及外部 API。
-
OwningRef很接近,但我意识到(我在我的问题中错过了这一点)CodedInputStream 需要一个可变引用。 AFAIU,OwningRef 只能处理不可变的值? -
另一个问题中提出的解决方案需要重新设计 B,这样就不需要引用 A — 也许我的其他答案过于混乱了;我并不是建议您将外部类型分开。我建议您在上面的代码中拆分包含类型
Connection。 [我想创建]单个封装值——没错,当一个封装值引用另一个时,你不能这样做。这就是重复问题的全部意义所在。 -
FWIW,我对 protobuf 库了解不多,但
InputSource类型似乎不优雅。我本来希望InputSource成为您必须满足的特征,并且枚举中可能有用于 3 个事物的内置适配器。那将解决整个问题。其实someone else might agree that it should be changed,虽然那是输出,不是输入。