Rust use BufMut with a buffered reader instance

52 Views Asked by At

I have a function whose signature is this:

pub fn handle_decode(buf: &mut bytes::BytesMut) -> anyhow::Result<DataType> {}

Which is to be shared between routines which handle different network transfer protocols. The reason I'm using the bytes package is because it nicely handles things like endianness and shallow copies. It's very nice for picking off bytes in the right order and "cloning" them cheaply.

With that being said, in the TCP routine I'm looking to use a BufReader<TcpStream> to combat the overhead of repeated syscalls to read() when picking data off the stream.

Is there any way to use a bytes::BufMut in conjunction with a buffered reader to get the best of both worlds?

Minimum example:

use anyhow::Context;
use std::io::BufReader;
use std::net::TcpListener;

fn bind_accept() -> anyhow::Result<()> {
    fn handle_decode(buf: &mut bytes::BytesMut) -> anyhow::Result<()> {
        unimplemented!()
    }

    let mut l = TcpListener::bind("1234")?;

    let (sock, _) = l.accept().context("should bind to provided port")?;

    let bufreader = BufReader::new(sock);
    let mut buf = bytes::BytesMut::with_capacity(1024);

    // This line will not work in this current state
    handle_decode(&mut bufreader)
}
1

There are 1 best solutions below

2
Stargateur On

BytesMut already buffer its content, there is no need for another buffer. You either use BytesMut or BufReader not both.

Using the trait BufMut you can use writer this will return you a wrapper that implement Write from std. Then you need to implement yourself what does BufReader of std, I didn't find anything that already do it for you. Or you could prefer use the BufMut trait instead of std trait directly.

use anyhow::Context;
use std::net::TcpListener;
use bytes::BytesMut;

fn bind_accept() -> anyhow::Result<()> {
    fn handle_decode(buf: &mut bytes::BytesMut) -> anyhow::Result<()> {
        unimplemented!()
    }

    let l = TcpListener::bind("1234")?;

    let (sock, _) = l.accept().context("should bind to provided port")?;

    let mut buf = BytesMut::with_capacity(1024);
    
    // read socket with BytesMut as buffer here

    handle_decode(&mut buf)
}