Is there a way to use a String::new() as a buffer for reading from a TcpStream ? I am using one as a buffer for writing, but i would like to be able to do the same for reading.
use std::net::TcpListener;
use std::io::{stdin, Read, Write};
use std::str;
pub fn socket_listen(addr: &String, port: &String) {
// bind to socket
let listner = TcpListener::bind(format!("{addr}:{port}")).unwrap();
for stream in listner.incoming() {
let mut stream = stream.unwrap();
loop {
// write
let mut write_buf = String::new();
stdin().read_line(&mut write_buf).unwrap();
stream.write(write_buf.as_bytes()).unwrap();
// read
let mut read_buf= [0u8; 1024]; // <- I want read_buf to be a String::new() like write_buf
let bytes_read = stream.read(&mut read_buf).unwrap();
let data = &read_buf[..bytes_read];
println!("{}", str::from_utf8(&data).unwrap());
}
}
}
When i have tried to do conversion acrobatics, i have gotten a lot of weird errors and i figured there must be a better way
// read
let mut read_buf = String::new();
let bytes_read =
stream.read(unsafe { read_buf.as_mut_vec() }).unwrap();
let data = &read_buf[..bytes_read];
println!("{}", &data);
It is unsafe because the bytes being read may not be valid utf-8. There may be a better way.
Do you want to allocate a buffer for every read as in your example, or will you be reusing a buffer?
This works without unsafe, whether reusing the read buffer or not:
for stream in listner.incoming() {
let mut stream = stream.unwrap();
let mut read_buf = Vec::new();
loop {
// write
let mut write_buf = String::new();
stdin().read_line(&mut write_buf).unwrap();
stream.write(write_buf.as_bytes()).unwrap();
// read
read_buf.truncate(0);
stream.read(&mut read_buf).unwrap();
let string = String::from_utf8(read_buf).unwrap();
println!("{}", string);
read_buf = string.into_bytes();
}
}
The conversions between String and Vec<u8> in both directions are simple moves, the data is not copied and there is no allocation.