s2n_quic_core/buffer/writer/
storage.rs

1// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2// SPDX-License-Identifier: Apache-2.0
3
4use crate::buffer::reader::storage::Chunk;
5use bytes::{Bytes, BytesMut};
6
7mod buf;
8mod byte_queue;
9mod discard;
10mod empty;
11mod limit;
12mod tracked;
13mod uninit_slice;
14mod vec_deque;
15mod write_once;
16
17pub use buf::BufMut;
18pub use bytes::buf::UninitSlice;
19pub use discard::Discard;
20pub use empty::Empty;
21pub use limit::Limit;
22pub use tracked::Tracked;
23pub use write_once::WriteOnce;
24
25/// An implementation that accepts concrete types of chunked writes
26pub trait Storage {
27    const SPECIALIZES_BYTES: bool = false;
28    const SPECIALIZES_BYTES_MUT: bool = false;
29
30    /// Writes a slice of bytes into the storage
31    ///
32    /// The bytes MUST always be less than `remaining_capacity`.
33    fn put_slice(&mut self, bytes: &[u8]);
34
35    /// Tries to write into a uninit slice for the current storage
36    ///
37    /// If `false` is returned, the storage wasn't capable of this operation and a regular `put_*`
38    /// call should be used instead.
39    #[inline(always)]
40    fn put_uninit_slice<F, Error>(&mut self, payload_len: usize, f: F) -> Result<bool, Error>
41    where
42        F: FnOnce(&mut UninitSlice) -> Result<(), Error>,
43    {
44        // we can specialize on an empty payload
45        ensure!(payload_len == 0, Ok(false));
46
47        f(UninitSlice::new(&mut []))?;
48
49        Ok(true)
50    }
51
52    /// Returns the additional number of bytes that can be written to the storage
53    fn remaining_capacity(&self) -> usize;
54
55    /// Returns `true` if the storage will accept any additional bytes
56    #[inline]
57    fn has_remaining_capacity(&self) -> bool {
58        self.remaining_capacity() > 0
59    }
60
61    /// Writes [`Bytes`] into the storage
62    ///
63    /// Callers should check `SPECIALIZES_BYTES` before deciding to use this method. Otherwise, it
64    /// might be cheaper to copy a slice into the storage and then increment the offset.
65    #[inline]
66    fn put_bytes(&mut self, bytes: Bytes) {
67        self.put_slice(&bytes);
68    }
69
70    /// Writes [`BytesMut`] into the storage
71    ///
72    /// Callers should check `SPECIALIZES_BYTES_MUT` before deciding to use this method. Otherwise, it
73    /// might be cheaper to copy a slice into the storage and then increment the offset.
74    #[inline]
75    fn put_bytes_mut(&mut self, bytes: BytesMut) {
76        self.put_slice(&bytes);
77    }
78
79    /// Writes a reader [`Chunk`] into the storage
80    #[inline]
81    fn put_chunk(&mut self, chunk: Chunk) {
82        match chunk {
83            Chunk::Slice(v) => self.put_slice(v),
84            Chunk::Bytes(v) => self.put_bytes(v),
85            Chunk::BytesMut(v) => self.put_bytes_mut(v),
86        }
87    }
88
89    /// Limits the number of bytes that can be written to the storage
90    #[inline]
91    fn with_write_limit(&mut self, max_len: usize) -> Limit<'_, Self> {
92        Limit::new(self, max_len)
93    }
94
95    /// Tracks the number of bytes written to the storage
96    #[inline]
97    fn track_write(&mut self) -> Tracked<'_, Self> {
98        Tracked::new(self)
99    }
100
101    /// Only allows a single write into the storage. After that, no more writes are allowed.
102    ///
103    /// This can be used for very low latency scenarios where processing the single read is more
104    /// important than filling the entire storage with as much data as possible.
105    #[inline]
106    fn write_once(&mut self) -> WriteOnce<'_, Self> {
107        WriteOnce::new(self)
108    }
109}