pub struct LineBuffer { /* private fields */ }Expand description
Accumulates raw stream bytes and yields complete newline-terminated lines.
Streaming responses arrive as arbitrary byte chunks: a single multi-byte
UTF-8 character (e.g. é, or an emoji) can be split across two chunks. The
naive buffer.push_str(&String::from_utf8_lossy(&chunk)) decodes each raw
chunk in isolation, so the leading bytes of a split character decode to
U+FFFD (the replacement character) and the trailing bytes decode to another
— permanently corrupting the text.
LineBuffer accumulates raw bytes and only decodes complete,
newline-terminated lines. A \n (0x0A) byte can never appear inside a
multi-byte UTF-8 sequence, so decoding a whole line is always safe even when
the underlying chunk boundary fell mid-character.
Consumed bytes are tracked with a cursor rather than drained per line: draining left-shifts every remaining byte, which turns a chunk carrying K lines into O(K·chunk) work. The buffer compacts once the consumed prefix grows past a threshold, so memory stays bounded over a long stream.
Implementations§
Source§impl LineBuffer
impl LineBuffer
Sourcepub fn next_line(&mut self) -> Option<String>
pub fn next_line(&mut self) -> Option<String>
Removes and returns the next complete line (trailing \n stripped),
or None when no complete line is buffered yet.
Sourcepub fn take_remaining(&mut self) -> Option<String>
pub fn take_remaining(&mut self) -> Option<String>
Drains and returns whatever bytes remain after the last complete line.
A stream can end without a trailing newline, leaving a final,
otherwise-complete record buffered that next_line will never yield.
Call this once at end-of-stream to recover it. Returns None when the
buffer is empty or the remainder is only whitespace.