pub struct FrameDecoder { /* private fields */ }Expand description
Reassembles newline-delimited frames from arbitrarily chopped-up bytes.
Feed it whatever a read returned with push, then take
complete frames out with next_frame until it says
None, which means “not yet” rather than “nothing more”.
The cursor (buffered) matters for reading these two in
order. A caller that pushes without draining accumulates complete frames as
well as the partial one, and the buffer is then bounded by the limit plus the
chunk it was given — never by the peer’s frame size. The stdio adapter reads
a chunk, pushes it, and drains it before reading again.
§Examples
use protocol_droid::domain::{FrameDecoder, MaxFrameSize};
let mut decoder = FrameDecoder::new(MaxFrameSize::new(1024)?);
decoder.push(b"first\nsecond\n")?;
assert_eq!(decoder.next_frame()?, Some("first"));
assert_eq!(decoder.next_frame()?, Some("second"));
assert_eq!(decoder.next_frame()?, None);
assert!(decoder.is_empty());Implementations§
Source§impl FrameDecoder
impl FrameDecoder
Sourcepub const fn new(limit: MaxFrameSize) -> Self
pub const fn new(limit: MaxFrameSize) -> Self
A decoder that refuses frames larger than limit.
No default: see the module docs.
Sourcepub const fn limit(&self) -> MaxFrameSize
pub const fn limit(&self) -> MaxFrameSize
The limit this decoder was built with.
Sourcepub const fn buffered(&self) -> usize
pub const fn buffered(&self) -> usize
Bytes read and not yet handed out, including a partially-read frame.
Exposed so a caller — or a test — can see the decoder’s own footprint. It is bounded by the limit plus the size of the last chunk pushed, and is not a function of how large a frame the peer chose to send.
Sourcepub fn push(&mut self, bytes: &[u8]) -> Result<(), FramingError>
pub fn push(&mut self, bytes: &[u8]) -> Result<(), FramingError>
Adds bytes read from the peer.
The frame in progress may be split anywhere, including inside a multi-byte UTF-8 sequence — nothing here decodes until a frame is complete, so a character is never truncated by a read boundary.
§Errors
FramingError::FrameTooLarge when the bytes after the last terminator
would push the frame in progress past the limit. The check runs before
those bytes are buffered, so the decoder’s footprint is unaffected and
the decoder is left exactly as it was.
Sourcepub fn next_frame(&mut self) -> Result<Option<&str>, FramingError>
pub fn next_frame(&mut self) -> Result<Option<&str>, FramingError>
Takes the next complete frame, or None if the terminator has not
arrived.
The returned &str borrows the read buffer and is valid until the next
push or next_frame. A caller that needs to keep a frame past that
point copies it; the copy is then at the call site, where it is visible,
rather than hidden inside a type that allocates for everyone.
§Errors
FramingError::NotUtf8 when the frame’s bytes are not UTF-8. The
offending frame is dropped, so a caller that chooses to carry on reads
the next frame instead of being handed the same bad one for ever. A
transport will normally close on this error, because a peer that emits a
non-UTF-8 frame has said something about itself; the discard is here so
that a caller which decides to continue is not trapped in a loop.