pub struct PacketReader { /* private fields */ }Implementations§
Source§impl PacketReader
impl PacketReader
pub fn new(max_packet_size: usize, padding: usize) -> Self
Sourcepub fn push_data(&mut self, data: &[u8]) -> Result<(), PushDataError>
pub fn push_data(&mut self, data: &[u8]) -> Result<(), PushDataError>
Push data to the reader’s internal buffer.
get_packet() should be called to extract packets.
Sourcepub fn spare_capacity_mut(&mut self) -> &mut [u8] ⓘ
pub fn spare_capacity_mut(&mut self) -> &mut [u8] ⓘ
Borrow the unused tail of the internal buffer to fill in place.
This is the zero-copy counterpart to push_data: instead of reading into a scratch buffer
and copying that in, a transport can write straight into the reassembly buffer and mark the
bytes received with commit. That removes one copy of every received byte on the hot
receive path.
Space freed by already-consumed packets is reclaimed here (at most one compaction per
refill), so the returned slice is empty only when unconsumed data fills the whole buffer. A
caller that drains to NeedData before each read never sees that: a mid-packet reader
holds fewer than size_of::<u32>() + max_packet_size bytes, less than the buffer’s capacity
even with padding == 0. The slice is therefore never empty, so a read into it cannot
return Ok(0) and be mistaken for end-of-stream. padding only trades memory for fewer,
larger reads.
§Example
use std::io::Read;
use fcast_protocol::{PacketReader, ReadResult};
// A transport carrying one framed packet: length prefix 3, body [1, 2, 3].
let mut stream: &[u8] = &[3, 0, 0, 0, 1, 2, 3];
let mut reader = PacketReader::new(1024, 0);
let n = stream.read(reader.spare_capacity_mut())?;
reader.commit(n);
assert_eq!(reader.get_packet(), ReadResult::Read(&[1, 2, 3]));
assert_eq!(reader.get_packet(), ReadResult::NeedData);Sourcepub fn commit(&mut self, n: usize)
pub fn commit(&mut self, n: usize)
Mark n bytes written into the slice returned by spare_capacity_mut as
received.
n must not exceed the length of that slice (a transport must never report having read more
bytes than the slice could hold). In debug builds this is asserted; in release builds an
out-of-range n corrupts the reader’s length bookkeeping, so it is a caller bug rather than
defined behaviour.
Sourcepub fn get_packet(&mut self) -> ReadResult<'_>
pub fn get_packet(&mut self) -> ReadResult<'_>
Get a packet if it’s available.
This should be called in a loop until None is returned which means more data is needed.
Sourcepub fn drain_unparsed(&mut self) -> Vec<u8> ⓘ
pub fn drain_unparsed(&mut self) -> Vec<u8> ⓘ
Take all buffered bytes that are not part of an already-returned packet and reset the reader.
This is used when the underlying connection is handed to another protocol layer (e.g. a TLS
upgrade after the plaintext Version exchange): a single read may have pulled in bytes
belonging to that next layer, and those must be replayed there instead of being lost.