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 /// Generate a new buffer from a given slice, the buffer must contain the
41 /// same data as the original slice.
42 fn buf_from_slice(buf: &[u8]) -> Self::Buf;
43}
44
45/// A trait that enables zero-copy sends to quiche. When buffers produced
46/// by the `BufFactory` implement this trait, quiche and h3 can supply the
47/// raw buffers to be sent, instead of slices that must be copied first.
48pub trait BufSplit {
49 /// Split the buffer at a given point, after the split the old buffer
50 /// must only contain the first `at` bytes, while the newly produced
51 /// buffer must containt the remaining bytes.
52 fn split_at(&mut self, at: usize) -> Self;
53
54 /// Try to prepend a prefix to the buffer, return true if succeeded.
55 fn try_add_prefix(&mut self, _prefix: &[u8]) -> bool {
56 false
57 }
58}
59
60/// The default [`BufFactory`] allocates buffers on the heap on demand.
61#[derive(Debug, Clone, Default)]
62pub struct DefaultBufFactory;
63
64/// The default [`BufFactory::Buf`] is a boxed slice wrapped in an [`Arc`].
65#[derive(Debug, Clone, Default)]
66pub struct DefaultBuf(Arc<Box<[u8]>>);
67
68impl BufFactory for DefaultBufFactory {
69 type Buf = DefaultBuf;
70
71 fn buf_from_slice(buf: &[u8]) -> Self::Buf {
72 DefaultBuf(Arc::new(buf.into()))
73 }
74}
75
76impl AsRef<[u8]> for DefaultBuf {
77 fn as_ref(&self) -> &[u8] {
78 &self.0[..]
79 }
80}