Переменная не живет достаточно долго для отправки по каналу - PullRequest
0 голосов
/ 13 сентября 2018

Я пытаюсь отправить сообщение, содержащее Cow<[u8]>, по каналу. Однако правила жизни не позволяют мне пройти мимо.

use std::borrow::Cow;
use std::sync::mpsc;

#[derive(Debug, Default, PartialEq, Clone)]
pub struct PlayerAction<'a> {
    pub data: Cow<'a, [u8]>,
}

#[derive(Debug, Clone)]
pub enum NetworkMessage<'a> {
    PlayerActionMessage(PlayerAction<'a>),
}

pub struct ConnectionsManager<'a> {
    channel: mpsc::Sender<NetworkMessage<'a>>,
}

pub struct MessageHandler<'a> {
    pub connection_manager: ConnectionsManager<'a>,
}

fn read_message<'a>(bytes: &'a Vec<u8>) -> NetworkMessage {
    NetworkMessage::PlayerActionMessage(PlayerAction {
        data: Cow::Borrowed(&bytes),
    })
}

impl<'a> MessageHandler<'a> {
    fn on_message(&mut self, msg: Vec<u8>) {
        let readm = read_message(&msg);
        self.connection_manager.channel.send(readm);
    }
}

fn main() {}

Детская площадка

error[E0597]: `msg` does not live long enough
  --> src/main.rs:30:35
   |
30 |         let readm = read_message(&msg);
   |                                   ^^^ borrowed value does not live long enough
31 |         self.connection_manager.channel.send(readm);
32 |     }
   |     - borrowed value only lives until here
   |
note: borrowed value must be valid for the lifetime 'a as defined on the impl at 28:1...
  --> src/main.rs:28:1
   |
28 | impl<'a> MessageHandler<'a> {
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^

MessageHandler переживает Vec<u8>, но я понятия не имею, как его пройти другим путем.

Есть ли способ передать Vec<u8>, чтобы он мог жить дольше, чем функция on_message?

1 Ответ

0 голосов
/ 13 сентября 2018

Вот однострочное изменение, которое вы можете сделать, чтобы этот код был корректным:

fn on_message(&mut self, msg: &'a [u8])

Вместо того, чтобы принимать Vec<u8> по значению, возьмите ссылку на фрагмент, который уже гарантированно будет жить припо крайней мере, пока 'a.Это означает, что вызывающий абонент несет ответственность за то, чтобы все, что вы передадите на on_message, проживало достаточно долго для отправки по каналу.


Но, возможно, вы не сможете этого сделать,Либо у вызывающей стороны возникнет та же проблема, и вы не сможете ее поднять дальше, либо Vec<u8> является обязательной частью подписи on_message.Если это так, вам придется изменить read_message.Вот одна из возможностей:

fn read_message<'b>(bytes: Vec<u8>) -> NetworkMessage<'b> {
    NetworkMessage::PlayerActionMessage(PlayerAction {
        data: Cow::Owned(bytes),
    })
}

impl<'a> MessageHandler<'a> {
    fn on_message(&mut self, msg: Vec<u8>) {
        let readm = read_message(msg);
        self.connection_manager.channel.send(readm);
    }
}

Перемещение msg в read_message оставляет компилятору свободу выбора любого времени жизни, которое он хочет за 'bon_message он может просто выбрать 'a для компиляции кода.Недостаток этого подхода заключается в том, что вам может потребоваться .clone() Vec, если вам потребуется использовать его снова после отправки по каналу.

...