1use std::fs::File;
4use std::io;
5use std::io::{BufRead, BufReader, Read, Seek};
6use std::io::{Cursor, Empty};
7
8use crate::{SeekSkipAdapter, Skip};
9
10macro_rules! deref_skip {
15 () => {
16 fn skip(&mut self, amount: u64) -> io::Result<()> {
17 (**self).skip(amount)
18 }
19
20 fn stream_position(&mut self) -> io::Result<u64> {
21 (**self).stream_position()
22 }
23
24 fn stream_len(&mut self) -> io::Result<u64> {
25 (**self).stream_len()
26 }
27 };
28}
29
30impl<T: Skip + ?Sized> Skip for &mut T {
31 deref_skip!();
32}
33
34impl<T: Skip + ?Sized> Skip for Box<T> {
35 deref_skip!();
36}
37
38macro_rules! skip_via_adapter {
39 () => {
40 fn skip(&mut self, amount: u64) -> io::Result<()> {
41 SeekSkipAdapter(self).skip(amount)
42 }
43
44 fn stream_position(&mut self) -> io::Result<u64> {
45 SeekSkipAdapter(self).stream_position()
46 }
47
48 fn stream_len(&mut self) -> io::Result<u64> {
49 SeekSkipAdapter(self).stream_len()
50 }
51 };
52}
53
54impl<T: AsRef<[u8]>> Skip for Cursor<T> {
55 skip_via_adapter!();
56}
57
58impl Skip for Empty {
59 skip_via_adapter!();
60}
61
62impl Skip for File {
63 skip_via_adapter!();
64}
65
66impl Skip for &File {
67 skip_via_adapter!();
68}
69
70impl<T: Read + Skip + ?Sized> Skip for BufReader<T> {
71 fn skip(&mut self, amount: u64) -> io::Result<()> {
72 let buf_len = self.buffer().len();
73 if let Some(skip_amount) = amount.checked_sub(buf_len as u64) {
74 if skip_amount != 0 {
75 self.get_mut().skip(skip_amount)?;
76 }
77 }
78 self.consume(buf_len.min(amount as usize));
79 Ok(())
80 }
81
82 fn stream_position(&mut self) -> io::Result<u64> {
84 let stream_pos = self.get_mut().stream_position()?;
85 Ok(stream_pos.saturating_sub(self.buffer().len() as u64))
86 }
87
88 fn stream_len(&mut self) -> io::Result<u64> {
90 self.get_mut().stream_len()
91 }
92}
93
94impl<T: Seek> Skip for SeekSkipAdapter<T> {
99 fn skip(&mut self, amount: u64) -> io::Result<()> {
100 match amount.try_into() {
101 Ok(0) => (),
102 Ok(amount) => {
103 self.seek(io::SeekFrom::Current(amount))?;
104 }
105 Err(_) => {
106 let stream_pos = self.stream_position()?;
107 let seek_pos = stream_pos
108 .checked_add(amount)
109 .ok_or_else(|| io::Error::new(io::ErrorKind::InvalidData, "seek past u64::MAX"))?;
110 self.seek(io::SeekFrom::Start(seek_pos))?;
111 }
112 }
113 Ok(())
114 }
115
116 fn stream_position(&mut self) -> io::Result<u64> {
117 self.0.stream_position()
118 }
119
120 fn stream_len(&mut self) -> io::Result<u64> {
121 let stream_pos = self.stream_position()?;
123 let len = self.0.seek(io::SeekFrom::End(0))?;
124
125 if stream_pos != len {
126 self.0.seek(io::SeekFrom::Start(stream_pos))?;
127 }
128
129 Ok(len)
130 }
131}
132
133impl<T: Read + ?Sized> Read for SeekSkipAdapter<T> {
134 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
135 self.0.read(buf)
136 }
137}