1#![allow(clippy::arithmetic_side_effects)]
2
3#[cfg(target_os = "linux")]
17pub use crate::io_uring::sequential_file_reader::{
18 SequentialFileReader, SequentialFileReaderBuilder,
19};
20use {
21 crate::{
22 FileSize,
23 file_io::{read_into_buffer, read_more_buffer},
24 io_setup::IoSetupState,
25 },
26 std::{
27 fs::File,
28 io::{self, BufRead},
29 mem::MaybeUninit,
30 ops::Range,
31 path::Path,
32 slice,
33 },
34};
35
36struct Stack<const N: usize>([MaybeUninit<u8>; N]);
43
44impl<const N: usize> Stack<N> {
45 #[inline(always)]
46 const fn new() -> Self {
47 Self([MaybeUninit::uninit(); N])
48 }
49}
50
51impl<const N: usize> Stack<N> {
52 fn capacity(&self) -> usize {
53 N
54 }
55
56 #[inline(always)]
57 unsafe fn as_slice(&self) -> &[u8] {
58 unsafe { slice::from_raw_parts(self.0.as_ptr() as *const u8, N) }
59 }
60
61 #[inline(always)]
62 unsafe fn as_mut_slice(&mut self) -> &mut [u8] {
63 unsafe { slice::from_raw_parts_mut(self.0.as_mut_ptr() as *mut u8, N) }
64 }
65}
66
67pub trait FileBufRead<'a>: BufRead {
70 fn set_file(&mut self, file: &'a File, read_limit: FileSize) -> io::Result<()>;
81
82 fn add_file_to_prefetch(&mut self, file: &'a File, read_limit: FileSize) -> io::Result<()>;
90
91 fn get_file_offset(&self) -> FileSize;
97
98 fn consume_or_skip(&mut self, n: usize);
106}
107
108pub trait RequiredLenBufRead: BufRead {
115 fn fill_buf_required(&mut self, required_len: usize) -> io::Result<&[u8]>;
127}
128
129pub trait RequiredLenBufFileRead<'a>: RequiredLenBufRead + FileBufRead<'a> {}
130impl<'a, T: RequiredLenBufRead + FileBufRead<'a>> RequiredLenBufFileRead<'a> for T {}
131
132pub struct BufferedReader<'a, const N: usize> {
134 file_offset_of_next_read: FileSize,
136 buf: Stack<N>,
138 buf_valid_bytes: Range<usize>,
140 file_last_offset: FileSize,
142 file_len_valid: FileSize,
144 file: Option<&'a File>,
146}
147
148impl<'a, const N: usize> BufferedReader<'a, N> {
149 pub const fn new() -> Self {
150 Self {
151 file_offset_of_next_read: 0,
152 buf: Stack::new(),
153 buf_valid_bytes: 0..0,
154 file_last_offset: 0,
155 file_len_valid: 0,
156 file: None,
157 }
158 }
159
160 pub fn with_file(mut self, file: &'a File, read_limit: FileSize) -> Self {
161 self.do_set_file(file, read_limit);
162 self
163 }
164
165 fn do_set_file(&mut self, file: &'a File, read_limit: FileSize) {
166 self.file = Some(file);
167 self.file_len_valid = read_limit;
168 self.file_last_offset = 0;
169 self.file_offset_of_next_read = 0;
170 self.buf_valid_bytes = 0..0;
171 }
172
173 pub fn rebind<'b>(self) -> io::Result<BufferedReader<'b, N>> {
175 Ok(BufferedReader {
176 file_offset_of_next_read: 0,
177 buf: self.buf,
178 buf_valid_bytes: 0..0,
179 file_last_offset: 0,
180 file_len_valid: 0,
181 file: None,
182 })
183 }
184}
185
186impl<'a, const N: usize> FileBufRead<'a> for BufferedReader<'a, N> {
187 fn set_file(&mut self, file: &'a File, read_limit: FileSize) -> io::Result<()> {
188 self.do_set_file(file, read_limit);
189 Ok(())
190 }
191
192 fn add_file_to_prefetch(&mut self, _file: &'a File, _read_limit: FileSize) -> io::Result<()> {
195 Ok(())
196 }
197
198 #[inline(always)]
199 fn get_file_offset(&self) -> FileSize {
200 if self.buf_valid_bytes.is_empty() {
201 self.file_offset_of_next_read
202 } else {
203 self.file_last_offset + self.buf_valid_bytes.start as FileSize
204 }
205 }
206
207 fn consume_or_skip(&mut self, amt: usize) {
208 if self.buf_valid_bytes.len() >= amt {
209 self.buf_valid_bytes.start += amt;
210 } else {
211 let additional_amount_to_skip = amt - self.buf_valid_bytes.len();
212 self.buf_valid_bytes = 0..0;
213 self.file_offset_of_next_read += additional_amount_to_skip as FileSize;
214 }
215 }
216}
217
218impl<const N: usize> BufferedReader<'_, N> {
219 fn read_more_bytes(&mut self) -> io::Result<()> {
222 debug_assert!(self.buf_valid_bytes.len() as FileSize <= self.file_offset_of_next_read);
224 self.file_last_offset =
225 self.file_offset_of_next_read - self.buf_valid_bytes.len() as FileSize;
226 let Some(file) = &self.file else {
227 return Err(io::Error::new(io::ErrorKind::BrokenPipe, "no open file"));
228 };
229 read_more_buffer(
230 file,
231 self.file_len_valid,
232 &mut self.file_offset_of_next_read,
233 unsafe { self.buf.as_mut_slice() },
235 &mut self.buf_valid_bytes,
236 )
237 }
238
239 fn valid_slice(&self) -> &[u8] {
240 unsafe { &self.buf.as_slice()[self.buf_valid_bytes.clone()] }
243 }
244}
245
246impl<const N: usize> io::Read for BufferedReader<'_, N> {
247 fn read(&mut self, mut buf: &mut [u8]) -> io::Result<usize> {
248 let available_len = self.buf_valid_bytes.len();
249 if available_len > 0 {
250 let available_valid_data = self.valid_slice();
252 if available_len >= buf.len() {
253 buf.copy_from_slice(&available_valid_data[..buf.len()]);
254 self.consume(buf.len());
255 return Ok(buf.len());
256 }
257 buf[..available_len].copy_from_slice(available_valid_data);
259 buf = &mut buf[available_len..];
260 }
261
262 let Some(file) = &self.file else {
264 return Err(io::Error::new(io::ErrorKind::BrokenPipe, "no open file"));
265 };
266 let bytes_read = read_into_buffer(
267 file,
268 self.file_len_valid,
269 self.file_offset_of_next_read,
270 buf,
271 )?;
272 let filled_len = bytes_read + available_len;
273 self.consume_or_skip(filled_len);
275 Ok(filled_len)
276 }
277}
278
279impl<const N: usize> BufRead for BufferedReader<'_, N> {
282 fn fill_buf(&mut self) -> io::Result<&[u8]> {
283 if self.buf_valid_bytes.is_empty() {
284 self.read_more_bytes()?;
285 }
286 Ok(self.valid_slice())
287 }
288
289 fn consume(&mut self, amt: usize) {
295 self.buf_valid_bytes.start = self
296 .buf_valid_bytes
297 .end
298 .min(self.buf_valid_bytes.start + amt)
299 }
300}
301
302impl<const N: usize> RequiredLenBufRead for BufferedReader<'_, N> {
304 fn fill_buf_required(&mut self, required_len: usize) -> io::Result<&[u8]> {
305 if self.buf_valid_bytes.len() < required_len {
306 self.read_more_bytes()?;
307 if self.buf_valid_bytes.len() < required_len {
308 if required_len > self.buf.capacity() {
309 return Err(io::Error::new(
310 io::ErrorKind::QuotaExceeded,
311 "requested more bytes than supported by buffer",
312 ));
313 }
314 return Err(io::Error::new(
315 io::ErrorKind::UnexpectedEof,
316 "unable to read enough data",
317 ));
318 }
319 }
320 Ok(self.valid_slice())
321 }
322}
323
324pub struct BufReaderWithOverflow<R> {
329 reader: R,
330 overflow_buf: Vec<u8>,
331 overflow_min_capacity: usize,
332 overflow_max_capacity: usize,
333}
334
335impl<R: BufRead> BufReaderWithOverflow<R> {
336 pub fn new(reader: R, overflow_min_capacity: usize, overflow_max_capacity: usize) -> Self {
337 Self {
338 reader,
339 overflow_buf: Vec::new(),
340 overflow_min_capacity,
341 overflow_max_capacity,
342 }
343 }
344}
345
346impl<R: BufRead> io::Read for BufReaderWithOverflow<R> {
347 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
348 let available_len = self.overflow_buf.len();
349 if available_len == 0 {
350 self.reader.read(buf)
351 } else {
352 assert!(
353 buf.len() >= available_len,
354 "should read all previously required bytes"
355 );
356 buf[..available_len].copy_from_slice(&self.overflow_buf);
357 self.overflow_buf.clear();
358 if buf.len() > available_len {
359 let bytes_read = self.reader.read(&mut buf[available_len..])?;
360 Ok(available_len + bytes_read)
361 } else {
362 Ok(available_len)
363 }
364 }
365 }
366}
367
368impl<R: BufRead> BufRead for BufReaderWithOverflow<R> {
369 fn fill_buf(&mut self) -> io::Result<&[u8]> {
370 if self.overflow_buf.is_empty() {
371 self.reader.fill_buf()
372 } else {
373 Ok(self.overflow_buf.as_slice())
374 }
375 }
376
377 fn consume(&mut self, mut amt: usize) {
378 let overflow_len = self.overflow_buf.len();
379 if overflow_len > 0 {
380 amt = amt
381 .checked_sub(overflow_len)
382 .expect("should consume all previously required bytes");
383 self.overflow_buf.clear();
384 }
385 self.reader.consume(amt);
386 }
387}
388
389impl<'a, R: FileBufRead<'a>> FileBufRead<'a> for BufReaderWithOverflow<R> {
390 fn set_file(&mut self, file: &'a File, read_limit: FileSize) -> io::Result<()> {
391 self.overflow_buf.clear();
392 self.reader.set_file(file, read_limit)
393 }
394
395 fn add_file_to_prefetch(&mut self, file: &'a File, read_limit: FileSize) -> io::Result<()> {
396 self.reader.add_file_to_prefetch(file, read_limit)
397 }
398
399 fn get_file_offset(&self) -> FileSize {
400 self.reader.get_file_offset() - self.overflow_buf.len() as FileSize
401 }
402
403 fn consume_or_skip(&mut self, mut amt: usize) {
404 let overflow_len = self.overflow_buf.len();
405 if overflow_len > 0 {
406 amt = amt
407 .checked_sub(overflow_len)
408 .expect("should consume all previously required bytes");
409 self.overflow_buf.clear();
410 }
411 self.reader.consume_or_skip(amt);
412 }
413}
414
415impl<R: BufRead> RequiredLenBufRead for BufReaderWithOverflow<R> {
418 fn fill_buf_required(&mut self, required_len: usize) -> io::Result<&[u8]> {
419 let available_len = self.overflow_buf.len();
420 if available_len == 0 {
421 let buf = self.reader.fill_buf()?;
422 if buf.len() >= required_len {
423 return self.reader.fill_buf();
426 }
427 }
428 assert!(
429 available_len <= required_len,
430 "fill_buf_required should keep or grow required_len until consume"
431 );
432 if required_len > self.overflow_buf.capacity() {
433 let target_capacity = required_len
434 .next_power_of_two()
435 .clamp(self.overflow_min_capacity, self.overflow_max_capacity);
436 if required_len > target_capacity {
437 return Err(io::Error::new(
438 io::ErrorKind::QuotaExceeded,
439 "requested more bytes than allowed capacity range",
440 ));
441 }
442 self.overflow_buf
443 .reserve_exact(target_capacity - available_len);
444 }
445 unsafe { self.overflow_buf.set_len(required_len) };
447
448 self.reader
451 .read_exact(&mut self.overflow_buf[available_len..])
452 .inspect_err(|_| self.overflow_buf.clear())?;
453 Ok(self.overflow_buf.as_slice())
454 }
455}
456
457pub fn large_file_buf_reader(
460 path: &Path,
461 buf_size: usize,
462 io_setup: &IoSetupState,
463) -> io::Result<impl BufRead + use<>> {
464 #[cfg(target_os = "linux")]
465 {
466 assert!(agave_io_uring::io_uring_supported());
467
468 let mut reader = SequentialFileReaderBuilder::new()
469 .shared_sqpoll(io_setup.shared_sqpoll_fd())
470 .use_direct_io(io_setup.use_direct_io)
471 .use_registered_buffers(io_setup.use_registered_io_uring_buffers)
472 .build(buf_size)?;
473 reader.set_path(path)?;
474 Ok(reader)
475 }
476 #[cfg(not(target_os = "linux"))]
477 {
478 use std::io::BufReader;
479 let file = File::open(path)?;
480 let _ = io_setup;
481 Ok(BufReader::with_capacity(buf_size, file))
482 }
483}
484
485#[cfg(test)]
486mod tests {
487 use {
488 super::*,
489 std::io::{Read as _, Write},
490 tempfile::tempfile,
491 };
492
493 #[inline(always)]
494 fn rand_bytes<const N: usize>() -> [u8; N] {
495 use rand::Rng;
496 let mut rng = rand::rng();
497 std::array::from_fn(|_| rng.random::<u8>())
498 }
499
500 #[test]
501 fn test_buffered_reader() {
502 const BUFFER_SIZE: usize = 16;
504 const FILE_SIZE: usize = 32;
505 let mut sample_file = tempfile().unwrap();
506 let bytes = rand_bytes::<FILE_SIZE>();
507 sample_file.write_all(&bytes).unwrap();
508
509 let file_len_valid = 32;
511 let default_min_read = 8;
512 let mut reader =
513 BufferedReader::<BUFFER_SIZE>::new().with_file(&sample_file, file_len_valid);
514 let offset = reader.get_file_offset();
515 let slice = reader.fill_buf_required(default_min_read).unwrap();
516 let mut expected_offset = 0;
517 assert_eq!(offset, expected_offset);
518 assert_eq!(slice.len(), BUFFER_SIZE);
519 assert_eq!(slice, &bytes[0..BUFFER_SIZE]);
520
521 let advance = 16;
524 let mut required_len = 32;
525 reader.consume(advance);
526 let offset = reader.get_file_offset();
527 expected_offset += advance as FileSize;
528 assert_eq!(offset, expected_offset);
529 assert_eq!(
530 reader
531 .fill_buf_required(required_len)
532 .expect_err("should fail due to required length above buffer size")
533 .kind(),
534 io::ErrorKind::QuotaExceeded
535 );
536
537 reader.consume(advance);
539 let offset = reader.get_file_offset();
540 expected_offset += advance as FileSize;
541 assert_eq!(offset, expected_offset);
542 required_len = 16;
543 assert_eq!(
544 reader
545 .fill_buf_required(required_len)
546 .expect_err("should hit EOF")
547 .kind(),
548 io::ErrorKind::UnexpectedEof
549 );
550
551 required_len = 0;
553 let offset = reader.get_file_offset();
554 let slice = reader.fill_buf_required(required_len).unwrap();
555 let expected_offset = file_len_valid;
556 assert_eq!(offset, expected_offset);
557 let expected_slice_len = 0;
558 assert_eq!(slice.len(), expected_slice_len);
559 }
560
561 #[test]
562 fn test_buffered_reader_with_extra_data_in_file() {
563 const BUFFER_SIZE: usize = 16;
565 const FILE_SIZE: usize = 32;
566 let mut sample_file = tempfile().unwrap();
567 let bytes = rand_bytes::<FILE_SIZE>();
568 sample_file.write_all(&bytes).unwrap();
569
570 let valid_len = 30;
572
573 let default_min_read_size = 8;
575 let mut reader = BufferedReader::<BUFFER_SIZE>::new().with_file(&sample_file, valid_len);
576 let offset = reader.get_file_offset();
577 let slice = reader.fill_buf_required(default_min_read_size).unwrap();
578 let mut expected_offset = 0;
579 assert_eq!(offset, expected_offset);
580 assert_eq!(slice.len(), BUFFER_SIZE);
581 assert_eq!(slice, &bytes[0..BUFFER_SIZE]);
582
583 let mut advance = 16;
585 let mut required_data_len = 16;
586 reader.consume_or_skip(advance);
587 let offset = reader.get_file_offset();
588 expected_offset += advance as FileSize;
589 assert_eq!(offset, expected_offset);
590 assert_eq!(
591 reader
592 .fill_buf_required(required_data_len)
593 .expect_err("should hit EOF")
594 .kind(),
595 io::ErrorKind::UnexpectedEof
596 );
597
598 advance = 14;
600 required_data_len = 16;
601 reader.consume_or_skip(advance);
602 let offset = reader.get_file_offset();
603 expected_offset += advance as FileSize;
604 assert_eq!(offset, expected_offset);
605 assert_eq!(
606 reader
607 .fill_buf_required(required_data_len)
608 .expect_err("should hit EOF")
609 .kind(),
610 io::ErrorKind::UnexpectedEof
611 );
612
613 advance = 1;
615 required_data_len = 8;
616 reader.consume_or_skip(advance);
617 let offset = reader.get_file_offset();
618 expected_offset += advance as FileSize;
619 assert_eq!(offset, expected_offset);
620 assert_eq!(
621 reader
622 .fill_buf_required(required_data_len)
623 .expect_err("should hit EOF")
624 .kind(),
625 io::ErrorKind::UnexpectedEof
626 );
627
628 advance = 3;
630 required_data_len = 8;
631 reader.consume_or_skip(advance);
632 let offset = reader.get_file_offset();
633 expected_offset += advance as FileSize;
634 assert_eq!(offset, expected_offset);
635 assert_eq!(
636 reader
637 .fill_buf_required(required_data_len)
638 .expect_err("Should hit EOF")
639 .kind(),
640 io::ErrorKind::UnexpectedEof
641 );
642 }
643
644 #[test]
645 fn test_buffered_reader_partial_consume() {
646 const BUFFER_SIZE: usize = 16;
648 const FILE_SIZE: usize = 32;
649 let mut sample_file = tempfile().unwrap();
650 let bytes = rand_bytes::<FILE_SIZE>();
651 sample_file.write_all(&bytes).unwrap();
652
653 let file_len_valid = 32;
655 let default_min_read_size = 8;
656 let mut reader =
657 BufferedReader::<BUFFER_SIZE>::new().with_file(&sample_file, file_len_valid);
658 let offset = reader.get_file_offset();
659 let slice = reader.fill_buf_required(default_min_read_size).unwrap();
660 let mut expected_offset = 0;
661 assert_eq!(offset, expected_offset);
662 assert_eq!(slice.len(), BUFFER_SIZE);
663 assert_eq!(slice, &bytes[0..BUFFER_SIZE]);
664
665 let mut advance = 8;
667 let mut required_len = 8;
668 reader.consume(advance);
669 let offset = reader.get_file_offset();
670 let slice = reader.fill_buf_required(required_len).unwrap();
671 expected_offset += advance as FileSize;
672 assert_eq!(offset, expected_offset);
673 assert_eq!(slice.len(), required_len);
674 assert_eq!(
675 slice,
676 &bytes[expected_offset as usize..expected_offset as usize + required_len]
677 ); advance = 8;
681 required_len = 16;
682 reader.consume(advance);
683 let offset = reader.get_file_offset();
684 let slice = reader.fill_buf_required(required_len).unwrap();
685 expected_offset += advance as FileSize;
686 assert_eq!(offset, expected_offset);
687 assert_eq!(slice.len(), required_len);
688 assert_eq!(
689 slice,
690 &bytes[expected_offset as usize..expected_offset as usize + required_len]
691 );
692
693 advance = 16;
695 required_len = 16;
696 reader.consume(advance);
697 let offset = reader.get_file_offset();
698 expected_offset += advance as FileSize;
699 assert_eq!(offset, expected_offset);
700 assert_eq!(
701 reader
702 .fill_buf_required(required_len)
703 .expect_err("should hit EOF")
704 .kind(),
705 io::ErrorKind::UnexpectedEof
706 );
707
708 required_len = 32;
710 assert_eq!(
711 reader
712 .fill_buf_required(required_len)
713 .expect_err("should fail due to too large required length")
714 .kind(),
715 io::ErrorKind::QuotaExceeded
716 );
717 }
718
719 #[test]
720 fn test_buffered_reader_partial_consume_with_move() {
721 const BUFFER_SIZE: usize = 16;
723 const FILE_SIZE: usize = 32;
724 let mut sample_file = tempfile().unwrap();
725 let bytes = rand_bytes::<FILE_SIZE>();
726 sample_file.write_all(&bytes).unwrap();
727
728 let valid_len = 32;
730 let default_min_read = 8;
731 let mut reader = BufferedReader::<BUFFER_SIZE>::new().with_file(&sample_file, valid_len);
732 let offset = reader.get_file_offset();
733 let slice = reader.fill_buf_required(default_min_read).unwrap();
734 let mut expected_offset = 0;
735 assert_eq!(offset, expected_offset);
736 assert_eq!(slice.len(), BUFFER_SIZE);
737 assert_eq!(slice, &bytes[0..BUFFER_SIZE]);
738
739 let mut advance = 8;
742 let mut required_data_len = 16;
743 reader.consume(advance);
744 let offset = reader.get_file_offset();
745 let slice = reader.fill_buf_required(required_data_len).unwrap();
746 expected_offset += advance as FileSize;
747 assert_eq!(offset, expected_offset);
748 assert_eq!(slice.len(), required_data_len);
749 assert_eq!(
750 slice,
751 &bytes[expected_offset as usize..expected_offset as usize + required_data_len]
752 );
753
754 advance = 16;
756 required_data_len = 8;
757 reader.consume(advance);
758 let offset = reader.get_file_offset();
759 let slice = reader.fill_buf_required(required_data_len).unwrap();
760 expected_offset += advance as FileSize;
761 assert_eq!(offset, expected_offset);
762 assert_eq!(slice.len(), required_data_len);
763 assert_eq!(
764 slice,
765 &bytes[expected_offset as usize..expected_offset as usize + required_data_len]
766 );
767 }
768
769 #[test]
770 fn test_fill_buf_required_or_overflow() {
771 const BUFFER_SIZE: usize = 16;
773 const FILE_SIZE: usize = 32;
774 let mut sample_file = tempfile().unwrap();
775 let bytes = rand_bytes::<FILE_SIZE>();
776 sample_file.write_all(&bytes).unwrap();
777
778 let mut reader = BufReaderWithOverflow::new(
779 BufferedReader::<BUFFER_SIZE>::new().with_file(&sample_file, FILE_SIZE as FileSize),
780 0,
781 usize::MAX,
782 );
783
784 let required_len = 8;
786 let slice = reader.fill_buf_required(required_len).unwrap();
787 assert_eq!(&slice[..required_len], &bytes[..required_len]);
788
789 reader.consume_or_skip(required_len);
791
792 let required_len = BUFFER_SIZE + 8;
794 let slice = reader.fill_buf_required(required_len).unwrap();
795
796 assert_eq!(slice.len(), required_len);
798 assert_eq!(slice, &bytes[8..8 + required_len]);
799
800 reader.consume_or_skip(required_len);
802
803 let required_len = 64;
805 let result = reader.fill_buf_required(required_len);
806 assert_eq!(result.unwrap_err().kind(), io::ErrorKind::UnexpectedEof);
807
808 let required_len = 0;
810 let offset_before = reader.get_file_offset();
811 let slice = reader.fill_buf_required(required_len).unwrap();
812 assert_eq!(slice.len(), 0);
813 let offset_after = reader.get_file_offset();
814 assert_eq!(offset_before, offset_after);
815 }
816
817 #[test]
818 fn test_overflow_reader_read_and_fill_buf() {
819 const BUFFER_SIZE: usize = 16;
820 const FILE_SIZE: usize = 64;
821 let mut sample_file = tempfile().unwrap();
822 let bytes = rand_bytes::<FILE_SIZE>();
823 sample_file.write_all(&bytes).unwrap();
824
825 let mut reader = BufReaderWithOverflow::new(
826 BufferedReader::<BUFFER_SIZE>::new().with_file(&sample_file, FILE_SIZE as FileSize),
827 0,
828 32,
829 );
830 let buf = reader.fill_buf().unwrap();
831 assert_eq!(buf, &bytes[0..BUFFER_SIZE]);
832
833 reader.consume_or_skip(8);
834 let mut buf = [0; 8];
835 assert_eq!(reader.read(&mut buf).unwrap(), 8);
836 assert_eq!(buf, &bytes[8..BUFFER_SIZE]);
837
838 assert_eq!(
839 reader
840 .fill_buf_required(40)
841 .expect_err("should exceed len limit")
842 .kind(),
843 io::ErrorKind::QuotaExceeded
844 );
845
846 let buf = reader.fill_buf_required(32).unwrap();
848 assert_eq!(buf, &bytes[BUFFER_SIZE..BUFFER_SIZE + 32]);
849 let buf = reader.fill_buf().unwrap();
851 assert_eq!(buf, &bytes[BUFFER_SIZE..BUFFER_SIZE + 32]);
852
853 let mut buf = [0; 48];
854 assert_eq!(reader.read(&mut buf).unwrap(), 48);
855 assert_eq!(buf, &bytes[BUFFER_SIZE..BUFFER_SIZE + 48]);
856
857 assert_eq!(reader.read(&mut buf).unwrap(), 0);
858
859 assert_eq!(
860 reader
861 .fill_buf_required(1)
862 .expect_err("should reach EOF")
863 .kind(),
864 io::ErrorKind::UnexpectedEof
865 );
866 }
867}