s2n_quic_core/buffer/
reader.rs

1// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2// SPDX-License-Identifier: Apache-2.0
3
4use crate::varint::VarInt;
5
6pub mod checked;
7mod complete;
8mod empty;
9pub mod incremental;
10mod limit;
11pub mod storage;
12
13pub use checked::Checked;
14pub use complete::Complete;
15pub use empty::Empty;
16pub use incremental::Incremental;
17pub use limit::Limit;
18pub use storage::Storage;
19
20#[cfg(any(test, feature = "testing"))]
21pub mod testing;
22
23/// A buffer that can be read with a tracked offset and final position.
24pub trait Reader: Storage {
25    /// Returns the currently read offset for the stream
26    fn current_offset(&self) -> VarInt;
27
28    /// Returns the final offset for the stream
29    fn final_offset(&self) -> Option<VarInt>;
30
31    /// Returns `true` if the reader has the final offset buffered
32    #[inline]
33    fn has_buffered_fin(&self) -> bool {
34        self.final_offset().is_some_and(|fin| {
35            let buffered_end = self
36                .current_offset()
37                .as_u64()
38                .saturating_add(self.buffered_len() as u64);
39            fin == buffered_end
40        })
41    }
42
43    /// Returns `true` if the reader is finished producing data
44    #[inline]
45    fn is_consumed(&self) -> bool {
46        self.final_offset()
47            .is_some_and(|fin| fin == self.current_offset())
48    }
49
50    /// Skips the data in the reader until `offset` is reached, or the reader storage is exhausted.
51    #[inline]
52    fn skip_until(&mut self, offset: VarInt) -> Result<(), Self::Error> {
53        ensure!(offset > self.current_offset(), Ok(()));
54
55        while let Some(len) = offset.checked_sub(self.current_offset()) {
56            let len = len.as_u64();
57
58            // we don't need to skip anything if the difference is 0
59            ensure!(len > 0, break);
60
61            // clamp the len to usize
62            let len = (usize::MAX as u64).min(len) as usize;
63            let _chunk = self.read_chunk(len)?;
64
65            ensure!(!self.buffer_is_empty(), break);
66        }
67
68        Ok(())
69    }
70
71    /// Limits the maximum offset that the caller can read from the reader
72    #[inline]
73    fn with_max_data(&mut self, max_data: VarInt) -> Limit<'_, Self> {
74        let max_buffered_len = max_data.saturating_sub(self.current_offset());
75        let max_buffered_len = max_buffered_len.as_u64().min(self.buffered_len() as u64) as usize;
76        self.with_read_limit(max_buffered_len)
77    }
78
79    /// Limits the maximum amount of data that the caller can read from the reader
80    #[inline]
81    fn with_read_limit(&mut self, max_buffered_len: usize) -> Limit<'_, Self> {
82        Limit::new(self, max_buffered_len)
83    }
84
85    /// Return an empty view onto the reader, with no change in current offset
86    #[inline]
87    fn with_empty_buffer(&self) -> Empty<'_, Self> {
88        Empty::new(self)
89    }
90
91    /// Enables checking the reader for correctness invariants
92    ///
93    /// # Note
94    ///
95    /// `debug_assertions` must be enabled for these checks to be performed. Otherwise, the reader
96    /// methods will simply be forwarded to `Self`.
97    #[inline]
98    fn with_checks(&mut self) -> Checked<'_, Self> {
99        Checked::new(self)
100    }
101}