1
+ //! This module implements a buffered/peekable reader.
2
+ //!
3
+ //! The purpose of the buffered/peekable reader is to allow for backtracking parsers.
4
+ //!
5
+ //! A reader implementing the standard librairy's [`std::io::BufRead`] trait seems like a good fit, but
6
+ //! it does not allow for peeking a specific number of bytes, so it provides no way to request
7
+ //! more data from the underlying reader without consuming the existing data.
8
+ //!
9
+ //! This API still tries to adhere to the [`std::io::BufRead`]'s trait philosophy.
10
+ //!
11
+ //! The main type `PeekReader`does not implement [`std::io::Read`] itself, as there is no added benefit
12
+ //! in doing so.
13
+ //!
14
+
1
15
use std:: io:: { self , ErrorKind , Read } ;
2
16
17
+ // The default chunk size to read from the underlying reader
3
18
const DEFAULT_CHUNK_SIZE : usize = 1024 ;
4
19
20
+ /// A buffered/peekable reader
21
+ ///
22
+ /// This reader wraps a type implementing [`std::io::Read`] and adds buffering via an internal buffer.
23
+ ///
24
+ /// It allows the user to `peek` a specified number of bytes (without consuming them),
25
+ /// to `read` bytes (consuming them), or to `consume` them after `peek`ing.
26
+ ///
5
27
pub struct PeekReader < R > {
6
28
// Internal buffer
7
29
buffer : Vec < u8 > ,
@@ -13,15 +35,17 @@ pub struct PeekReader<R> {
13
35
reader : R ,
14
36
// Stashed error, if any.
15
37
error : Option < io:: Error > ,
16
- /// Whether we hit EOF on the underlying reader.
38
+ // Whether we hit EOF on the underlying reader.
17
39
eof : bool ,
18
40
}
19
41
20
42
impl < R : Read > PeekReader < R > {
43
+ /// Instanciates a new [`PeekReader`], wrapping the provided [`std::io::Read`]er and using the default chunk size
21
44
pub fn new ( reader : R ) -> Self {
22
45
Self :: with_chunk_size ( reader, DEFAULT_CHUNK_SIZE )
23
46
}
24
47
48
+ /// Instanciates a new [`PeekReader`], wrapping the provided [`std::io::Read`]er and using the supplied chunk size
25
49
pub fn with_chunk_size ( reader : R , preferred_chunk_size : usize ) -> Self {
26
50
Self {
27
51
buffer : Vec :: with_capacity ( preferred_chunk_size) ,
@@ -33,41 +57,95 @@ impl<R: Read> PeekReader<R> {
33
57
}
34
58
}
35
59
60
+ /// Peeks a specified amount of bytes from the internal buffer
61
+ ///
62
+ /// If the internal buffer does not contain enough data, this function will read
63
+ /// from the underlying [`std::io::Read`]er until it does, an error occurs or no more data can be read (EOF).
64
+ ///
65
+ /// This function does not consume data from the buffer, so subsequent calls to `peek` or `read` functions
66
+ /// will still return the peeked data.
67
+ ///
36
68
pub fn peek ( & mut self , amount : usize ) -> io:: Result < & [ u8 ] > {
37
69
self . fetch ( amount, false , false )
38
70
}
39
71
72
+ /// Peeks an exact amount of bytes from the internal buffer
73
+ ///
74
+ /// If the internal buffer does not contain enough data, this function will read
75
+ /// from the underlying [`std::io::Read`]er until it does, an error occurs or no more data can be read (EOF).
76
+ ///
77
+ /// If an EOF occurs and the specified amount could not be read, this function will return an [`ErrorKind::UnexpectedEof`].
78
+ ///
79
+ /// This function does not consume data from the buffer, so subsequent calls to `peek` or `read` functions
80
+ /// will still return the peeked data.
81
+ ///
40
82
pub fn peek_exact ( & mut self , amount : usize ) -> io:: Result < & [ u8 ] > {
41
83
self . fetch ( amount, true , false )
42
84
}
43
85
86
+ /// Consumes a specified amount of bytes from the buffer
87
+ ///
88
+ /// If the internal buffer does not contain enough data, this function will consume as much data as is buffered.
89
+ ///
44
90
pub fn consume ( & mut self , amount : usize ) -> usize {
45
91
let amount = amount. min ( self . buffer . len ( ) - self . cursor ) ;
46
92
self . cursor += amount;
47
93
amount
48
94
}
49
95
96
+ /// Reads a specified amount of bytes from the internal buffer
97
+ ///
98
+ /// If the internal buffer does not contain enough data, this function will read
99
+ /// from the underlying [`std::io::Read`]er until it does, an error occurs or no more data can be read (EOF).
100
+ ///
101
+ /// This function consumes the data from the buffer, unless an error occurs, in which case no data is consumed.
102
+ ///
50
103
pub fn read ( & mut self , amount : usize ) -> io:: Result < & [ u8 ] > {
51
104
self . fetch ( amount, false , true )
52
105
}
53
106
107
+ /// Reads a specified amount of bytes from the internal buffer
108
+ ///
109
+ /// If the internal buffer does not contain enough data, this function will read
110
+ /// from the underlying [`std::io::Read`]er until it does, an error occurs or no more data can be read (EOF).
111
+ ///
112
+ /// If an EOF occurs and the specified amount could not be read, this function will return an [`ErrorKind::UnexpectedEof`].
113
+ ///
114
+ /// This function consumes the data from the buffer, unless an error occurs, in which case no data is consumed.
115
+ ///
54
116
pub fn read_exact ( & mut self , amount : usize ) -> io:: Result < & [ u8 ] > {
55
117
self . fetch ( amount, true , true )
56
118
}
57
119
120
+ /// Reads a byte from the internal buffer
121
+ ///
122
+ /// If the internal buffer does not contain enough data, this function will read
123
+ /// from the underlying [`std::io::Read`]er until it does, an error occurs or no more data can be read (EOF).
124
+ ///
125
+ /// If an EOF occurs and the specified amount could not be read, this function will return an [`ErrorKind::UnexpectedEof`].
126
+ ///
127
+ /// This function consumes the data from the buffer, unless an error occurs, in which case no data is consumed.
128
+ ///
58
129
pub fn read_u8 ( & mut self ) -> io:: Result < u8 > {
59
130
let buf = self . read_exact ( 1 ) ?;
60
131
Ok ( buf[ 0 ] )
61
132
}
62
133
134
+ /// Returns an immutable reference to the underlying [`std::io::Read`]er
135
+ ///
136
+ /// Reading directly from the underlying stream will cause data loss
63
137
pub fn reader_ref ( & mut self ) -> & R {
64
138
& self . reader
65
139
}
66
140
141
+ /// Returns a mutable reference to the underlying [`std::io::Read`]er
142
+ ///
143
+ /// Reading directly from the underlying stream will cause data loss
67
144
pub fn reader_mut ( & mut self ) -> & mut R {
68
145
& mut self . reader
69
146
}
70
147
148
+ /// Internal function to fetch data from the internal buffer and/or reader
71
149
fn fetch ( & mut self , amount : usize , exact : bool , consume : bool ) -> io:: Result < & [ u8 ] > {
72
150
let previous_len = self . buffer . len ( ) ;
73
151
let mut buffered = previous_len - self . cursor ;
@@ -109,6 +187,7 @@ impl<R: Read> PeekReader<R> {
109
187
}
110
188
}
111
189
}
190
+ // if some bytes were read, add them to the buffer
112
191
if read > 0 {
113
192
if self . buffer . capacity ( ) - previous_len < read {
114
193
// reallocate
0 commit comments