std/io/buffered/bufreader/
buffer.rs1use crate::cmp;
13use crate::io::{self, BorrowedBuf, ErrorKind, Read};
14use crate::mem::MaybeUninit;
15
16pub struct Buffer {
17 buf: Box<[MaybeUninit<u8>]>,
19 pos: usize,
21 filled: usize,
24}
25
26impl Buffer {
27 #[inline]
28 pub fn with_capacity(capacity: usize) -> Self {
29 let buf = Box::new_uninit_slice(capacity);
30 Self { buf, pos: 0, filled: 0 }
31 }
32
33 #[inline]
34 pub fn try_with_capacity(capacity: usize) -> io::Result<Self> {
35 match Box::try_new_uninit_slice(capacity) {
36 Ok(buf) => Ok(Self { buf, pos: 0, filled: 0 }),
37 Err(_) => {
38 Err(io::const_error!(ErrorKind::OutOfMemory, "failed to allocate read buffer"))
39 }
40 }
41 }
42
43 #[inline]
44 pub fn buffer(&self) -> &[u8] {
45 unsafe { self.buf.get_unchecked(self.pos..self.filled).assume_init_ref() }
48 }
49
50 #[inline]
51 pub fn capacity(&self) -> usize {
52 self.buf.len()
53 }
54
55 #[inline]
56 pub fn filled(&self) -> usize {
57 self.filled
58 }
59
60 #[inline]
61 pub fn pos(&self) -> usize {
62 self.pos
63 }
64
65 #[inline]
66 pub fn discard_buffer(&mut self) {
67 self.pos = 0;
68 self.filled = 0;
69 }
70
71 #[inline]
72 pub fn consume(&mut self, amt: usize) {
73 self.pos = cmp::min(self.pos + amt, self.filled);
74 }
75
76 #[inline]
79 pub fn consume_with<V>(&mut self, amt: usize, mut visitor: V) -> bool
80 where
81 V: FnMut(&[u8]),
82 {
83 if let Some(claimed) = self.buffer().get(..amt) {
84 visitor(claimed);
85 self.pos += amt;
87 true
88 } else {
89 false
90 }
91 }
92
93 #[inline]
94 pub fn unconsume(&mut self, amt: usize) {
95 self.pos = self.pos.saturating_sub(amt);
96 }
97
98 pub fn read_more(&mut self, mut reader: impl Read) -> io::Result<usize> {
100 let mut buf = BorrowedBuf::from(&mut self.buf[self.filled..]);
101 reader.read_buf(buf.unfilled())?;
102 self.filled += buf.len();
103 Ok(buf.len())
104 }
105
106 pub fn backshift(&mut self) {
108 self.buf.copy_within(self.pos..self.filled, 0);
109 self.filled -= self.pos;
110 self.pos = 0;
111 }
112
113 #[inline]
114 pub fn fill_buf(&mut self, mut reader: impl Read) -> io::Result<&[u8]> {
115 if self.pos >= self.filled {
120 debug_assert!(self.pos == self.filled);
121
122 let mut buf = BorrowedBuf::from(&mut *self.buf);
123 let result = reader.read_buf(buf.unfilled());
124
125 self.pos = 0;
126 self.filled = buf.len();
127
128 result?;
129 }
130 Ok(self.buffer())
131 }
132}