s2n_quic_core/slice/deque/
pair.rs

1// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2// SPDX-License-Identifier: Apache-2.0
3
4use core::{mem::MaybeUninit, ops};
5
6pub struct Pair<Part> {
7    parts: [Part; 2],
8}
9
10impl<Part> From<(Part, Part)> for Pair<Part> {
11    #[inline]
12    fn from((head, tail): (Part, Part)) -> Self {
13        Self {
14            parts: [head, tail],
15        }
16    }
17}
18
19impl<Part> From<Pair<Part>> for (Part, Part) {
20    #[inline]
21    fn from(pair: Pair<Part>) -> (Part, Part) {
22        let [head, tail] = pair.parts;
23        (head, tail)
24    }
25}
26
27impl<T> Pair<T> {
28    #[inline]
29    pub fn map<F, U>(self, mut f: F) -> Pair<U>
30    where
31        F: FnMut(T) -> U,
32    {
33        let [head, tail] = self.parts;
34        let head = f(head);
35        let tail = f(tail);
36        Pair {
37            parts: [head, tail],
38        }
39    }
40}
41
42impl<Part, T> Pair<Part>
43where
44    Part: ops::Deref<Target = [T]>,
45{
46    #[inline]
47    pub fn get(&self, mut index: usize) -> Option<&T> {
48        for part in &self.parts {
49            if let Some(v) = part.get(index) {
50                return Some(v);
51            };
52            index -= part.len();
53        }
54
55        None
56    }
57
58    #[inline]
59    pub fn iter<'a>(&'a self) -> impl Iterator<Item = &'a T>
60    where
61        T: 'a,
62    {
63        self.parts.iter().flat_map(|p| p.iter())
64    }
65}
66
67impl<Part, T> Pair<Part>
68where
69    Part: ops::DerefMut<Target = [T]>,
70{
71    #[inline]
72    pub fn get_mut(&mut self, mut index: usize) -> Option<&mut T> {
73        for part in &mut self.parts {
74            let part_len = part.len();
75            if let Some(v) = part.get_mut(index) {
76                return Some(v);
77            };
78            index -= part_len;
79        }
80
81        None
82    }
83
84    #[inline]
85    pub fn iter_mut<'a>(&'a mut self) -> impl Iterator<Item = &'a mut T> + 'a
86    where
87        T: 'a,
88    {
89        self.parts.iter_mut().flat_map(|p| p.iter_mut())
90    }
91}
92
93impl<'a, T> Pair<&'a [MaybeUninit<T>]> {
94    /// # Safety
95    ///
96    /// Callers should guarantee the memory in the pair is initialized
97    #[inline]
98    pub unsafe fn assume_init_ref(self) -> Pair<&'a [T]> {
99        self.map(|slice| {
100            // SAFETY: similar justification for assume_init_mut
101            &*(slice as *const [MaybeUninit<T>] as *const [T])
102        })
103    }
104}
105
106impl<'a, T> Pair<&'a mut [MaybeUninit<T>]> {
107    /// # Safety
108    ///
109    /// Callers should guarantee the memory in the pair is initialized
110    #[inline]
111    pub unsafe fn assume_init_mut(self) -> Pair<&'a mut [T]> {
112        self.map(|slice| {
113            // SAFETY: casting `slice` to a `*mut [T]` is safe since the caller guarantees that
114            // `slice` is initialized, and `MaybeUninit` is guaranteed to have the same layout as `T`.
115            // The pointer obtained is valid since it refers to memory owned by `slice` which is a
116            // reference and thus guaranteed to be valid for reads and writes.
117            &mut *(slice as *mut [MaybeUninit<T>] as *mut [T])
118        })
119    }
120}
121
122#[cfg(feature = "std")]
123mod std_ {
124    use super::*;
125    use std::io::{IoSlice, IoSliceMut};
126
127    impl<'a> Pair<&'a [MaybeUninit<u8>]> {
128        /// # Safety
129        ///
130        /// Callers should guarantee the memory in the pair is initialized
131        #[inline]
132        pub unsafe fn assume_init_io_slice(self) -> Pair<IoSlice<'a>> {
133            self.assume_init_ref().map(IoSlice::new)
134        }
135    }
136
137    #[cfg(feature = "std")]
138    impl<'a> Pair<&'a mut [MaybeUninit<u8>]> {
139        /// # Safety
140        ///
141        /// Callers should guarantee the memory in the pair is initialized
142        #[inline]
143        pub unsafe fn assume_init_io_slice_mut(self) -> Pair<IoSliceMut<'a>> {
144            self.assume_init_mut().map(IoSliceMut::new)
145        }
146    }
147}
148
149#[cfg(feature = "alloc")]
150mod alloc_ {
151    use super::*;
152    use crate::buffer::{reader, writer};
153    use bytes::buf::UninitSlice;
154
155    impl<S: reader::Storage> reader::Storage for Pair<S> {
156        type Error = S::Error;
157
158        #[inline]
159        fn buffered_len(&self) -> usize {
160            self.parts[0].buffered_len() + self.parts[1].buffered_len()
161        }
162
163        #[inline]
164        fn read_chunk(
165            &mut self,
166            watermark: usize,
167        ) -> Result<reader::storage::Chunk<'_>, Self::Error> {
168            if !self.parts[0].buffer_is_empty() {
169                self.parts[0].read_chunk(watermark)
170            } else {
171                self.parts[1].read_chunk(watermark)
172            }
173        }
174
175        #[inline]
176        fn partial_copy_into<Dest>(
177            &mut self,
178            dest: &mut Dest,
179        ) -> Result<reader::storage::Chunk<'_>, Self::Error>
180        where
181            Dest: crate::buffer::writer::Storage + ?Sized,
182        {
183            if self.parts[0].buffered_len() >= dest.remaining_capacity() {
184                self.parts[0].partial_copy_into(dest)
185            } else {
186                self.parts[0].copy_into(dest)?;
187                self.parts[1].partial_copy_into(dest)
188            }
189        }
190
191        #[inline]
192        fn copy_into<Dest>(&mut self, dest: &mut Dest) -> Result<(), Self::Error>
193        where
194            Dest: writer::Storage + ?Sized,
195        {
196            self.parts[0].copy_into(dest)?;
197            self.parts[1].copy_into(dest)
198        }
199    }
200
201    impl<Part> Pair<Part>
202    where
203        Part: reader::Storage,
204    {
205        #[inline]
206        pub fn reader_slice(&mut self) -> &[Part] {
207            let [head, tail] = &self.parts;
208            match (!head.buffer_is_empty(), !tail.buffer_is_empty()) {
209                (true, true) => &self.parts,
210                (true, false) => &self.parts[..1],
211                (false, true) => &self.parts[1..],
212                (false, false) => &[],
213            }
214        }
215
216        #[inline]
217        pub fn reader_slice_mut(&mut self) -> &mut [Part] {
218            let [head, tail] = &self.parts;
219            match (!head.buffer_is_empty(), !tail.buffer_is_empty()) {
220                (true, true) => &mut self.parts,
221                (true, false) => &mut self.parts[..1],
222                (false, true) => &mut self.parts[1..],
223                (false, false) => &mut [],
224            }
225        }
226    }
227
228    impl<S: writer::Storage> writer::Storage for Pair<S> {
229        #[inline]
230        fn put_slice(&mut self, mut bytes: &[u8]) {
231            use reader::storage::Infallible;
232
233            debug_assert!(bytes.len() <= self.remaining_capacity());
234
235            bytes.infallible_copy_into(&mut self.parts[0]);
236            bytes.infallible_copy_into(&mut self.parts[1]);
237        }
238
239        #[inline]
240        fn put_uninit_slice<F, Error>(&mut self, payload_len: usize, f: F) -> Result<bool, Error>
241        where
242            F: FnOnce(&mut UninitSlice) -> Result<(), Error>,
243        {
244            if self.parts[0].has_remaining_capacity() {
245                self.parts[0].put_uninit_slice(payload_len, f)
246            } else {
247                self.parts[1].put_uninit_slice(payload_len, f)
248            }
249        }
250
251        #[inline]
252        fn remaining_capacity(&self) -> usize {
253            self.parts[0].remaining_capacity() + self.parts[1].remaining_capacity()
254        }
255    }
256
257    impl<Part> Pair<Part>
258    where
259        Part: writer::Storage,
260    {
261        #[inline]
262        pub fn writer_slice(&mut self) -> &[Part] {
263            let [head, tail] = &self.parts;
264            match (head.has_remaining_capacity(), tail.has_remaining_capacity()) {
265                (true, true) => &self.parts,
266                (true, false) => &self.parts[..1],
267                (false, true) => &self.parts[1..],
268                (false, false) => &[],
269            }
270        }
271
272        #[inline]
273        pub fn writer_slice_mut(&mut self) -> &mut [Part] {
274            let [head, tail] = &self.parts;
275            match (head.has_remaining_capacity(), tail.has_remaining_capacity()) {
276                (true, true) => &mut self.parts,
277                (true, false) => &mut self.parts[..1],
278                (false, true) => &mut self.parts[1..],
279                (false, false) => &mut [],
280            }
281        }
282    }
283}