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#[derive(Debug, Default)]
13pub(super) struct Assembler {
14 state: State,
15 data: BinaryHeap<Buffer>,
16 buffered: usize,
18 allocated: usize,
20 bytes_read: u64,
24 end: u64,
25}
26
27impl Assembler {
28 pub(super) fn new() -> Self {
29 Self::default()
30 }
31
32 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 if !self.data.is_empty() {
46 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 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 return None;
68 } else if (chunk.offset + chunk.bytes.len() as u64) <= self.bytes_read {
69 self.buffered -= chunk.bytes.len();
71 self.allocated -= chunk.allocation_size;
72 PeekMut::pop(chunk);
73 continue;
74 }
75
76 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 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 if !chunk.bytes.is_empty() {
128 self.data.push(chunk);
129 }
130 continue;
131 }
132 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 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 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 let buffered = self.buffered.min((self.end - self.bytes_read) as usize);
202 let over_allocation = self.allocated - buffered;
203 let threshold = 32768.max(buffered * 3 / 2);
211 if over_allocation > threshold {
212 self.defragment();
213 if self.data.len() > 1024 {
215 return Err(TooManyChunks);
216 }
217 }
218
219 Ok(())
220 }
221
222 pub(super) fn bytes_read(&self) -> u64 {
224 self.bytes_read
225 }
226
227 pub(super) fn clear(&mut self) {
229 self.data.clear();
230 self.buffered = 0;
231 self.allocated = 0;
232 }
233}
234
235#[derive(Debug, PartialEq, Eq)]
237pub struct Chunk {
238 pub offset: u64,
240 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 allocation_size: usize,
258 defragmented: bool,
259}
260
261impl Buffer {
262 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 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 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 self.bytes = Bytes::new();
290 self.defragmented = true;
291 self.allocation_size = 0;
292 return;
293 }
294 self.bytes.advance(duplicate);
295 self.defragmented = self.defragmented || self.bytes.len() * 6 / 5 >= self.allocation_size;
298 if self.defragmented {
299 self.allocation_size = self.bytes.len();
301 }
302 }
303}
304
305impl Ord for Buffer {
306 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 recvd: RangeSet,
336 },
337}
338
339impl State {
340 fn is_ordered(&self) -> bool {
341 matches!(self, Self::Ordered)
342 }
343}
344
345#[derive(Debug)]
347pub struct IllegalOrderedRead;
348
349#[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}