buffer.rs
Overview
This file provides buffer management for stream data transmission and reception within a networking context. It defines two primary buffer abstractions:
StreamRecvBuffer: A read-only buffer for receiving data from a stream. It supports operations for iterating over multiple underlying buffers, tracking read progress, and signaling the end of stream (FIN).WriteBuffer: A write buffer abstraction supporting zero-copy writes and internal buffering, designed for efficient data preparation before transmission.
Both buffers interact closely with the stream layer, particularly the StreamInstance type, to manage data flow and lifecycle events.
Types and Structures
StreamRecvBuffer
A buffer for receiving data from a stream. It implements the [bytes::Buf] trait to provide read operations over a collection of buffers (msquic::ffi::QUIC_BUFFER). It tracks offsets and read cursors to efficiently handle partial consumption of buffers.
Fields
stream: Option<Arc<StreamInstance>>
Optional reference to the associated stream, used to notify when reading is complete.buffers: Vec<msquic::ffi::QUIC_BUFFER>
Underlying data buffers received from the stream.offset: usize
Stream offset representing the starting position of this buffer's data.len: usize
Total length of data across all buffers in this instance.read_cursor: usize
Index of the current buffer being read.read_cursor_in_buffer: usize
Offset within the current buffer indicating the read position.fin: bool
Flag indicating if this buffer contains the end of the stream.
Methods
new
pub(crate) fn new<T: AsRef<[msquic::BufferRef]> + ?Sized>(offset: usize, buffers: &T, fin: bool) -> Self
Creates a new StreamRecvBuffer from a list of msquic::BufferRef buffers.
Parameters:
offset: Starting offset in the stream for these buffers.buffers: Reference to a list of buffer references wrappingQUIC_BUFFERs.fin: Indicates whether this buffer marks the end of the stream.
Returns:
A newStreamRecvBufferinstance.Usage Example:
let recv_buffer = StreamRecvBuffer::new(stream_offset, &buffers, is_fin);
set_stream
pub(crate) fn set_stream(&mut self, stream: Arc<StreamInstance>)
Associates this buffer with a specific StreamInstance.
Parameters:
stream: Shared reference-counted pointer to aStreamInstance.
Usage:
Typically called after creation to link the buffer back to its stream for lifecycle notifications.
len
pub fn len(&self) -> usize
Returns the number of unread bytes remaining in the buffer.
Returns:
Number of bytes not yet consumed.
is_empty
pub fn is_empty(&self) -> bool
Indicates whether the buffer has no remaining unread data.
as_slice_upto_size
pub fn as_slice_upto_size(&self, size: usize) -> &[u8]
Provides a read-only byte slice of at most size bytes from the current read position in the buffer.
Parameters:
size: Maximum size of the slice to return.
Returns:
A byte slice referencing the underlying buffer data without advancing the read cursor.
get_bytes_upto_size
pub fn get_bytes_upto_size<'a>(&mut self, size: usize) -> Option<&'a [u8]>
Consumes and returns a slice of up to size bytes from the current read position, advancing the read cursor accordingly.
Parameters:
size: Maximum number of bytes to consume.
Returns:
An optional byte slice if there is data available; otherwise,None.
offset
pub fn offset(&self) -> usize
Returns the starting offset of this buffer's data in the stream.
range
pub fn range(&self) -> Range<usize>
Returns the byte range in the stream covered by this buffer: [offset, offset + len).
fin
pub fn fin(&self) -> bool
Indicates whether this buffer marks the end of the stream.
Trait Implementations for StreamRecvBuffer
Buf Trait
Implements [bytes::Buf] for StreamRecvBuffer to allow iterator-style consumption of buffer data.
advance(&mut self, count: usize)
Advances the read cursor bycountbytes, moving across buffers as necessary.chunk(&self) -> &[u8]
Returns the current contiguous slice of unread bytes.remaining(&self) -> usize
Returns the count of unread bytes remaining.chunks_vectored<'a>(&'a self, dst: &mut [IoSlice<'a>]) -> usize
Populates the providedIoSlicearray with slices referencing the unread buffers, enabling vectored I/O.
Drop Implementation for StreamRecvBuffer
When a StreamRecvBuffer instance is dropped, it notifies the associated StreamInstance (if any) that the read operation is complete by calling stream.read_complete(self). This lifecycle hook allows the stream to manage buffer recycling or other cleanup operations.
WriteBuffer
An abstraction for preparing data to be written to a stream, supporting zero-copy slices and internally owned byte vectors.
Structure
WriteBufferis a wrapper around a boxedWriteBufferInnerstruct.WriteBufferInnercontains:internal: Vec<u8>: Internal byte vector for owned data.zerocopy: Vec<Bytes>: Collection of zero-copy buffers (Bytes) that can be sent without copying.buffers: Vec<msquic::BufferRef>: Buffers prepared for interfacing with the underlying QUIC API.
Methods
new
pub(crate) fn new() -> Self
Creates a new, empty WriteBuffer.
from_raw
pub(crate) unsafe fn from_raw(inner: *const c_void) -> Self
Creates a WriteBuffer from a raw pointer, used for interoperation with FFI or external buffer management.
put_zerocopy
pub(crate) fn put_zerocopy(&mut self, buf: &Bytes) -> usize
Appends a zero-copy buffer (Bytes) to the WriteBuffer.
Parameters:
buf: A zero-copy byte buffer to add.
Returns:
The length of the appended buffer.
put_slice
pub(crate) fn put_slice(&mut self, slice: &[u8]) -> usize
Appends a slice of bytes to the internal owned buffer.
Parameters:
slice: Byte slice to append.
Returns:
Length of the appended data.
get_buffers
pub(crate) fn get_buffers(&mut self) -> (*const msquic::BufferRef, usize)
Prepares and returns a pointer and count of buffers suitable for sending via the underlying QUIC transport.
If zero-copy buffers exist, converts them into
msquic::BufferRefwrappers.Otherwise, wraps the internal owned buffer.
Returns:
Tuple of pointer to the array ofBufferRefs and the count.
into_raw
pub(crate) fn into_raw(self) -> *mut c_void
Consumes the WriteBuffer and returns a raw pointer for FFI usage.
reset
pub(crate) fn reset(&mut self)
Clears all internal buffers, preparing this instance for reuse.
Important Implementation Details
StreamRecvBuffermanages multiple underlyingQUIC_BUFFERs and tracks the current read position with two cursors:read_cursorfor the buffer index.read_cursor_in_bufferfor the byte offset within the current buffer.
Safety is ensured using
unsafeblocks for creating slices from raw pointers (slice::from_raw_parts), relying on guarantees from the QUIC API about buffer validity and lifetime during usage.WriteBuffersupports zero-copy operations by holding references toBytesbuffers, which avoids unnecessary data copying when sending data.Both buffer types implement
SyncandSendmanually to guarantee thread-safety due to their internal usage of raw pointers and synchronization primitives.Dropimplementation inStreamRecvBuffercalls back to the stream to signal the completion of read operations, integrating with the stream lifecycle management.
Interaction with Other System Components
StreamRecvBufferinteracts directly withStreamInstance(referenced viaArc<StreamInstance>) to report when reading is complete (read_completemethod).Both buffer types wrap or convert to/from
msquic::ffi::QUIC_BUFFERandmsquic::BufferRef, which are FFI bindings to the underlying QUIC transport buffers.WriteBufferis part of the asynchronous buffer handling in the msquic subsystem (crate::msquic::msquic_async::buffer), preparing data for transmission.The buffers serve as intermediaries between raw network data and higher-level stream processing layers, facilitating efficient data movement and memory management.
Mermaid Diagram: Structure of buffer.rs
classDiagram
class StreamRecvBuffer {
-stream: Option<Arc<StreamInstance>>
-buffers: Vec<QUIC_BUFFER>
-offset: usize
-len: usize
-read_cursor: usize
-read_cursor_in_buffer: usize
-fin: bool
+new()
+set_stream()
+len()
+is_empty()
+as_slice_upto_size()
+get_bytes_upto_size()
+offset()
+range()
+fin()
+advance()
+chunk()
+remaining()
+chunks_vectored()
}
class WriteBuffer {
-0: Box<WriteBufferInner>
+new()
+from_raw()
+put_zerocopy()
+put_slice()
+get_buffers()
+into_raw()
+reset()
}
class WriteBufferInner {
-internal: Vec<u8>
-zerocopy: Vec<Bytes>
-buffers: Vec<BufferRef>
}
StreamRecvBuffer ..> StreamInstance : uses
WriteBufferInner ..> Bytes : contains
WriteBufferInner ..> BufferRef : contains