Skip to main content

quiche/
buffers.rs

1// Copyright (C) 2026, 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::fmt::Debug;
28use std::sync::Arc;
29
30/// A trait for providing internal storage buffers for streams,
31/// enabling zero-copy operations.
32/// The associated type `Buf` can be any type that dereferences to
33/// a slice, but should be fast to clone, eg. by wrapping it with an
34/// [`Arc`].
35pub trait BufFactory: Clone + Default + Debug {
36    /// The type of the generated buffer. The clone operation should be cheap,
37    /// e.g., by using an [`Arc`].
38    type Buf: Clone + Debug + AsRef<[u8]>;
39
40    /// The type of generated buffers used for datagrams. These do not need to
41    /// be cloneable.
42    type DgramBuf: AsRef<[u8]> + From<Vec<u8>>;
43
44    /// Generate a new buffer from a given slice, the buffer must contain the
45    /// same data as the original slice.
46    fn buf_from_slice(buf: &[u8]) -> Self::Buf;
47
48    /// Generate a new datagram buffer from a given slice, the buffer must
49    /// contain the same data as the original slice.
50    fn dgram_buf_from_slice(buf: &[u8]) -> Self::DgramBuf;
51}
52
53/// A trait that enables zero-copy sends to quiche. When buffers produced
54/// by the `BufFactory` implement this trait, quiche and h3 can supply the
55/// raw buffers to be sent, instead of slices that must be copied first.
56pub trait BufSplit {
57    /// Split the buffer at a given point, after the split the old buffer
58    /// must only contain the first `at` bytes, while the newly produced
59    /// buffer must containt the remaining bytes.
60    fn split_at(&mut self, at: usize) -> Self;
61
62    /// Try to prepend a prefix to the buffer, return true if succeeded.
63    fn try_add_prefix(&mut self, _prefix: &[u8]) -> bool {
64        false
65    }
66}
67
68/// The default [`BufFactory`] allocates buffers on the heap on demand.
69#[derive(Debug, Clone, Default)]
70pub struct DefaultBufFactory;
71
72/// The default [`BufFactory::Buf`] is a boxed slice wrapped in an [`Arc`].
73#[derive(Debug, Clone, Default)]
74pub struct DefaultBuf(Arc<[u8]>);
75
76impl BufFactory for DefaultBufFactory {
77    type Buf = DefaultBuf;
78    type DgramBuf = Vec<u8>;
79
80    fn buf_from_slice(buf: &[u8]) -> DefaultBuf {
81        DefaultBuf(Arc::from(buf))
82    }
83
84    fn dgram_buf_from_slice(buf: &[u8]) -> Vec<u8> {
85        buf.into()
86    }
87}
88
89impl AsRef<[u8]> for DefaultBuf {
90    fn as_ref(&self) -> &[u8] {
91        &self.0
92    }
93}
94
95impl BufSplit for bytes::Bytes {
96    fn split_at(&mut self, at: usize) -> Self {
97        self.split_off(at)
98    }
99}
100
101impl BufSplit for bytes::BytesMut {
102    fn split_at(&mut self, at: usize) -> Self {
103        self.split_off(at)
104    }
105}