Skip to main content

PacketReader

Struct PacketReader 

Source
pub struct PacketReader { /* private fields */ }

Implementations§

Source§

impl PacketReader

Source

pub fn new(max_packet_size: usize, padding: usize) -> Self

Source

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.

Source

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);
Source

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.

Source

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.

Source

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.

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.