How does BufReader's .lines() function work when the capacity of the buffer is less than that of the line?

In the following code example, my buffer size is just 3 bytes, whereas each line on my TCP stream will be more than that. How does Buffer Reader handle this and give me the correct results?

pub fn serve(self) -> () {
    env_logger::builder().filter_level(log::LevelFilter::Trace).init();

    let tcp_listener = TcpListener::bind(&self.host)
        .inspect_err(|err| self.handle_error(err))
        .unwrap();

    for connection_stream in tcp_listener.incoming() {
        self.handle_connection(connection_stream);
    }
}


fn handle_connection(&self, connection_stream: Result<TcpStream, std::io::Error>) {
    info!("{} is connected.", connection_stream.as_ref().unwrap().peer_addr().unwrap());

    if connection_stream.is_err() {
        self.handle_error(&connection_stream.err().unwrap());
        return ();
    }

    let reader: BufReader<TcpStream> = BufReader::with_capacity(3, connection_stream.unwrap());
    let lines: Vec<_> = reader // -> BufReader<TcpStream>
        .lines() // -> Lines<BufReader<TcpStream>>
        .map(|result: Result<String, std::io::Error>| result.unwrap()) // -> impl Iterator<Item = String>
        .take_while(|line| !line.is_empty()) // -> impl Iterator<Item = String>
        .collect();

    info!("Lines: {lines:#?}");
    }

Output: (for lines)

"GET / HTTP/1.1",
"Host: localhost:9999"
.....

The BufReader's internal buffer grows to fit the next line. Note that your buffer's size is not three, just its initial capacity. If you read something bigger, the buffer grows, increasing its capacity.

2 Likes

Got it. Thank you!

1 Like