rocket/data/
peekable.rs
1use tokio::io::{AsyncRead, AsyncReadExt};
2
3pub struct Peekable<const N: usize, R> {
4 pub(crate) buffer: Vec<u8>,
5 pub(crate) complete: bool,
6 pub(crate) reader: R,
7}
8
9impl<const N: usize, R: AsyncRead + Unpin> Peekable<N, R> {
10 pub fn new(reader: R) -> Self {
11 Self { buffer: Vec::new(), complete: false, reader }
12 }
13
14 pub fn with_buffer(buffer: Vec<u8>, complete: bool, reader: R) -> Self {
15 Self { buffer, complete, reader }
16 }
17
18 pub async fn peek(&mut self, num: usize) -> &[u8] {
19 if self.complete {
20 return self.buffer.as_slice();
21 }
22
23 let to_read = std::cmp::min(N, num);
24 if self.buffer.len() >= to_read {
25 return self.buffer.as_slice();
26 }
27
28 if self.buffer.capacity() == 0 {
29 self.buffer.reserve(N);
30 }
31
32 while self.buffer.len() < to_read {
33 match self.reader.read_buf::<Vec<u8>>(&mut self.buffer).await {
34 Ok(0) => {
35 self.complete = self.buffer.capacity() > self.buffer.len();
36 break;
37 },
38 Ok(_) => { },
39 Err(e) => {
40 error!("failed to read into peek buffer: {:?}.", e);
41 break;
42 }
43 }
44 }
45
46 self.buffer.as_slice()
47 }
48}