I wanted a TcpStream
shared by both a BufReader
and a BufWriter
, I found a solution in:
If BufReader takes ownership of a stream, how can I read and write lines on it?
Now I want it in its own data structure, but I only got a partial answer from:
Why can't I store a value and a reference to that value in the same struct?
The desired implementation is violating ownership rules.
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
}
}
}
To solve this problem, I had to ensure the TcpStream
references will stay valid during all the structure lifetime, I used a Pin<Box<TcpStream>>
to ensure it.
But the compiler still complain about the move of the borrowed value socket
. To remove this barrier I used std::meme::transmute()
.
Now, what i want to know is:
Is this implementation safe?
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)
}
}