Rust 在包装函数中从结构借用内部数据

Rust 在包装函数中从结构借用内部数据,rust,Rust,我一直在努力使一个库(rust websocket)使用更多的借阅和更少的拥有数据。这涉及到向结构添加一个Cow,这涉及到向该结构添加一个生存期,这使得整个库需要生存期 简而言之,我还有一个问题,我已经努力解决了好几天了。可以用以下代码进行总结: { // This works great! let mut sender = Wire; let message = Text("Hello World!".to_string()); sender.send_messag

我一直在努力使一个库(
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\u 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);
    }
}
使用std::borrow::Cow;
使用std::iter::{Take,Repeat,Repeat};
使用std::marker::PhantomData;
特质发送者

{ fn发送_数据包(&mut self,数据包:&P)->结果; fn发送消息结果 其中M:Message{ 数据:Cow消息>用于文本{ 键入PacketIterator=Take-Take-Sender(&mut-self,packet:&packet(&mut-self,message:&m)->结果


其中M:Message将
PhantomData
更改为
PhantomData
。您的类型不存储
p
,它在
p
上运行


这里的问题是,您声称要存储一个
p
,这意味着类型
p
必须比类型
客户端
更有效。对于
p
(数据包类型)要使
客户机
类型的生存时间更长,
消息
本身必须比
客户机
的生存时间更长,因为您从消息中借用数据包。但是,在这种情况下,
客户机
消息
的生存时间更长,因为
客户机
是在堆栈上首先分配的(堆栈按相反的顺序拆下).

你肯定是对的,但这是我不想要的行为,我应该更清楚。因为你指出的生命周期限制,所有消息都必须在创建客户端之前提前发出!我想要这些生命周期(客户端和消息)分开。有点离题,但我强烈建议您遵循where子句的Rust标准格式。我在扫描代码以查看泛型如何使用时遇到很多问题。我个人更喜欢总是使用where子句,而不是像
那样内联它。我也更喜欢
where
(一生除外)。很高兴知道有一种标准样式,我很乐意遵循它。@Shepmaster改变了样式。