Skip to content

Commit 80713e0

Browse files
committed
pr feedback
1 parent 0f61e93 commit 80713e0

File tree

4 files changed

+61
-62
lines changed

4 files changed

+61
-62
lines changed

quic/s2n-quic-core/src/buffer/duplex.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,17 @@
44
use super::{Error, Reader, Writer};
55
use crate::varint::VarInt;
66

7-
mod split;
7+
mod interposer;
88

9-
pub use split::Split;
9+
pub use interposer::Interposer;
1010

1111
/// A buffer that is capable of both reading and writing
1212
pub trait Duplex: Reader + Writer {}
1313

1414
impl<T: Reader + Writer> Duplex for T {}
1515

16-
/// A buffer that is capable of both skipping a write and read with a given amount.
16+
/// A buffer which can be advanced forward without reading or writing payloads. This
17+
/// is essentially a forward-only [`std::io::Seek`].
1718
///
1819
/// This can be used for scenarios where the buffer was written somewhere else but still needed to
1920
/// be tracked.

quic/s2n-quic-core/src/buffer/duplex/split.rs quic/s2n-quic-core/src/buffer/duplex/interposer.rs

+37-31
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,10 @@ use crate::{
1212
};
1313
use core::convert::Infallible;
1414

15-
/// A split duplex that tries to write as much as possible to `storage`, while falling back to
16-
/// `duplex`.
17-
pub struct Split<'a, S, D>
15+
/// A wrapper around an underlying buffer (`duplex`) which will prefer to read/write from a
16+
/// user-provided temporary buffer (`storage`). The underlying buffer (`duplex`)'s current
17+
/// position and total length are updated if needed.
18+
pub struct Interposer<'a, S, D>
1819
where
1920
S: writer::Storage + ?Sized,
2021
D: duplex::Skip<Error = Infallible> + ?Sized,
@@ -23,19 +24,24 @@ where
2324
duplex: &'a mut D,
2425
}
2526

26-
impl<'a, S, D> Split<'a, S, D>
27+
impl<'a, S, D> Interposer<'a, S, D>
2728
where
2829
S: writer::Storage + ?Sized,
2930
D: duplex::Skip<Error = Infallible> + ?Sized,
3031
{
3132
#[inline]
3233
pub fn new(storage: &'a mut S, duplex: &'a mut D) -> Self {
34+
debug_assert!(
35+
!storage.has_remaining_capacity() || duplex.buffer_is_empty(),
36+
"`duplex` should be drained into `storage` before constructing an Interposer"
37+
);
38+
3339
Self { storage, duplex }
3440
}
3541
}
3642

3743
/// Delegates to the inner Duplex
38-
impl<'a, S, D> reader::Storage for Split<'a, S, D>
44+
impl<'a, S, D> reader::Storage for Interposer<'a, S, D>
3945
where
4046
S: writer::Storage + ?Sized,
4147
D: duplex::Skip<Error = Infallible> + ?Sized,
@@ -78,7 +84,7 @@ where
7884
}
7985

8086
/// Delegates to the inner Duplex
81-
impl<'a, C, D> Reader for Split<'a, C, D>
87+
impl<'a, C, D> Reader for Interposer<'a, C, D>
8288
where
8389
C: writer::Storage + ?Sized,
8490
D: duplex::Skip<Error = Infallible> + ?Sized,
@@ -104,7 +110,7 @@ where
104110
}
105111
}
106112

107-
impl<'a, C, D> Writer for Split<'a, C, D>
113+
impl<'a, C, D> Writer for Interposer<'a, C, D>
108114
where
109115
C: writer::Storage + ?Sized,
110116
D: duplex::Skip<Error = Infallible> + ?Sized,
@@ -121,7 +127,7 @@ where
121127
// receive buffer, since that's what it stores
122128
let mut should_delegate = C::SPECIALIZES_BYTES || C::SPECIALIZES_BYTES_MUT;
123129

124-
// if the storage is empty then write into the duplex
130+
// if the storage has no space left then write into the duplex
125131
should_delegate |= !self.storage.has_remaining_capacity();
126132

127133
// if this packet is non-contiguous, then delegate to the wrapped writer
@@ -192,9 +198,9 @@ mod tests {
192198
// limit the storage capacity so we force writing into the duplex
193199
let mut storage = storage.with_write_limit(1);
194200

195-
let mut split = Split::new(&mut storage, &mut duplex);
201+
let mut interposer = Interposer::new(&mut storage, &mut duplex);
196202

197-
split.read_from(&mut reader).unwrap();
203+
interposer.read_from(&mut reader).unwrap();
198204
}
199205

200206
// the storage was too small so we delegated to duplex
@@ -220,15 +226,15 @@ mod tests {
220226

221227
let mut storage: Vec<u8> = vec![];
222228

223-
let mut split = Split::new(&mut storage, &mut duplex);
229+
let mut interposer = Interposer::new(&mut storage, &mut duplex);
224230

225-
split.read_from(&mut reader).unwrap();
231+
interposer.read_from(&mut reader).unwrap();
226232

227233
// make sure we consumed the reader
228234
assert_eq!(reader.current_offset().as_u64(), 10);
229235

230-
assert_eq!(split.current_offset().as_u64(), 0);
231-
assert_eq!(split.buffered_len(), 0);
236+
assert_eq!(interposer.current_offset().as_u64(), 0);
237+
assert_eq!(interposer.buffered_len(), 0);
232238

233239
// make sure we didn't write to the storage, even if we had capacity, since the
234240
// current_offset doesn't match
@@ -241,15 +247,15 @@ mod tests {
241247

242248
let mut storage: Vec<u8> = vec![];
243249

244-
let mut split = Split::new(&mut storage, &mut duplex);
250+
let mut interposer = Interposer::new(&mut storage, &mut duplex);
245251

246-
split.read_from(&mut reader).unwrap();
252+
interposer.read_from(&mut reader).unwrap();
247253

248254
// make sure we consumed the reader
249255
assert_eq!(reader.current_offset().as_u64(), 10);
250256

251-
assert_eq!(split.current_offset().as_u64(), 10);
252-
assert_eq!(split.buffered_len(), 0);
257+
assert_eq!(interposer.current_offset().as_u64(), 10);
258+
assert_eq!(interposer.buffered_len(), 0);
253259

254260
// make sure we copied the entire reader
255261
assert_eq!(storage.len(), 10);
@@ -265,9 +271,9 @@ mod tests {
265271

266272
let mut storage: Vec<u8> = vec![];
267273

268-
let mut split = Split::new(&mut storage, &mut duplex);
274+
let mut interposer = Interposer::new(&mut storage, &mut duplex);
269275

270-
split.read_from(&mut reader).unwrap();
276+
interposer.read_from(&mut reader).unwrap();
271277

272278
assert_eq!(storage.len(), 10);
273279
assert_eq!(duplex.current_offset().as_u64(), 10);
@@ -283,19 +289,19 @@ mod tests {
283289

284290
let mut storage = writer::storage::Empty;
285291

286-
let mut split = Split::new(&mut storage, &mut duplex);
292+
let mut interposer = Interposer::new(&mut storage, &mut duplex);
287293

288-
split.read_from(&mut reader).unwrap();
294+
interposer.read_from(&mut reader).unwrap();
289295

290-
assert_eq!(split.current_offset().as_u64(), 0);
291-
assert_eq!(split.buffered_len(), 10);
296+
assert_eq!(interposer.current_offset().as_u64(), 0);
297+
assert_eq!(interposer.buffered_len(), 10);
292298

293-
checker.read_from(&mut split).unwrap();
299+
checker.read_from(&mut interposer).unwrap();
294300

295-
assert_eq!(split.current_offset().as_u64(), 10);
296-
assert!(split.buffer_is_empty());
297-
assert_eq!(split.buffered_len(), 0);
298-
assert!(split.is_consumed());
301+
assert_eq!(interposer.current_offset().as_u64(), 10);
302+
assert!(interposer.buffer_is_empty());
303+
assert_eq!(interposer.buffered_len(), 0);
304+
assert!(interposer.is_consumed());
299305
}
300306

301307
#[test]
@@ -308,9 +314,9 @@ mod tests {
308314
{
309315
let mut storage = storage.with_write_limit(9);
310316

311-
let mut split = Split::new(&mut storage, &mut duplex);
317+
let mut interposer = Interposer::new(&mut storage, &mut duplex);
312318

313-
split.read_from(&mut reader).unwrap();
319+
interposer.read_from(&mut reader).unwrap();
314320
}
315321

316322
// the storage was at least half the reader

quic/s2n-quic-core/src/buffer/reader/limit.rs

+13-16
Original file line numberDiff line numberDiff line change
@@ -13,19 +13,16 @@ use crate::{
1313
///
1414
/// This can be used for applying back pressure to the reader with flow control.
1515
pub struct Limit<'a, R: Reader + ?Sized> {
16-
buffered_len: usize,
16+
len: usize,
1717
reader: &'a mut R,
1818
}
1919

2020
impl<'a, R: Reader + ?Sized> Limit<'a, R> {
2121
#[inline]
2222
pub fn new(reader: &'a mut R, max_buffered_len: usize) -> Self {
23-
let buffered_len = max_buffered_len.min(reader.buffered_len());
23+
let len = max_buffered_len.min(reader.buffered_len());
2424

25-
Self {
26-
buffered_len,
27-
reader,
28-
}
25+
Self { len, reader }
2926
}
3027
}
3128

@@ -34,17 +31,17 @@ impl<'a, R: Reader + ?Sized> Storage for Limit<'a, R> {
3431

3532
#[inline]
3633
fn buffered_len(&self) -> usize {
37-
self.buffered_len
34+
self.len
3835
}
3936

4037
#[inline]
4138
fn read_chunk(&mut self, watermark: usize) -> Result<Chunk, Self::Error> {
42-
let watermark = self.buffered_len.min(watermark);
39+
let watermark = self.len.min(watermark);
4340
let chunk = self.reader.read_chunk(watermark)?;
4441
unsafe {
45-
assume!(chunk.len() <= self.buffered_len);
42+
assume!(chunk.len() <= self.len);
4643
}
47-
self.buffered_len -= chunk.len();
44+
self.len -= chunk.len();
4845
Ok(chunk)
4946
}
5047

@@ -53,14 +50,14 @@ impl<'a, R: Reader + ?Sized> Storage for Limit<'a, R> {
5350
where
5451
Dest: writer::Storage + ?Sized,
5552
{
56-
let mut dest = dest.with_write_limit(self.buffered_len);
53+
let mut dest = dest.with_write_limit(self.len);
5754
let mut dest = dest.track_write();
5855
let chunk = self.reader.partial_copy_into(&mut dest)?;
5956
let len = dest.written_len() + chunk.len();
6057
unsafe {
61-
assume!(len <= self.buffered_len);
58+
assume!(len <= self.len);
6259
}
63-
self.buffered_len -= len;
60+
self.len -= len;
6461
Ok(chunk)
6562
}
6663

@@ -69,14 +66,14 @@ impl<'a, R: Reader + ?Sized> Storage for Limit<'a, R> {
6966
where
7067
Dest: writer::Storage + ?Sized,
7168
{
72-
let mut dest = dest.with_write_limit(self.buffered_len);
69+
let mut dest = dest.with_write_limit(self.len);
7370
let mut dest = dest.track_write();
7471
self.reader.copy_into(&mut dest)?;
7572
let len = dest.written_len();
7673
unsafe {
77-
assume!(len <= self.buffered_len);
74+
assume!(len <= self.len);
7875
}
79-
self.buffered_len -= len;
76+
self.len -= len;
8077
Ok(())
8178
}
8279
}

quic/s2n-quic-core/src/buffer/reader/storage/io_slice.rs

+7-12
Original file line numberDiff line numberDiff line change
@@ -45,12 +45,10 @@ where
4545
};
4646
}
4747

48-
// skip over any empty slices
49-
let buf = &buf[first_non_empty..=last_non_empty];
50-
51-
unsafe {
52-
assume!(!buf.is_empty());
53-
}
48+
let buf = unsafe {
49+
// Safety: we checked above that this range is at least 1 element and is in-bounds
50+
buf.get_unchecked(first_non_empty..=last_non_empty)
51+
};
5452

5553
let mut slice = Self {
5654
len,
@@ -115,25 +113,22 @@ where
115113
// head can be consumed and the watermark still has capacity
116114
Ordering::Less => {
117115
let head = core::mem::take(&mut self.head);
118-
unsafe {
119-
assume!(!self.buf.is_empty());
120-
}
121116
self.advance_buf();
122117
self.sub_len(head.len());
123118
ControlFlow::Continue(head.into())
124119
}
125120
// head can be consumed and the watermark is filled
126121
Ordering::Equal => {
127122
let head = core::mem::take(&mut self.head);
128-
unsafe {
129-
assume!(!self.buf.is_empty());
130-
}
131123
self.advance_buf();
132124
self.sub_len(head.len());
133125
ControlFlow::Break(head.into())
134126
}
135127
// head is partially consumed and the watermark is filled
136128
Ordering::Greater => {
129+
unsafe {
130+
assume!(self.head.len() >= watermark);
131+
}
137132
let (head, tail) = self.head.split_at(watermark);
138133
self.head = tail;
139134
self.sub_len(head.len());

0 commit comments

Comments
 (0)