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}