如何在数据结构中使用 BufReader 和 BufWriter 存储 TcpStream

ube*_*ben 10 rust

我想要a和 aTcpStream共享,我找到了一个解决方案:如果 BufReader 拥有流的所有权,我如何在其上读取和写入行?BufReaderBufWriter

现在我希望它有自己的数据结构,但我只得到了部分答案:
为什么我不能在同一结构中存储一个值和对该值的引用?

期望的实现违反了所有权规则。

use std::io::{BufReader, BufWriter};
use std::net::TcpStream;

pub struct BufTcpStream<'a> {
    _socket: TcpStream,
    input:  BufReader<&'a TcpStream>;
    output: BufWriter<&'a TcpStream>;
}

impl<'a> BufTcpStream<'a> {
    pub fn new(socket: TcpStream) -> Self {
        Self{
            input : BufReader::new(&socket),
            output: BufWriter::new(&socket),
            _socket: socket,//                 <-- MOVE OF BORROWED VALUE HERE
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

为了解决这个问题,我必须确保TcpStream引用在整个结构生命周期内保持有效,我使用了 aPin<Box<TcpStream>>来确保它。

但编译器仍然抱怨借用值的移动socket。为了消除这个障碍,我使用了std::meme::transmute().

现在,我想知道的是:

这个实现安全吗?

use std::io::{BufReader, BufWriter};
use std::net::TcpStream;
use std::pin::Pin;

pub struct BufTcpStream<'a> {
    _socket: Pin<Box<TcpStream>>,
    input : BufReader<&'a TcpStream>,
    output: BufWriter<&'a TcpStream>,
}

impl<'a> BufTcpStream<'a> {
    pub fn new(socket: TcpStream) -> Self {
        let pin = Box::pin(socket);
        unsafe {
            Self{
                input : BufReader::new(std::mem::transmute(&*pin)),
                output: BufWriter::new(std::mem::transmute(&*pin)),
                _socket: pin,
            }
        }
    }
    pub fn reach(&mut self) -> (
        &mut BufReader<&'a TcpStream>,
        &mut BufWriter<&'a TcpStream>
    ) {
        (&mut self.input, &mut self.output)
    }
}
Run Code Online (Sandbox Code Playgroud)

She*_*ter 12

用于TcpStream::try_clone获取第二个流:

返回的TcpStream是对该对象引用的同一流的引用。两个句柄将读取和写入相同的数据流,并且在一个流上设置的选项将传播到另一个流。

然后,您可以将一个包装在读取器中,将一个包装在写入器中:

use std::{
    io::{self, BufReader, BufWriter},
    net::TcpStream,
};

struct BufTcpStream {
    input: BufReader<TcpStream>,
    output: BufWriter<TcpStream>,
}

impl BufTcpStream {
    fn new(stream: TcpStream) -> io::Result<Self> {
        let input = BufReader::new(stream.try_clone()?);
        let output = BufWriter::new(stream);

        Ok(Self { input, output })
    }
}
Run Code Online (Sandbox Code Playgroud)

也可以看看: