]> git.lizzy.rs Git - rust.git/blob - library/std/src/io/buffered/bufreader.rs
777d376f99173a920b896228b03aadc94cb82f81
[rust.git] / library / std / src / io / buffered / bufreader.rs
1 use crate::cmp;
2 use crate::fmt;
3 use crate::io::{self, BufRead, Initializer, IoSliceMut, Read, Seek, SeekFrom, DEFAULT_BUF_SIZE};
4
5 /// The `BufReader<R>` struct adds buffering to any reader.
6 ///
7 /// It can be excessively inefficient to work directly with a [`Read`] instance.
8 /// For example, every call to [`read`][`TcpStream::read`] on [`TcpStream`]
9 /// results in a system call. A `BufReader<R>` performs large, infrequent reads on
10 /// the underlying [`Read`] and maintains an in-memory buffer of the results.
11 ///
12 /// `BufReader<R>` can improve the speed of programs that make *small* and
13 /// *repeated* read calls to the same file or network socket. It does not
14 /// help when reading very large amounts at once, or reading just one or a few
15 /// times. It also provides no advantage when reading from a source that is
16 /// already in memory, like a [`Vec`]`<u8>`.
17 ///
18 /// When the `BufReader<R>` is dropped, the contents of its buffer will be
19 /// discarded. Creating multiple instances of a `BufReader<R>` on the same
20 /// stream can cause data loss. Reading from the underlying reader after
21 /// unwrapping the `BufReader<R>` with [`BufReader::into_inner`] can also cause
22 /// data loss.
23 ///
24 /// [`TcpStream::read`]: super::super::super::net::TcpStream::read
25 /// [`TcpStream`]: crate::net::TcpStream
26 ///
27 /// # Examples
28 ///
29 /// ```no_run
30 /// use std::io::prelude::*;
31 /// use std::io::BufReader;
32 /// use std::fs::File;
33 ///
34 /// fn main() -> std::io::Result<()> {
35 ///     let f = File::open("log.txt")?;
36 ///     let mut reader = BufReader::new(f);
37 ///
38 ///     let mut line = String::new();
39 ///     let len = reader.read_line(&mut line)?;
40 ///     println!("First line is {} bytes long", len);
41 ///     Ok(())
42 /// }
43 /// ```
44 #[stable(feature = "rust1", since = "1.0.0")]
45 pub struct BufReader<R> {
46     inner: R,
47     buf: Box<[u8]>,
48     pos: usize,
49     cap: usize,
50 }
51
52 impl<R: Read> BufReader<R> {
53     /// Creates a new `BufReader<R>` with a default buffer capacity. The default is currently 8 KB,
54     /// but may change in the future.
55     ///
56     /// # Examples
57     ///
58     /// ```no_run
59     /// use std::io::BufReader;
60     /// use std::fs::File;
61     ///
62     /// fn main() -> std::io::Result<()> {
63     ///     let f = File::open("log.txt")?;
64     ///     let reader = BufReader::new(f);
65     ///     Ok(())
66     /// }
67     /// ```
68     #[stable(feature = "rust1", since = "1.0.0")]
69     pub fn new(inner: R) -> BufReader<R> {
70         BufReader::with_capacity(DEFAULT_BUF_SIZE, inner)
71     }
72
73     /// Creates a new `BufReader<R>` with the specified buffer capacity.
74     ///
75     /// # Examples
76     ///
77     /// Creating a buffer with ten bytes of capacity:
78     ///
79     /// ```no_run
80     /// use std::io::BufReader;
81     /// use std::fs::File;
82     ///
83     /// fn main() -> std::io::Result<()> {
84     ///     let f = File::open("log.txt")?;
85     ///     let reader = BufReader::with_capacity(10, f);
86     ///     Ok(())
87     /// }
88     /// ```
89     #[stable(feature = "rust1", since = "1.0.0")]
90     pub fn with_capacity(capacity: usize, inner: R) -> BufReader<R> {
91         unsafe {
92             let mut buffer = Vec::with_capacity(capacity);
93             buffer.set_len(capacity);
94             inner.initializer().initialize(&mut buffer);
95             BufReader { inner, buf: buffer.into_boxed_slice(), pos: 0, cap: 0 }
96         }
97     }
98 }
99
100 impl<R> BufReader<R> {
101     /// Gets a reference to the underlying reader.
102     ///
103     /// It is inadvisable to directly read from the underlying reader.
104     ///
105     /// # Examples
106     ///
107     /// ```no_run
108     /// use std::io::BufReader;
109     /// use std::fs::File;
110     ///
111     /// fn main() -> std::io::Result<()> {
112     ///     let f1 = File::open("log.txt")?;
113     ///     let reader = BufReader::new(f1);
114     ///
115     ///     let f2 = reader.get_ref();
116     ///     Ok(())
117     /// }
118     /// ```
119     #[stable(feature = "rust1", since = "1.0.0")]
120     pub fn get_ref(&self) -> &R {
121         &self.inner
122     }
123
124     /// Gets a mutable reference to the underlying reader.
125     ///
126     /// It is inadvisable to directly read from the underlying reader.
127     ///
128     /// # Examples
129     ///
130     /// ```no_run
131     /// use std::io::BufReader;
132     /// use std::fs::File;
133     ///
134     /// fn main() -> std::io::Result<()> {
135     ///     let f1 = File::open("log.txt")?;
136     ///     let mut reader = BufReader::new(f1);
137     ///
138     ///     let f2 = reader.get_mut();
139     ///     Ok(())
140     /// }
141     /// ```
142     #[stable(feature = "rust1", since = "1.0.0")]
143     pub fn get_mut(&mut self) -> &mut R {
144         &mut self.inner
145     }
146
147     /// Returns a reference to the internally buffered data.
148     ///
149     /// Unlike [`fill_buf`], this will not attempt to fill the buffer if it is empty.
150     ///
151     /// [`fill_buf`]: BufRead::fill_buf
152     ///
153     /// # Examples
154     ///
155     /// ```no_run
156     /// use std::io::{BufReader, BufRead};
157     /// use std::fs::File;
158     ///
159     /// fn main() -> std::io::Result<()> {
160     ///     let f = File::open("log.txt")?;
161     ///     let mut reader = BufReader::new(f);
162     ///     assert!(reader.buffer().is_empty());
163     ///
164     ///     if reader.fill_buf()?.len() > 0 {
165     ///         assert!(!reader.buffer().is_empty());
166     ///     }
167     ///     Ok(())
168     /// }
169     /// ```
170     #[stable(feature = "bufreader_buffer", since = "1.37.0")]
171     pub fn buffer(&self) -> &[u8] {
172         &self.buf[self.pos..self.cap]
173     }
174
175     /// Returns the number of bytes the internal buffer can hold at once.
176     ///
177     /// # Examples
178     ///
179     /// ```no_run
180     /// use std::io::{BufReader, BufRead};
181     /// use std::fs::File;
182     ///
183     /// fn main() -> std::io::Result<()> {
184     ///     let f = File::open("log.txt")?;
185     ///     let mut reader = BufReader::new(f);
186     ///
187     ///     let capacity = reader.capacity();
188     ///     let buffer = reader.fill_buf()?;
189     ///     assert!(buffer.len() <= capacity);
190     ///     Ok(())
191     /// }
192     /// ```
193     #[stable(feature = "buffered_io_capacity", since = "1.46.0")]
194     pub fn capacity(&self) -> usize {
195         self.buf.len()
196     }
197
198     /// Unwraps this `BufReader<R>`, returning the underlying reader.
199     ///
200     /// Note that any leftover data in the internal buffer is lost. Therefore,
201     /// a following read from the underlying reader may lead to data loss.
202     ///
203     /// # Examples
204     ///
205     /// ```no_run
206     /// use std::io::BufReader;
207     /// use std::fs::File;
208     ///
209     /// fn main() -> std::io::Result<()> {
210     ///     let f1 = File::open("log.txt")?;
211     ///     let reader = BufReader::new(f1);
212     ///
213     ///     let f2 = reader.into_inner();
214     ///     Ok(())
215     /// }
216     /// ```
217     #[stable(feature = "rust1", since = "1.0.0")]
218     pub fn into_inner(self) -> R {
219         self.inner
220     }
221
222     /// Invalidates all data in the internal buffer.
223     #[inline]
224     fn discard_buffer(&mut self) {
225         self.pos = 0;
226         self.cap = 0;
227     }
228 }
229
230 impl<R: Seek> BufReader<R> {
231     /// Seeks relative to the current position. If the new position lies within the buffer,
232     /// the buffer will not be flushed, allowing for more efficient seeks.
233     /// This method does not return the location of the underlying reader, so the caller
234     /// must track this information themselves if it is required.
235     #[unstable(feature = "bufreader_seek_relative", issue = "31100")]
236     pub fn seek_relative(&mut self, offset: i64) -> io::Result<()> {
237         let pos = self.pos as u64;
238         if offset < 0 {
239             if let Some(new_pos) = pos.checked_sub((-offset) as u64) {
240                 self.pos = new_pos as usize;
241                 return Ok(());
242             }
243         } else {
244             if let Some(new_pos) = pos.checked_add(offset as u64) {
245                 if new_pos <= self.cap as u64 {
246                     self.pos = new_pos as usize;
247                     return Ok(());
248                 }
249             }
250         }
251         self.seek(SeekFrom::Current(offset)).map(drop)
252     }
253 }
254
255 #[stable(feature = "rust1", since = "1.0.0")]
256 impl<R: Read> Read for BufReader<R> {
257     fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
258         // If we don't have any buffered data and we're doing a massive read
259         // (larger than our internal buffer), bypass our internal buffer
260         // entirely.
261         if self.pos == self.cap && buf.len() >= self.buf.len() {
262             self.discard_buffer();
263             return self.inner.read(buf);
264         }
265         let nread = {
266             let mut rem = self.fill_buf()?;
267             rem.read(buf)?
268         };
269         self.consume(nread);
270         Ok(nread)
271     }
272
273     fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
274         let total_len = bufs.iter().map(|b| b.len()).sum::<usize>();
275         if self.pos == self.cap && total_len >= self.buf.len() {
276             self.discard_buffer();
277             return self.inner.read_vectored(bufs);
278         }
279         let nread = {
280             let mut rem = self.fill_buf()?;
281             rem.read_vectored(bufs)?
282         };
283         self.consume(nread);
284         Ok(nread)
285     }
286
287     fn is_read_vectored(&self) -> bool {
288         self.inner.is_read_vectored()
289     }
290
291     // we can't skip unconditionally because of the large buffer case in read.
292     unsafe fn initializer(&self) -> Initializer {
293         self.inner.initializer()
294     }
295 }
296
297 #[stable(feature = "rust1", since = "1.0.0")]
298 impl<R: Read> BufRead for BufReader<R> {
299     fn fill_buf(&mut self) -> io::Result<&[u8]> {
300         // If we've reached the end of our internal buffer then we need to fetch
301         // some more data from the underlying reader.
302         // Branch using `>=` instead of the more correct `==`
303         // to tell the compiler that the pos..cap slice is always valid.
304         if self.pos >= self.cap {
305             debug_assert!(self.pos == self.cap);
306             self.cap = self.inner.read(&mut self.buf)?;
307             self.pos = 0;
308         }
309         Ok(&self.buf[self.pos..self.cap])
310     }
311
312     fn consume(&mut self, amt: usize) {
313         self.pos = cmp::min(self.pos + amt, self.cap);
314     }
315 }
316
317 #[stable(feature = "rust1", since = "1.0.0")]
318 impl<R> fmt::Debug for BufReader<R>
319 where
320     R: fmt::Debug,
321 {
322     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
323         fmt.debug_struct("BufReader")
324             .field("reader", &self.inner)
325             .field("buffer", &format_args!("{}/{}", self.cap - self.pos, self.buf.len()))
326             .finish()
327     }
328 }
329
330 #[stable(feature = "rust1", since = "1.0.0")]
331 impl<R: Seek> Seek for BufReader<R> {
332     /// Seek to an offset, in bytes, in the underlying reader.
333     ///
334     /// The position used for seeking with [`SeekFrom::Current`]`(_)` is the
335     /// position the underlying reader would be at if the `BufReader<R>` had no
336     /// internal buffer.
337     ///
338     /// Seeking always discards the internal buffer, even if the seek position
339     /// would otherwise fall within it. This guarantees that calling
340     /// [`BufReader::into_inner()`] immediately after a seek yields the underlying reader
341     /// at the same position.
342     ///
343     /// To seek without discarding the internal buffer, use [`BufReader::seek_relative`].
344     ///
345     /// See [`std::io::Seek`] for more details.
346     ///
347     /// Note: In the edge case where you're seeking with [`SeekFrom::Current`]`(n)`
348     /// where `n` minus the internal buffer length overflows an `i64`, two
349     /// seeks will be performed instead of one. If the second seek returns
350     /// [`Err`], the underlying reader will be left at the same position it would
351     /// have if you called `seek` with [`SeekFrom::Current`]`(0)`.
352     ///
353     /// [`std::io::Seek`]: Seek
354     fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
355         let result: u64;
356         if let SeekFrom::Current(n) = pos {
357             let remainder = (self.cap - self.pos) as i64;
358             // it should be safe to assume that remainder fits within an i64 as the alternative
359             // means we managed to allocate 8 exbibytes and that's absurd.
360             // But it's not out of the realm of possibility for some weird underlying reader to
361             // support seeking by i64::MIN so we need to handle underflow when subtracting
362             // remainder.
363             if let Some(offset) = n.checked_sub(remainder) {
364                 result = self.inner.seek(SeekFrom::Current(offset))?;
365             } else {
366                 // seek backwards by our remainder, and then by the offset
367                 self.inner.seek(SeekFrom::Current(-remainder))?;
368                 self.discard_buffer();
369                 result = self.inner.seek(SeekFrom::Current(n))?;
370             }
371         } else {
372             // Seeking with Start/End doesn't care about our buffer length.
373             result = self.inner.seek(pos)?;
374         }
375         self.discard_buffer();
376         Ok(result)
377     }
378
379     /// Returns the current seek position from the start of the stream.
380     ///
381     /// The value returned is equivalent to `self.seek(SeekFrom::Current(0))`
382     /// but does not flush the internal buffer. Due to this optimization the
383     /// function does not guarantee that calling `.into_inner()` immediately
384     /// afterwards will yield the underlying reader at the same position. Use
385     /// [`BufReader::seek`] instead if you require that guarantee.
386     ///
387     /// # Panics
388     ///
389     /// This function will panic if the position of the inner reader is smaller
390     /// than the amount of buffered data. That can happen if the inner reader
391     /// has an incorrect implementation of [`Seek::stream_position`], or if the
392     /// position has gone out of sync due to calling [`Seek::seek`] directly on
393     /// the underlying reader.
394     ///
395     /// # Example
396     ///
397     /// ```no_run
398     /// #![feature(seek_convenience)]
399     /// use std::{
400     ///     io::{self, BufRead, BufReader, Seek},
401     ///     fs::File,
402     /// };
403     ///
404     /// fn main() -> io::Result<()> {
405     ///     let mut f = BufReader::new(File::open("foo.txt")?);
406     ///
407     ///     let before = f.stream_position()?;
408     ///     f.read_line(&mut String::new())?;
409     ///     let after = f.stream_position()?;
410     ///
411     ///     println!("The first line was {} bytes long", after - before);
412     ///     Ok(())
413     /// }
414     /// ```
415     fn stream_position(&mut self) -> io::Result<u64> {
416         let remainder = (self.cap - self.pos) as u64;
417         self.inner.stream_position().map(|pos| {
418             pos.checked_sub(remainder).expect(
419                 "overflow when subtracting remaining buffer size from inner stream position",
420             )
421         })
422     }
423 }