我一直致力于使图书馆(rust-websocket
)使用更多借阅和更少拥有的数据。这涉及向结构添加Cow
,其中包括为该结构添加生命周期,这使得整个库需要生命周期。
总之,我还有一个问题,而且我已经试图解决它好几天了。可以使用以下代码进行总结:
{ // This works great!
let mut sender = Wire;
let message = Text("Hello World!".to_string());
sender.send_message(&message);
}
{ // This DOES NOT COMPILE!
let mut client = Client {
sender: Wire,
packet: PhantomData,
};
let message = Text("Hello World!".to_string());
client.send(&message);
}
在上面的示例中,client.send
是sender.send_message
的包装器,两者具有相同的定义。虽然在client.send
的情况下,发送的邮件必须比客户端更长。在sender.send_message
情况下,消息只需要在函数调用的生命周期内存活。
use std::borrow::Cow;
use std::iter::{Take, Repeat, repeat};
use std::marker::PhantomData;
trait Sender<P> {
fn send_packet(&mut self, packet: &P) -> Result<(), ()>;
fn send_message<'m, M>(&mut self, message: &'m M) -> Result<(), ()>
where M: Message<'m, P>,
P: 'm
{
for ref packet in message.iter() {
try!( self.send_packet(packet) );
}
Ok(())
}
}
trait Message<'p, P>
where P: 'p
{
type PacketIterator: Iterator<Item = P>;
fn iter(&'p self) -> Self::PacketIterator;
}
#[derive(Clone, Debug)]
struct Packet<'d> {
data: Cow<'d, [u8]>,
}
struct Text(String);
impl<'p> Message<'p, Packet<'p>> for Text {
type PacketIterator = Take<Repeat<Packet<'p>>>;
fn iter(&'p self) -> Take<Repeat<Packet<'p>>> {
repeat(Packet {
data: Cow::Borrowed(self.0.as_bytes()),
}).take(1)
}
}
struct Wire;
impl<'s> Sender<Packet<'s>> for Wire {
fn send_packet<'p>(&mut self, packet: &Packet<'p>) -> Result<(), ()> {
println!("Sent {:?}", packet);
Ok(())
}
}
struct Client<P, S> {
sender: S,
packet: PhantomData<P>
}
impl<P, S> Client<P, S>
where S: Sender<P>
{
fn send<'m, M>(&mut self, message: &'m M) -> Result<(), ()>
where M: Message<'m, P>,
P: 'm
{
self.sender.send_message(message)
}
}
fn main() {
{ // This works great!
let mut sender = Wire;
let message = Text("Hello World!".to_string());
sender.send_message(&message);
}
{ // This DOES NOT COMPILE!
let mut client = Client {
sender: Wire,
packet: PhantomData,
};
let message = Text("Hello World!".to_string());
client.send(&message);
}
}
我把整个code on the Rust Playground
我希望我能更好地描述我的问题,以便更好地搜索,所以一旦我知道发生了什么,我就会改变我的头衔。
答案 0 :(得分:3)
将PhantomData<P>
更改为PhantomData<fn(P)>
。您的类型不会存储P
,而是会在P
上运行。
此处的问题是您声称存储 P
,这意味着类型P
必须比类型Client<S, P>
更长。要使P
(数据包类型)比Client
类型更长,message
本身必须比client
更长,因为您要从邮件中借用数据包。但是,在这种情况下,client
比message
更长,因为client
首先在堆栈上分配(堆栈以相反的顺序拆除)。