Skip to main content

quiche/
range_buf.rs

1// Copyright (C) 2025, Cloudflare, Inc.
2// All rights reserved.
3//
4// Redistribution and use in source and binary forms, with or without
5// modification, are permitted provided that the following conditions are
6// met:
7//
8//     * Redistributions of source code must retain the above copyright notice,
9//       this list of conditions and the following disclaimer.
10//
11//     * Redistributions in binary form must reproduce the above copyright
12//       notice, this list of conditions and the following disclaimer in the
13//       documentation and/or other materials provided with the distribution.
14//
15// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
16// IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
17// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
19// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
20// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
22// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
23// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
24// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26
27use std::cmp;
28use std::marker::PhantomData;
29use std::ops::Deref;
30
31use crate::buffers::BufFactory;
32use crate::buffers::DefaultBufFactory;
33
34/// Buffer holding data at a specific offset.
35///
36/// The data is stored in a `Vec<u8>` in such a way that it can be shared
37/// between multiple `RangeBuf` objects.
38///
39/// Each `RangeBuf` will have its own view of that buffer, where the `start`
40/// value indicates the initial offset within the `Vec`, and `len` indicates the
41/// number of bytes, starting from `start` that are included.
42///
43/// In addition, `pos` indicates the current offset within the `Vec`, starting
44/// from the very beginning of the `Vec`.
45///
46/// Finally, `off` is the starting offset for the specific `RangeBuf` within the
47/// stream the buffer belongs to.
48#[derive(Clone, Debug, Default)]
49pub struct RangeBuf<F = DefaultBufFactory>
50where
51    F: BufFactory,
52{
53    /// The internal buffer holding the data.
54    ///
55    /// To avoid needless allocations when a RangeBuf is split, this field
56    /// should be reference-counted so it can be shared between multiple
57    /// RangeBuf objects, and sliced using the `start` and `len` values.
58    pub(crate) data: F::Buf,
59
60    /// The initial offset within the internal buffer.
61    pub(crate) start: usize,
62
63    /// The current offset within the internal buffer.
64    pub(crate) pos: usize,
65
66    /// The number of bytes in the buffer, from the initial offset.
67    pub(crate) len: usize,
68
69    /// The offset of the buffer within a stream.
70    pub(crate) off: u64,
71
72    /// Whether this contains the final byte in the stream.
73    pub(crate) fin: bool,
74
75    _bf: PhantomData<F>,
76}
77
78impl<F: BufFactory> RangeBuf<F>
79where
80    F::Buf: Clone,
81{
82    /// Creates a new `RangeBuf` from the given slice.
83    pub fn from(buf: &[u8], off: u64, fin: bool) -> RangeBuf<F> {
84        Self::from_raw(F::buf_from_slice(buf), off, fin)
85    }
86
87    pub fn from_raw(data: F::Buf, off: u64, fin: bool) -> RangeBuf<F> {
88        RangeBuf {
89            len: data.as_ref().len(),
90            data,
91            start: 0,
92            pos: 0,
93            off,
94            fin,
95            _bf: Default::default(),
96        }
97    }
98
99    /// Returns whether `self` holds the final offset in the stream.
100    pub fn fin(&self) -> bool {
101        self.fin
102    }
103
104    /// Returns the starting offset of `self`.
105    pub fn off(&self) -> u64 {
106        (self.off - self.start as u64) + self.pos as u64
107    }
108
109    /// Returns the final offset of `self`.
110    pub fn max_off(&self) -> u64 {
111        self.off() + self.len() as u64
112    }
113
114    /// Returns the length of `self`.
115    pub fn len(&self) -> usize {
116        self.len - (self.pos - self.start)
117    }
118
119    /// Returns true if `self` has a length of zero bytes.
120    pub fn is_empty(&self) -> bool {
121        self.len() == 0
122    }
123
124    /// Consumes the starting `count` bytes of `self`.
125    pub fn consume(&mut self, count: usize) {
126        self.pos += count;
127    }
128
129    /// Splits the buffer into two at the given index.
130    pub fn split_off(&mut self, at: usize) -> RangeBuf<F>
131    where
132        F::Buf: Clone + AsRef<[u8]>,
133    {
134        assert!(
135            at <= self.len,
136            "`at` split index (is {}) should be <= len (is {})",
137            at,
138            self.len
139        );
140
141        let buf = RangeBuf {
142            data: self.data.clone(),
143            start: self.start + at,
144            pos: cmp::max(self.pos, self.start + at),
145            len: self.len - at,
146            off: self.off + at as u64,
147            _bf: Default::default(),
148            fin: self.fin,
149        };
150
151        self.pos = cmp::min(self.pos, self.start + at);
152        self.len = at;
153        self.fin = false;
154
155        buf
156    }
157}
158
159impl<F: BufFactory> Deref for RangeBuf<F> {
160    type Target = [u8];
161
162    fn deref(&self) -> &[u8] {
163        &self.data.as_ref()[self.pos..self.start + self.len]
164    }
165}
166
167impl<F: BufFactory> Ord for RangeBuf<F> {
168    fn cmp(&self, other: &RangeBuf<F>) -> cmp::Ordering {
169        // Invert ordering to implement min-heap.
170        self.off.cmp(&other.off).reverse()
171    }
172}
173
174impl<F: BufFactory> PartialOrd for RangeBuf<F> {
175    fn partial_cmp(&self, other: &RangeBuf<F>) -> Option<cmp::Ordering> {
176        Some(self.cmp(other))
177    }
178}
179
180impl<F: BufFactory> Eq for RangeBuf<F> {}
181
182impl<F: BufFactory> PartialEq for RangeBuf<F> {
183    fn eq(&self, other: &RangeBuf<F>) -> bool {
184        self.off == other.off
185    }
186}