Coverage Report

Created: 2026-10-17 06:16

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/mp4san/common/src/async_skip.rs
Line
Count
Source
1
//! Utility functions for the [`AsyncSkip`] trait.
2
3
use std::future::Future;
4
use std::io;
5
use std::ops::DerefMut;
6
use std::pin::Pin;
7
use std::task::{ready, Context, Poll};
8
9
use futures_util::io::{BufReader, Cursor};
10
use futures_util::{AsyncBufRead, AsyncRead, AsyncSeek};
11
12
use crate::{AsyncSkip, SeekSkipAdapter};
13
14
//
15
// public types
16
//
17
18
/// An extension trait which adds utility methods to [`AsyncSkip`] types.
19
pub trait AsyncSkipExt: AsyncSkip {
20
    /// Skip an amount of bytes in a stream.
21
    ///
22
    /// A skip beyond the end of a stream is allowed, but behavior is defined by the implementation.
23
280k
    fn skip(&mut self, amount: u64) -> Skip<'_, Self> {
24
280k
        Skip { amount, inner: self }
25
280k
    }
Unexecuted instantiation: <_ as mediasan_common::async_skip::AsyncSkipExt>::skip
<core::pin::Pin<&mut futures_util::io::buf_reader::BufReader<mediasan_common::sync::AsyncInputAdapter<std::io::cursor::Cursor<&[u8]>>>> as mediasan_common::async_skip::AsyncSkipExt>::skip
Line
Count
Source
23
280k
    fn skip(&mut self, amount: u64) -> Skip<'_, Self> {
24
280k
        Skip { amount, inner: self }
25
280k
    }
Unexecuted instantiation: <_ as mediasan_common::async_skip::AsyncSkipExt>::skip
26
27
    /// Returns the current position of the cursor from the start of the stream.
28
296k
    fn stream_position(&mut self) -> StreamPosition<'_, Self> {
29
296k
        StreamPosition { inner: self }
30
296k
    }
Unexecuted instantiation: <_ as mediasan_common::async_skip::AsyncSkipExt>::stream_position
<core::pin::Pin<&mut futures_util::io::buf_reader::BufReader<mediasan_common::sync::AsyncInputAdapter<std::io::cursor::Cursor<&[u8]>>>> as mediasan_common::async_skip::AsyncSkipExt>::stream_position
Line
Count
Source
28
296k
    fn stream_position(&mut self) -> StreamPosition<'_, Self> {
29
296k
        StreamPosition { inner: self }
30
296k
    }
Unexecuted instantiation: <_ as mediasan_common::async_skip::AsyncSkipExt>::stream_position
31
32
    /// Returns the length of this stream, in bytes.
33
3.48k
    fn stream_len(&mut self) -> StreamLen<'_, Self> {
34
3.48k
        StreamLen { inner: self }
35
3.48k
    }
Unexecuted instantiation: <_ as mediasan_common::async_skip::AsyncSkipExt>::stream_len
<core::pin::Pin<&mut futures_util::io::buf_reader::BufReader<mediasan_common::sync::AsyncInputAdapter<std::io::cursor::Cursor<&[u8]>>>> as mediasan_common::async_skip::AsyncSkipExt>::stream_len
Line
Count
Source
33
3.48k
    fn stream_len(&mut self) -> StreamLen<'_, Self> {
34
3.48k
        StreamLen { inner: self }
35
3.48k
    }
Unexecuted instantiation: <_ as mediasan_common::async_skip::AsyncSkipExt>::stream_len
36
}
37
38
/// Future for the [`skip`](AsyncSkipExt::skip) method.
39
pub struct Skip<'a, T: ?Sized> {
40
    amount: u64,
41
    inner: &'a mut T,
42
}
43
44
/// Future for the [`stream_position`](AsyncSkipExt::stream_position) method.
45
pub struct StreamPosition<'a, T: ?Sized> {
46
    inner: &'a mut T,
47
}
48
49
/// Future for the [`stream_len`](AsyncSkipExt::stream_len) method.
50
pub struct StreamLen<'a, T: ?Sized> {
51
    inner: &'a mut T,
52
}
53
54
//
55
// AsyncSkipExt impls
56
//
57
58
impl<T: AsyncSkip + ?Sized> AsyncSkipExt for T {}
59
60
//
61
// Skip impls
62
//
63
64
impl<T: AsyncSkip + Unpin + ?Sized> Future for Skip<'_, T> {
65
    type Output = io::Result<()>;
66
67
280k
    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
68
280k
        let amount = self.amount;
69
280k
        Pin::new(&mut *self.inner).poll_skip(cx, amount)
70
280k
    }
Unexecuted instantiation: <mediasan_common::async_skip::Skip<_> as core::future::future::Future>::poll
<mediasan_common::async_skip::Skip<core::pin::Pin<&mut futures_util::io::buf_reader::BufReader<mediasan_common::sync::AsyncInputAdapter<std::io::cursor::Cursor<&[u8]>>>>> as core::future::future::Future>::poll
Line
Count
Source
67
280k
    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
68
280k
        let amount = self.amount;
69
280k
        Pin::new(&mut *self.inner).poll_skip(cx, amount)
70
280k
    }
Unexecuted instantiation: <mediasan_common::async_skip::Skip<_> as core::future::future::Future>::poll
71
}
72
73
//
74
// StreamPosition impls
75
//
76
77
impl<T: AsyncSkip + Unpin + ?Sized> Future for StreamPosition<'_, T> {
78
    type Output = io::Result<u64>;
79
80
296k
    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
81
296k
        Pin::new(&mut *self.inner).poll_stream_position(cx)
82
296k
    }
Unexecuted instantiation: <mediasan_common::async_skip::StreamPosition<_> as core::future::future::Future>::poll
<mediasan_common::async_skip::StreamPosition<core::pin::Pin<&mut futures_util::io::buf_reader::BufReader<mediasan_common::sync::AsyncInputAdapter<std::io::cursor::Cursor<&[u8]>>>>> as core::future::future::Future>::poll
Line
Count
Source
80
296k
    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
81
296k
        Pin::new(&mut *self.inner).poll_stream_position(cx)
82
296k
    }
Unexecuted instantiation: <mediasan_common::async_skip::StreamPosition<_> as core::future::future::Future>::poll
83
}
84
85
//
86
// StreamLen impls
87
//
88
89
impl<T: AsyncSkip + Unpin + ?Sized> Future for StreamLen<'_, T> {
90
    type Output = io::Result<u64>;
91
92
3.48k
    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
93
3.48k
        Pin::new(&mut *self.inner).poll_stream_len(cx)
94
3.48k
    }
Unexecuted instantiation: <mediasan_common::async_skip::StreamLen<_> as core::future::future::Future>::poll
<mediasan_common::async_skip::StreamLen<core::pin::Pin<&mut futures_util::io::buf_reader::BufReader<mediasan_common::sync::AsyncInputAdapter<std::io::cursor::Cursor<&[u8]>>>>> as core::future::future::Future>::poll
Line
Count
Source
92
3.48k
    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
93
3.48k
        Pin::new(&mut *self.inner).poll_stream_len(cx)
94
3.48k
    }
Unexecuted instantiation: <mediasan_common::async_skip::StreamLen<_> as core::future::future::Future>::poll
95
}
96
97
//
98
// SeekSkipAdapter impls
99
//
100
101
impl<T: AsyncRead + Unpin + ?Sized> AsyncRead for SeekSkipAdapter<T> {
102
0
    fn poll_read(mut self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &mut [u8]) -> Poll<io::Result<usize>> {
103
0
        Pin::new(&mut self.0).poll_read(cx, buf)
104
0
    }
Unexecuted instantiation: <mediasan_common::SeekSkipAdapter<_> as futures_io::if_std::AsyncRead>::poll_read
Unexecuted instantiation: <mediasan_common::SeekSkipAdapter<_> as futures_io::if_std::AsyncRead>::poll_read
105
}
106
107
impl<R: AsyncSeek + Unpin + ?Sized> AsyncSkip for SeekSkipAdapter<R> {
108
0
    fn poll_skip(mut self: Pin<&mut Self>, cx: &mut Context<'_>, amount: u64) -> Poll<io::Result<()>> {
109
0
        match amount.try_into() {
110
0
            Ok(0) => (),
111
0
            Ok(amount) => {
112
0
                let reader = Pin::new(&mut self.get_mut().0);
113
0
                ready!(reader.poll_seek(cx, io::SeekFrom::Current(amount)))?;
114
            }
115
            Err(_) => {
116
0
                let stream_pos = ready!(self.as_mut().poll_stream_position(cx))?;
117
0
                let seek_pos = stream_pos
118
0
                    .checked_add(amount)
119
0
                    .ok_or_else(|| io::Error::new(io::ErrorKind::InvalidData, "seek past u64::MAX"))?;
Unexecuted instantiation: <mediasan_common::SeekSkipAdapter<_> as mediasan_common::AsyncSkip>::poll_skip::{closure#0}
Unexecuted instantiation: <mediasan_common::SeekSkipAdapter<_> as mediasan_common::AsyncSkip>::poll_skip::{closure#0}
120
0
                let reader = Pin::new(&mut self.get_mut().0);
121
0
                ready!(reader.poll_seek(cx, io::SeekFrom::Start(seek_pos)))?;
122
            }
123
        }
124
0
        Ok(()).into()
125
0
    }
Unexecuted instantiation: <mediasan_common::SeekSkipAdapter<_> as mediasan_common::AsyncSkip>::poll_skip
Unexecuted instantiation: <mediasan_common::SeekSkipAdapter<_> as mediasan_common::AsyncSkip>::poll_skip
126
127
0
    fn poll_stream_position(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<u64>> {
128
0
        let reader = Pin::new(&mut self.get_mut().0);
129
0
        reader.poll_seek(cx, io::SeekFrom::Current(0))
130
0
    }
Unexecuted instantiation: <mediasan_common::SeekSkipAdapter<_> as mediasan_common::AsyncSkip>::poll_stream_position
Unexecuted instantiation: <mediasan_common::SeekSkipAdapter<_> as mediasan_common::AsyncSkip>::poll_stream_position
131
132
0
    fn poll_stream_len(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<u64>> {
133
        // This is the unstable Seek::stream_len
134
0
        let stream_pos = ready!(self.as_mut().poll_stream_position(cx))?;
135
0
        let mut reader = Pin::new(&mut self.get_mut().0);
136
0
        let len = ready!(reader.as_mut().poll_seek(cx, io::SeekFrom::End(0)))?;
137
138
0
        if stream_pos != len {
139
0
            ready!(reader.poll_seek(cx, io::SeekFrom::Start(stream_pos)))?;
140
0
        }
141
142
0
        Ok(len).into()
143
0
    }
Unexecuted instantiation: <mediasan_common::SeekSkipAdapter<_> as mediasan_common::AsyncSkip>::poll_stream_len
Unexecuted instantiation: <mediasan_common::SeekSkipAdapter<_> as mediasan_common::AsyncSkip>::poll_stream_len
144
}
145
146
//
147
// AsyncSkip impls
148
//
149
150
macro_rules! deref_async_skip {
151
    () => {
152
0
        fn poll_skip(mut self: Pin<&mut Self>, cx: &mut Context<'_>, amount: u64) -> Poll<io::Result<()>> {
153
0
            Pin::new(&mut **self).poll_skip(cx, amount)
154
0
        }
Unexecuted instantiation: <&mut _ as mediasan_common::AsyncSkip>::poll_skip
Unexecuted instantiation: <alloc::boxed::Box<_> as mediasan_common::AsyncSkip>::poll_skip
Unexecuted instantiation: <&mut _ as mediasan_common::AsyncSkip>::poll_skip
Unexecuted instantiation: <alloc::boxed::Box<_> as mediasan_common::AsyncSkip>::poll_skip
155
156
0
        fn poll_stream_position(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<u64>> {
157
0
            Pin::new(&mut **self).poll_stream_position(cx)
158
0
        }
Unexecuted instantiation: <&mut _ as mediasan_common::AsyncSkip>::poll_stream_position
Unexecuted instantiation: <alloc::boxed::Box<_> as mediasan_common::AsyncSkip>::poll_stream_position
Unexecuted instantiation: <&mut _ as mediasan_common::AsyncSkip>::poll_stream_position
Unexecuted instantiation: <alloc::boxed::Box<_> as mediasan_common::AsyncSkip>::poll_stream_position
159
160
0
        fn poll_stream_len(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<u64>> {
161
0
            Pin::new(&mut **self).poll_stream_len(cx)
162
0
        }
Unexecuted instantiation: <&mut _ as mediasan_common::AsyncSkip>::poll_stream_len
Unexecuted instantiation: <alloc::boxed::Box<_> as mediasan_common::AsyncSkip>::poll_stream_len
Unexecuted instantiation: <&mut _ as mediasan_common::AsyncSkip>::poll_stream_len
Unexecuted instantiation: <alloc::boxed::Box<_> as mediasan_common::AsyncSkip>::poll_stream_len
163
    };
164
}
165
166
impl<R: AsyncSkip + Unpin + ?Sized> AsyncSkip for &mut R {
167
    deref_async_skip!();
168
}
169
170
impl<R: AsyncSkip + Unpin + ?Sized> AsyncSkip for Box<R> {
171
    deref_async_skip!();
172
}
173
174
impl<P: DerefMut + Unpin> AsyncSkip for Pin<P>
175
where
176
    P::Target: AsyncSkip,
177
{
178
280k
    fn poll_skip(self: Pin<&mut Self>, cx: &mut Context<'_>, amount: u64) -> Poll<io::Result<()>> {
179
280k
        self.get_mut().as_mut().poll_skip(cx, amount)
180
280k
    }
Unexecuted instantiation: <core::pin::Pin<_> as mediasan_common::AsyncSkip>::poll_skip
<core::pin::Pin<&mut futures_util::io::buf_reader::BufReader<mediasan_common::sync::AsyncInputAdapter<std::io::cursor::Cursor<&[u8]>>>> as mediasan_common::AsyncSkip>::poll_skip
Line
Count
Source
178
280k
    fn poll_skip(self: Pin<&mut Self>, cx: &mut Context<'_>, amount: u64) -> Poll<io::Result<()>> {
179
280k
        self.get_mut().as_mut().poll_skip(cx, amount)
180
280k
    }
Unexecuted instantiation: <core::pin::Pin<_> as mediasan_common::AsyncSkip>::poll_skip
181
182
296k
    fn poll_stream_position(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<u64>> {
183
296k
        self.get_mut().as_mut().poll_stream_position(cx)
184
296k
    }
Unexecuted instantiation: <core::pin::Pin<_> as mediasan_common::AsyncSkip>::poll_stream_position
<core::pin::Pin<&mut futures_util::io::buf_reader::BufReader<mediasan_common::sync::AsyncInputAdapter<std::io::cursor::Cursor<&[u8]>>>> as mediasan_common::AsyncSkip>::poll_stream_position
Line
Count
Source
182
296k
    fn poll_stream_position(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<u64>> {
183
296k
        self.get_mut().as_mut().poll_stream_position(cx)
184
296k
    }
Unexecuted instantiation: <core::pin::Pin<_> as mediasan_common::AsyncSkip>::poll_stream_position
185
186
3.48k
    fn poll_stream_len(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<u64>> {
187
3.48k
        self.get_mut().as_mut().poll_stream_len(cx)
188
3.48k
    }
Unexecuted instantiation: <core::pin::Pin<_> as mediasan_common::AsyncSkip>::poll_stream_len
<core::pin::Pin<&mut futures_util::io::buf_reader::BufReader<mediasan_common::sync::AsyncInputAdapter<std::io::cursor::Cursor<&[u8]>>>> as mediasan_common::AsyncSkip>::poll_stream_len
Line
Count
Source
186
3.48k
    fn poll_stream_len(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<u64>> {
187
3.48k
        self.get_mut().as_mut().poll_stream_len(cx)
188
3.48k
    }
Unexecuted instantiation: <core::pin::Pin<_> as mediasan_common::AsyncSkip>::poll_stream_len
189
}
190
191
macro_rules! async_skip_via_adapter {
192
    () => {
193
0
        fn poll_skip(self: Pin<&mut Self>, cx: &mut Context<'_>, amount: u64) -> Poll<io::Result<()>> {
194
0
            Pin::new(&mut SeekSkipAdapter(self.get_mut())).poll_skip(cx, amount)
195
0
        }
Unexecuted instantiation: <futures_util::io::cursor::Cursor<_> as mediasan_common::AsyncSkip>::poll_skip
Unexecuted instantiation: <futures_util::io::cursor::Cursor<_> as mediasan_common::AsyncSkip>::poll_skip
196
197
0
        fn poll_stream_position(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<u64>> {
198
0
            Pin::new(&mut SeekSkipAdapter(self.get_mut())).poll_stream_position(cx)
199
0
        }
Unexecuted instantiation: <futures_util::io::cursor::Cursor<_> as mediasan_common::AsyncSkip>::poll_stream_position
Unexecuted instantiation: <futures_util::io::cursor::Cursor<_> as mediasan_common::AsyncSkip>::poll_stream_position
200
201
0
        fn poll_stream_len(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<u64>> {
202
0
            Pin::new(&mut SeekSkipAdapter(self.get_mut())).poll_stream_len(cx)
203
0
        }
Unexecuted instantiation: <futures_util::io::cursor::Cursor<_> as mediasan_common::AsyncSkip>::poll_stream_len
Unexecuted instantiation: <futures_util::io::cursor::Cursor<_> as mediasan_common::AsyncSkip>::poll_stream_len
204
    };
205
}
206
207
impl<T: AsRef<[u8]> + Unpin> AsyncSkip for Cursor<T> {
208
    async_skip_via_adapter!();
209
}
210
211
impl<R: AsyncRead + AsyncSkip> AsyncSkip for BufReader<R> {
212
    /// Poll skipping `amount` bytes in a [`BufReader`] implementing [`AsyncRead`] + [`AsyncSkip`].
213
280k
    fn poll_skip(mut self: Pin<&mut Self>, cx: &mut Context<'_>, amount: u64) -> Poll<io::Result<()>> {
214
280k
        let buf_len = self.buffer().len();
215
280k
        if let Some(skip_amount) = amount.checked_sub(buf_len as u64) {
216
51.4k
            if skip_amount != 0 {
217
9.22k
                ready!(self.as_mut().get_pin_mut().poll_skip(cx, skip_amount))?
218
42.2k
            }
219
229k
        }
220
280k
        self.consume(buf_len.min(amount as usize));
221
280k
        Poll::Ready(Ok(()))
222
280k
    }
Unexecuted instantiation: <futures_util::io::buf_reader::BufReader<_> as mediasan_common::AsyncSkip>::poll_skip
<futures_util::io::buf_reader::BufReader<mediasan_common::sync::AsyncInputAdapter<std::io::cursor::Cursor<&[u8]>>> as mediasan_common::AsyncSkip>::poll_skip
Line
Count
Source
213
280k
    fn poll_skip(mut self: Pin<&mut Self>, cx: &mut Context<'_>, amount: u64) -> Poll<io::Result<()>> {
214
280k
        let buf_len = self.buffer().len();
215
280k
        if let Some(skip_amount) = amount.checked_sub(buf_len as u64) {
216
51.4k
            if skip_amount != 0 {
217
9.22k
                ready!(self.as_mut().get_pin_mut().poll_skip(cx, skip_amount))?
218
42.2k
            }
219
229k
        }
220
280k
        self.consume(buf_len.min(amount as usize));
221
280k
        Poll::Ready(Ok(()))
222
280k
    }
Unexecuted instantiation: <futures_util::io::buf_reader::BufReader<_> as mediasan_common::AsyncSkip>::poll_skip
223
224
    /// Poll the stream position for a [`BufReader`] implementing [`AsyncRead`] + [`AsyncSkip`].
225
296k
    fn poll_stream_position(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<u64>> {
226
296k
        let stream_pos = ready!(self.as_mut().get_pin_mut().poll_stream_position(cx))?;
227
296k
        Poll::Ready(Ok(stream_pos.saturating_sub(self.buffer().len() as u64)))
228
296k
    }
Unexecuted instantiation: <futures_util::io::buf_reader::BufReader<_> as mediasan_common::AsyncSkip>::poll_stream_position
<futures_util::io::buf_reader::BufReader<mediasan_common::sync::AsyncInputAdapter<std::io::cursor::Cursor<&[u8]>>> as mediasan_common::AsyncSkip>::poll_stream_position
Line
Count
Source
225
296k
    fn poll_stream_position(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<u64>> {
226
296k
        let stream_pos = ready!(self.as_mut().get_pin_mut().poll_stream_position(cx))?;
227
296k
        Poll::Ready(Ok(stream_pos.saturating_sub(self.buffer().len() as u64)))
228
296k
    }
Unexecuted instantiation: <futures_util::io::buf_reader::BufReader<_> as mediasan_common::AsyncSkip>::poll_stream_position
229
230
    /// Poll the stream length for a [`BufReader`] implementing [`AsyncRead`] + [`AsyncSkip`].
231
3.48k
    fn poll_stream_len(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<u64>> {
232
3.48k
        self.as_mut().get_pin_mut().poll_stream_len(cx)
233
3.48k
    }
Unexecuted instantiation: <futures_util::io::buf_reader::BufReader<_> as mediasan_common::AsyncSkip>::poll_stream_len
<futures_util::io::buf_reader::BufReader<mediasan_common::sync::AsyncInputAdapter<std::io::cursor::Cursor<&[u8]>>> as mediasan_common::AsyncSkip>::poll_stream_len
Line
Count
Source
231
3.48k
    fn poll_stream_len(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<u64>> {
232
3.48k
        self.as_mut().get_pin_mut().poll_stream_len(cx)
233
3.48k
    }
Unexecuted instantiation: <futures_util::io::buf_reader::BufReader<_> as mediasan_common::AsyncSkip>::poll_stream_len
234
}