blitz_ws/
buffer.rs

1//! A buffer for reading data from the network.
2//!
3//! The `ReadBuffer` is a buffer of bytes similar to a first-in, first-out queue.
4//! It is filled by reading from a stream supporting `Read` and is then
5//! accessible as a cursor for reading bytes.
6
7use bytes::Buf;
8use std::io::{Cursor, Read, Result as IoResult};
9
10/// A FIFO buffer for reading packets from the network.
11#[derive(Debug)]
12pub struct ReadBuffer<const CHUNK_SIZE: usize> {
13    storage: Cursor<Vec<u8>>,
14    chunk: Box<[u8; CHUNK_SIZE]>,
15}
16
17impl<const CHUNK_SIZE: usize> ReadBuffer<CHUNK_SIZE> {
18    /// Initializes an empty input buffer
19    pub fn new() -> Self {
20        Self::with_capacity(CHUNK_SIZE)
21    }
22
23    /// Initalizes an empty input buffer with a given capacity
24    pub fn with_capacity(capacity: usize) -> Self {
25        Self {
26            storage: Cursor::new(Vec::with_capacity(capacity)),
27            chunk: Box::new([0; CHUNK_SIZE]),
28        }
29    }
30
31    /// Reads the next portion of the data from the given input stream
32    pub fn read_from<S: Read>(&mut self, source: &mut S) -> IoResult<usize> {
33        self.clean();
34
35        let read_size = source.read(&mut *self.chunk)?;
36        self.storage.get_mut().extend_from_slice(&self.chunk[..read_size]);
37
38        Ok(read_size)
39    }
40
41    /// Cleans up the parts of the vector that has already been ready by the cursor
42    fn clean(&mut self) {
43        let pos = self.storage.position() as usize;
44        self.storage.get_mut().drain(..pos);
45        self.storage.set_position(0);
46    }
47
48    /// Consumes the `ReadBuffer` and gets the internal data storage
49    pub fn into_vec(mut self) -> Vec<u8> {
50        self.clean();
51        self.storage.into_inner()
52    }
53
54    /// Gets a cursor to the data storage
55    pub fn as_cursor(&self) -> &Cursor<Vec<u8>> {
56        &self.storage
57    }
58
59    /// Gets a cursor to the mutable data storage
60    pub fn as_cursor_mut(&mut self) -> &mut Cursor<Vec<u8>> {
61        &mut self.storage
62    }
63}
64
65impl<const CHUNK_SIZE: usize> Buf for ReadBuffer<CHUNK_SIZE> {
66    fn remaining(&self) -> usize {
67        self.storage.get_ref().len() - self.storage.position() as usize
68    }
69
70    fn chunk(&self) -> &[u8] {
71        let pos = self.storage.position() as usize;
72        &self.storage.get_ref()[pos..]
73    }
74
75    fn advance(&mut self, cnt: usize) {
76        let new_position =
77            (self.storage.position() + cnt as u64).min(self.storage.get_ref().len() as u64);
78        self.storage.set_position(new_position);
79    }
80}
81
82impl<const CHUNK_SIZE: usize> Default for ReadBuffer<CHUNK_SIZE> {
83    fn default() -> Self {
84        Self::new()
85    }
86}