Skip to main content

quinn_proto\connection/
assembler.rs

1use std::{
2    cmp::Ordering,
3    collections::{BinaryHeap, binary_heap::PeekMut},
4    mem,
5};
6
7use bytes::{Buf, Bytes, BytesMut};
8
9use crate::range_set::RangeSet;
10
11/// Helper to assemble unordered stream frames into an ordered stream
12#[derive(Debug, Default)]
13pub(super) struct Assembler {
14    state: State,
15    data: BinaryHeap<Buffer>,
16    /// Total number of buffered bytes, including duplicates in ordered mode.
17    buffered: usize,
18    /// Estimated number of allocated bytes, will never be less than `buffered`.
19    allocated: usize,
20    /// Number of bytes read by the application. When only ordered reads have been used, this is the
21    /// length of the contiguous prefix of the stream which has been consumed by the application,
22    /// aka the stream offset.
23    bytes_read: u64,
24    end: u64,
25}
26
27impl Assembler {
28    pub(super) fn new() -> Self {
29        Self::default()
30    }
31
32    /// Reset to the initial state
33    pub(super) fn reinit(&mut self) {
34        let old_data = mem::take(&mut self.data);
35        *self = Self::default();
36        self.data = old_data;
37        self.data.clear();
38    }
39
40    pub(super) fn ensure_ordering(&mut self, ordered: bool) -> Result<(), IllegalOrderedRead> {
41        if ordered && !self.state.is_ordered() {
42            return Err(IllegalOrderedRead);
43        } else if !ordered && self.state.is_ordered() {
44            // Enter unordered mode
45            if !self.data.is_empty() {
46                // Get rid of possible duplicates
47                self.defragment();
48            }
49            let mut recvd = RangeSet::new();
50            recvd.insert(0..self.bytes_read);
51            for chunk in &self.data {
52                recvd.insert(chunk.offset..chunk.offset + chunk.bytes.len() as u64);
53            }
54            self.state = State::Unordered { recvd };
55        }
56        Ok(())
57    }
58
59    /// Get the the next chunk
60    pub(super) fn read(&mut self, max_length: usize, ordered: bool) -> Option<Chunk> {
61        loop {
62            let mut chunk = self.data.peek_mut()?;
63
64            if ordered {
65                if chunk.offset > self.bytes_read {
66                    // Next chunk is after current read index
67                    return None;
68                } else if (chunk.offset + chunk.bytes.len() as u64) <= self.bytes_read {
69                    // Next chunk is useless as the read index is beyond its end
70                    self.buffered -= chunk.bytes.len();
71                    self.allocated -= chunk.allocation_size;
72                    PeekMut::pop(chunk);
73                    continue;
74                }
75
76                // Determine `start` and `len` of the slice of useful data in chunk
77                let start = (self.bytes_read - chunk.offset) as usize;
78                if start > 0 {
79                    chunk.bytes.advance(start);
80                    chunk.offset += start as u64;
81                    self.buffered -= start;
82                }
83            }
84
85            return Some(if max_length < chunk.bytes.len() {
86                self.bytes_read += max_length as u64;
87                let offset = chunk.offset;
88                chunk.offset += max_length as u64;
89                self.buffered -= max_length;
90                Chunk::new(offset, chunk.bytes.split_to(max_length))
91            } else {
92                self.bytes_read += chunk.bytes.len() as u64;
93                self.buffered -= chunk.bytes.len();
94                self.allocated -= chunk.allocation_size;
95                let chunk = PeekMut::pop(chunk);
96                Chunk::new(chunk.offset, chunk.bytes)
97            });
98        }
99    }
100
101    /// Copy fragmented chunk data to new chunks backed by a single buffer
102    ///
103    /// This makes sure we're not unnecessarily holding on to many larger allocations.
104    /// We merge contiguous chunks in the process of doing so.
105    fn defragment(&mut self) {
106        let new = BinaryHeap::with_capacity(self.data.len());
107        let old = mem::replace(&mut self.data, new);
108        let mut buffers = old.into_sorted_vec();
109        self.buffered = 0;
110        let mut fragmented_buffered = 0;
111        let mut offset = 0;
112        for chunk in buffers.iter_mut().rev() {
113            chunk.try_mark_defragment(offset);
114            let size = chunk.bytes.len();
115            offset = chunk.offset + size as u64;
116            self.buffered += size;
117            if !chunk.defragmented {
118                fragmented_buffered += size;
119            }
120        }
121        self.allocated = self.buffered;
122        let mut buffer = BytesMut::with_capacity(fragmented_buffered);
123        let mut offset = 0;
124        for chunk in buffers.into_iter().rev() {
125            if chunk.defragmented {
126                // bytes might be empty after try_mark_defragment
127                if !chunk.bytes.is_empty() {
128                    self.data.push(chunk);
129                }
130                continue;
131            }
132            // Overlap is resolved by try_mark_defragment
133            if chunk.offset != offset + (buffer.len() as u64) {
134                if !buffer.is_empty() {
135                    self.data
136                        .push(Buffer::new_defragmented(offset, buffer.split().freeze()));
137                }
138                offset = chunk.offset;
139            }
140            buffer.extend_from_slice(&chunk.bytes);
141        }
142        if !buffer.is_empty() {
143            self.data
144                .push(Buffer::new_defragmented(offset, buffer.split().freeze()));
145        }
146    }
147
148    // Note: If a packet contains many frames from the same stream, the estimated over-allocation
149    // will be much higher because we are counting the same allocation multiple times.
150    pub(super) fn insert(
151        &mut self,
152        mut offset: u64,
153        mut bytes: Bytes,
154        allocation_size: usize,
155    ) -> Result<(), TooManyChunks> {
156        debug_assert!(
157            bytes.len() <= allocation_size,
158            "allocation_size less than bytes.len(): {:?} < {:?}",
159            allocation_size,
160            bytes.len()
161        );
162        self.end = self.end.max(offset + bytes.len() as u64);
163        if let State::Unordered { ref mut recvd } = self.state {
164            // Discard duplicate data
165            for duplicate in recvd.replace(offset..offset + bytes.len() as u64) {
166                if duplicate.start > offset {
167                    let buffer = Buffer::new(
168                        offset,
169                        bytes.split_to((duplicate.start - offset) as usize),
170                        allocation_size,
171                    );
172                    self.buffered += buffer.bytes.len();
173                    self.allocated += buffer.allocation_size;
174                    self.data.push(buffer);
175                    offset = duplicate.start;
176                }
177                bytes.advance((duplicate.end - offset) as usize);
178                offset = duplicate.end;
179            }
180        } else if offset < self.bytes_read {
181            if (offset + bytes.len() as u64) <= self.bytes_read {
182                return Ok(());
183            } else {
184                let diff = self.bytes_read - offset;
185                offset += diff;
186                bytes.advance(diff as usize);
187            }
188        }
189
190        if bytes.is_empty() {
191            return Ok(());
192        }
193        let buffer = Buffer::new(offset, bytes, allocation_size);
194        self.buffered += buffer.bytes.len();
195        self.allocated += buffer.allocation_size;
196        self.data.push(buffer);
197        // `self.buffered` also counts duplicate bytes, therefore we use
198        // `self.end - self.bytes_read` as an upper bound of buffered unique
199        // bytes. This will cause a defragmentation if the amount of duplicate
200        // bytes exceedes a proportion of the receive window size.
201        let buffered = self.buffered.min((self.end - self.bytes_read) as usize);
202        let over_allocation = self.allocated - buffered;
203        // Rationale: on the one hand, we want to defragment rarely, ideally never
204        // in non-pathological scenarios. However, a pathological or malicious
205        // peer could send us one-byte frames, and since we use reference-counted
206        // buffers in order to prevent copying, this could result in keeping a lot
207        // of memory allocated. This limits over-allocation in proportion to the
208        // buffered data. The constants are chosen somewhat arbitrarily and try to
209        // balance between defragmentation overhead and over-allocation.
210        let threshold = 32768.max(buffered * 3 / 2);
211        if over_allocation > threshold {
212            self.defragment();
213            // ngtcp2 uses a threshold of 4000 -- try to be a little more conservative?
214            if self.data.len() > 1024 {
215                return Err(TooManyChunks);
216            }
217        }
218
219        Ok(())
220    }
221
222    /// Number of bytes consumed by the application
223    pub(super) fn bytes_read(&self) -> u64 {
224        self.bytes_read
225    }
226
227    /// Discard all buffered data
228    pub(super) fn clear(&mut self) {
229        self.data.clear();
230        self.buffered = 0;
231        self.allocated = 0;
232    }
233}
234
235/// A chunk of data from the receive stream
236#[derive(Debug, PartialEq, Eq)]
237pub struct Chunk {
238    /// The offset in the stream
239    pub offset: u64,
240    /// The contents of the chunk
241    pub bytes: Bytes,
242}
243
244impl Chunk {
245    fn new(offset: u64, bytes: Bytes) -> Self {
246        Self { offset, bytes }
247    }
248}
249
250#[derive(Debug, Eq)]
251struct Buffer {
252    offset: u64,
253    bytes: Bytes,
254    /// Size of the allocation behind `bytes`, if `defragmented == false`.
255    /// Otherwise this will be set to `bytes.len()` by `try_mark_defragment`.
256    /// Will never be less than `bytes.len()`.
257    allocation_size: usize,
258    defragmented: bool,
259}
260
261impl Buffer {
262    /// Constructs a new fragmented Buffer
263    fn new(offset: u64, bytes: Bytes, allocation_size: usize) -> Self {
264        Self {
265            offset,
266            bytes,
267            allocation_size,
268            defragmented: false,
269        }
270    }
271
272    /// Constructs a new defragmented Buffer
273    fn new_defragmented(offset: u64, bytes: Bytes) -> Self {
274        let allocation_size = bytes.len();
275        Self {
276            offset,
277            bytes,
278            allocation_size,
279            defragmented: true,
280        }
281    }
282
283    /// Discards data before `offset` and flags `self` as defragmented if it has good utilization
284    fn try_mark_defragment(&mut self, offset: u64) {
285        let duplicate = offset.saturating_sub(self.offset) as usize;
286        self.offset = self.offset.max(offset);
287        if duplicate >= self.bytes.len() {
288            // All bytes are duplicate
289            self.bytes = Bytes::new();
290            self.defragmented = true;
291            self.allocation_size = 0;
292            return;
293        }
294        self.bytes.advance(duplicate);
295        // Make sure that fragmented buffers with high utilization become defragmented and
296        // defragmented buffers remain defragmented
297        self.defragmented = self.defragmented || self.bytes.len() * 6 / 5 >= self.allocation_size;
298        if self.defragmented {
299            // Make sure that defragmented buffers do not contribute to over-allocation
300            self.allocation_size = self.bytes.len();
301        }
302    }
303}
304
305impl Ord for Buffer {
306    // Invert ordering based on offset (max-heap, min offset first),
307    // prioritize longer chunks at the same offset.
308    fn cmp(&self, other: &Self) -> Ordering {
309        self.offset
310            .cmp(&other.offset)
311            .reverse()
312            .then(self.bytes.len().cmp(&other.bytes.len()))
313    }
314}
315
316impl PartialOrd for Buffer {
317    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
318        Some(self.cmp(other))
319    }
320}
321
322impl PartialEq for Buffer {
323    fn eq(&self, other: &Self) -> bool {
324        (self.offset, self.bytes.len()) == (other.offset, other.bytes.len())
325    }
326}
327
328#[derive(Debug, Default)]
329enum State {
330    #[default]
331    Ordered,
332    Unordered {
333        /// The set of offsets that have been received from the peer, including portions not yet
334        /// read by the application.
335        recvd: RangeSet,
336    },
337}
338
339impl State {
340    fn is_ordered(&self) -> bool {
341        matches!(self, Self::Ordered)
342    }
343}
344
345/// Error indicating that an ordered read was performed on a stream after an unordered read
346#[derive(Debug)]
347pub struct IllegalOrderedRead;
348
349/// Error indicating that too many chunks are buffered due to maliciously small/gapped frames
350#[derive(Debug)]
351pub(crate) struct TooManyChunks;
352
353#[cfg(test)]
354mod test {
355    use super::*;
356    use assert_matches::assert_matches;
357
358    #[test]
359    fn assemble_ordered() {
360        let mut x = Assembler::new();
361        assert_matches!(next(&mut x, 32), None);
362        x.insert(0, Bytes::from_static(b"123"), 3).unwrap();
363        assert_matches!(next(&mut x, 1), Some(ref y) if &y[..] == b"1");
364        assert_matches!(next(&mut x, 3), Some(ref y) if &y[..] == b"23");
365        x.insert(3, Bytes::from_static(b"456"), 3).unwrap();
366        assert_matches!(next(&mut x, 32), Some(ref y) if &y[..] == b"456");
367        x.insert(6, Bytes::from_static(b"789"), 3).unwrap();
368        x.insert(9, Bytes::from_static(b"10"), 2).unwrap();
369        assert_matches!(next(&mut x, 32), Some(ref y) if &y[..] == b"789");
370        assert_matches!(next(&mut x, 32), Some(ref y) if &y[..] == b"10");
371        assert_matches!(next(&mut x, 32), None);
372    }
373
374    #[test]
375    fn assemble_unordered() {
376        let mut x = Assembler::new();
377        x.ensure_ordering(false).unwrap();
378        x.insert(3, Bytes::from_static(b"456"), 3).unwrap();
379        assert_matches!(next(&mut x, 32), None);
380        x.insert(0, Bytes::from_static(b"123"), 3).unwrap();
381        assert_matches!(next(&mut x, 32), Some(ref y) if &y[..] == b"123");
382        assert_matches!(next(&mut x, 32), Some(ref y) if &y[..] == b"456");
383        assert_matches!(next(&mut x, 32), None);
384    }
385
386    #[test]
387    fn assemble_duplicate() {
388        let mut x = Assembler::new();
389        x.insert(0, Bytes::from_static(b"123"), 3).unwrap();
390        x.insert(0, Bytes::from_static(b"123"), 3).unwrap();
391        assert_matches!(next(&mut x, 32), Some(ref y) if &y[..] == b"123");
392        assert_matches!(next(&mut x, 32), None);
393    }
394
395    #[test]
396    fn assemble_duplicate_compact() {
397        let mut x = Assembler::new();
398        x.insert(0, Bytes::from_static(b"123"), 3).unwrap();
399        x.insert(0, Bytes::from_static(b"123"), 3).unwrap();
400        x.defragment();
401        assert_matches!(next(&mut x, 32), Some(ref y) if &y[..] == b"123");
402        assert_matches!(next(&mut x, 32), None);
403    }
404
405    #[test]
406    fn assemble_contained() {
407        let mut x = Assembler::new();
408        x.insert(0, Bytes::from_static(b"12345"), 5).unwrap();
409        x.insert(1, Bytes::from_static(b"234"), 3).unwrap();
410        assert_matches!(next(&mut x, 32), Some(ref y) if &y[..] == b"12345");
411        assert_matches!(next(&mut x, 32), None);
412    }
413
414    #[test]
415    fn assemble_contained_compact() {
416        let mut x = Assembler::new();
417        x.insert(0, Bytes::from_static(b"12345"), 5).unwrap();
418        x.insert(1, Bytes::from_static(b"234"), 3).unwrap();
419        x.defragment();
420        assert_matches!(next(&mut x, 32), Some(ref y) if &y[..] == b"12345");
421        assert_matches!(next(&mut x, 32), None);
422    }
423
424    #[test]
425    fn assemble_contains() {
426        let mut x = Assembler::new();
427        x.insert(1, Bytes::from_static(b"234"), 3).unwrap();
428        x.insert(0, Bytes::from_static(b"12345"), 5).unwrap();
429        assert_matches!(next(&mut x, 32), Some(ref y) if &y[..] == b"12345");
430        assert_matches!(next(&mut x, 32), None);
431    }
432
433    #[test]
434    fn assemble_contains_compact() {
435        let mut x = Assembler::new();
436        x.insert(1, Bytes::from_static(b"234"), 3).unwrap();
437        x.insert(0, Bytes::from_static(b"12345"), 5).unwrap();
438        x.defragment();
439        assert_matches!(next(&mut x, 32), Some(ref y) if &y[..] == b"12345");
440        assert_matches!(next(&mut x, 32), None);
441    }
442
443    #[test]
444    fn assemble_overlapping() {
445        let mut x = Assembler::new();
446        x.insert(0, Bytes::from_static(b"123"), 3).unwrap();
447        x.insert(1, Bytes::from_static(b"234"), 3).unwrap();
448        assert_matches!(next(&mut x, 32), Some(ref y) if &y[..] == b"123");
449        assert_matches!(next(&mut x, 32), Some(ref y) if &y[..] == b"4");
450        assert_matches!(next(&mut x, 32), None);
451    }
452
453    #[test]
454    fn assemble_overlapping_compact() {
455        let mut x = Assembler::new();
456        x.insert(0, Bytes::from_static(b"123"), 4).unwrap();
457        x.insert(1, Bytes::from_static(b"234"), 4).unwrap();
458        x.defragment();
459        assert_matches!(next(&mut x, 32), Some(ref y) if &y[..] == b"1234");
460        assert_matches!(next(&mut x, 32), None);
461    }
462
463    #[test]
464    fn assemble_complex() {
465        let mut x = Assembler::new();
466        x.insert(0, Bytes::from_static(b"1"), 1).unwrap();
467        x.insert(2, Bytes::from_static(b"3"), 1).unwrap();
468        x.insert(4, Bytes::from_static(b"5"), 1).unwrap();
469        x.insert(0, Bytes::from_static(b"123456"), 6).unwrap();
470        assert_matches!(next(&mut x, 32), Some(ref y) if &y[..] == b"123456");
471        assert_matches!(next(&mut x, 32), None);
472    }
473
474    #[test]
475    fn assemble_complex_compact() {
476        let mut x = Assembler::new();
477        x.insert(0, Bytes::from_static(b"1"), 1).unwrap();
478        x.insert(2, Bytes::from_static(b"3"), 1).unwrap();
479        x.insert(4, Bytes::from_static(b"5"), 1).unwrap();
480        x.insert(0, Bytes::from_static(b"123456"), 6).unwrap();
481        x.defragment();
482        assert_matches!(next(&mut x, 32), Some(ref y) if &y[..] == b"123456");
483        assert_matches!(next(&mut x, 32), None);
484    }
485
486    #[test]
487    fn assemble_old() {
488        let mut x = Assembler::new();
489        x.insert(0, Bytes::from_static(b"1234"), 4).unwrap();
490        assert_matches!(next(&mut x, 32), Some(ref y) if &y[..] == b"1234");
491        x.insert(0, Bytes::from_static(b"1234"), 4).unwrap();
492        assert_matches!(next(&mut x, 32), None);
493    }
494
495    #[test]
496    fn compact() {
497        let mut x = Assembler::new();
498        x.insert(0, Bytes::from_static(b"abc"), 4).unwrap();
499        x.insert(3, Bytes::from_static(b"def"), 4).unwrap();
500        x.insert(9, Bytes::from_static(b"jkl"), 4).unwrap();
501        x.insert(12, Bytes::from_static(b"mno"), 4).unwrap();
502        x.defragment();
503        assert_eq!(
504            next_unordered(&mut x),
505            Chunk::new(0, Bytes::from_static(b"abcdef"))
506        );
507        assert_eq!(
508            next_unordered(&mut x),
509            Chunk::new(9, Bytes::from_static(b"jklmno"))
510        );
511    }
512
513    #[test]
514    fn defrag_with_missing_prefix() {
515        let mut x = Assembler::new();
516        x.insert(3, Bytes::from_static(b"def"), 3).unwrap();
517        x.defragment();
518        assert_eq!(
519            next_unordered(&mut x),
520            Chunk::new(3, Bytes::from_static(b"def"))
521        );
522    }
523
524    #[test]
525    fn defrag_read_chunk() {
526        let mut x = Assembler::new();
527        x.insert(3, Bytes::from_static(b"def"), 4).unwrap();
528        x.insert(0, Bytes::from_static(b"abc"), 4).unwrap();
529        x.insert(7, Bytes::from_static(b"hij"), 4).unwrap();
530        x.insert(11, Bytes::from_static(b"lmn"), 4).unwrap();
531        x.defragment();
532        assert_matches!(x.read(usize::MAX, true), Some(ref y) if &y.bytes[..] == b"abcdef");
533        x.insert(5, Bytes::from_static(b"fghijklmn"), 9).unwrap();
534        assert_matches!(x.read(usize::MAX, true), Some(ref y) if &y.bytes[..] == b"ghijklmn");
535        x.insert(13, Bytes::from_static(b"nopq"), 4).unwrap();
536        assert_matches!(x.read(usize::MAX, true), Some(ref y) if &y.bytes[..] == b"opq");
537        x.insert(15, Bytes::from_static(b"pqrs"), 4).unwrap();
538        assert_matches!(x.read(usize::MAX, true), Some(ref y) if &y.bytes[..] == b"rs");
539        assert_matches!(x.read(usize::MAX, true), None);
540    }
541
542    #[test]
543    fn unordered_happy_path() {
544        let mut x = Assembler::new();
545        x.ensure_ordering(false).unwrap();
546        x.insert(0, Bytes::from_static(b"abc"), 3).unwrap();
547        assert_eq!(
548            next_unordered(&mut x),
549            Chunk::new(0, Bytes::from_static(b"abc"))
550        );
551        assert_eq!(x.read(usize::MAX, false), None);
552        x.insert(3, Bytes::from_static(b"def"), 3).unwrap();
553        assert_eq!(
554            next_unordered(&mut x),
555            Chunk::new(3, Bytes::from_static(b"def"))
556        );
557        assert_eq!(x.read(usize::MAX, false), None);
558    }
559
560    #[test]
561    fn unordered_dedup() {
562        let mut x = Assembler::new();
563        x.ensure_ordering(false).unwrap();
564        x.insert(3, Bytes::from_static(b"def"), 3).unwrap();
565        assert_eq!(
566            next_unordered(&mut x),
567            Chunk::new(3, Bytes::from_static(b"def"))
568        );
569        assert_eq!(x.read(usize::MAX, false), None);
570        x.insert(0, Bytes::from_static(b"a"), 1).unwrap();
571        x.insert(0, Bytes::from_static(b"abcdefghi"), 9).unwrap();
572        x.insert(0, Bytes::from_static(b"abcd"), 4).unwrap();
573        assert_eq!(
574            next_unordered(&mut x),
575            Chunk::new(0, Bytes::from_static(b"a"))
576        );
577        assert_eq!(
578            next_unordered(&mut x),
579            Chunk::new(1, Bytes::from_static(b"bc"))
580        );
581        assert_eq!(
582            next_unordered(&mut x),
583            Chunk::new(6, Bytes::from_static(b"ghi"))
584        );
585        assert_eq!(x.read(usize::MAX, false), None);
586        x.insert(8, Bytes::from_static(b"ijkl"), 4).unwrap();
587        assert_eq!(
588            next_unordered(&mut x),
589            Chunk::new(9, Bytes::from_static(b"jkl"))
590        );
591        assert_eq!(x.read(usize::MAX, false), None);
592        x.insert(12, Bytes::from_static(b"mno"), 3).unwrap();
593        assert_eq!(
594            next_unordered(&mut x),
595            Chunk::new(12, Bytes::from_static(b"mno"))
596        );
597        assert_eq!(x.read(usize::MAX, false), None);
598        x.insert(2, Bytes::from_static(b"cde"), 3).unwrap();
599        assert_eq!(x.read(usize::MAX, false), None);
600    }
601
602    #[test]
603    fn chunks_dedup() {
604        let mut x = Assembler::new();
605        x.insert(3, Bytes::from_static(b"def"), 3).unwrap();
606        assert_eq!(x.read(usize::MAX, true), None);
607        x.insert(0, Bytes::from_static(b"a"), 1).unwrap();
608        x.insert(1, Bytes::from_static(b"bcdefghi"), 9).unwrap();
609        x.insert(0, Bytes::from_static(b"abcd"), 4).unwrap();
610        assert_eq!(
611            x.read(usize::MAX, true),
612            Some(Chunk::new(0, Bytes::from_static(b"abcd")))
613        );
614        assert_eq!(
615            x.read(usize::MAX, true),
616            Some(Chunk::new(4, Bytes::from_static(b"efghi")))
617        );
618        assert_eq!(x.read(usize::MAX, true), None);
619        x.insert(8, Bytes::from_static(b"ijkl"), 4).unwrap();
620        assert_eq!(
621            x.read(usize::MAX, true),
622            Some(Chunk::new(9, Bytes::from_static(b"jkl")))
623        );
624        assert_eq!(x.read(usize::MAX, true), None);
625        x.insert(12, Bytes::from_static(b"mno"), 3).unwrap();
626        assert_eq!(
627            x.read(usize::MAX, true),
628            Some(Chunk::new(12, Bytes::from_static(b"mno")))
629        );
630        assert_eq!(x.read(usize::MAX, true), None);
631        x.insert(2, Bytes::from_static(b"cde"), 3).unwrap();
632        assert_eq!(x.read(usize::MAX, true), None);
633    }
634
635    #[test]
636    fn ordered_eager_discard() {
637        let mut x = Assembler::new();
638        x.insert(0, Bytes::from_static(b"abc"), 3).unwrap();
639        assert_eq!(x.data.len(), 1);
640        assert_eq!(
641            x.read(usize::MAX, true),
642            Some(Chunk::new(0, Bytes::from_static(b"abc")))
643        );
644        x.insert(0, Bytes::from_static(b"ab"), 2).unwrap();
645        assert_eq!(x.data.len(), 0);
646        x.insert(2, Bytes::from_static(b"cd"), 2).unwrap();
647        assert_eq!(
648            x.data.peek(),
649            Some(&Buffer::new(3, Bytes::from_static(b"d"), 2))
650        );
651    }
652
653    #[test]
654    fn ordered_insert_unordered_read() {
655        let mut x = Assembler::new();
656        x.insert(0, Bytes::from_static(b"abc"), 3).unwrap();
657        x.insert(0, Bytes::from_static(b"abc"), 3).unwrap();
658        x.ensure_ordering(false).unwrap();
659        assert_eq!(
660            x.read(3, false),
661            Some(Chunk::new(0, Bytes::from_static(b"abc")))
662        );
663        assert_eq!(x.read(3, false), None);
664    }
665
666    fn next_unordered(x: &mut Assembler) -> Chunk {
667        x.read(usize::MAX, false).unwrap()
668    }
669
670    fn next(x: &mut Assembler, size: usize) -> Option<Bytes> {
671        x.read(size, true).map(|chunk| chunk.bytes)
672    }
673}