1use crate::listpack::{Entry, backlen_len, decode, entry_len, read_backlen, write_entry};
45
46pub const CHUNK_BYTES: usize = 8192;
54
55pub const CHUNK_ENTRIES: usize = 512;
65
66#[derive(Debug, Clone, PartialEq, Eq)]
68pub struct Chunk {
69 bytes: Vec<u8>,
70 head: usize,
72 tail: usize,
74 count: usize,
75}
76
77impl Chunk {
78 #[must_use]
80 pub fn for_back() -> Chunk {
81 Chunk {
82 bytes: vec![0; CHUNK_BYTES],
83 head: 0,
84 tail: 0,
85 count: 0,
86 }
87 }
88
89 #[must_use]
91 pub fn for_front() -> Chunk {
92 Chunk {
93 bytes: vec![0; CHUNK_BYTES],
94 head: CHUNK_BYTES,
95 tail: CHUNK_BYTES,
96 count: 0,
97 }
98 }
99
100 #[must_use]
108 pub fn plain(value: &[u8]) -> Chunk {
109 let mut c = Chunk {
110 bytes: vec![0; entry_len(value)],
111 head: 0,
112 tail: 0,
113 count: 0,
114 };
115 let put = c.push_back(value);
116 debug_assert!(put, "a chunk sized for one element refused it");
117 c
118 }
119
120 #[must_use]
128 pub fn adopt(entries: &[u8], count: usize) -> Chunk {
129 let mut bytes = vec![0; CHUNK_BYTES.max(entries.len())];
130 bytes[..entries.len()].copy_from_slice(entries);
131 Chunk {
132 bytes,
133 head: 0,
134 tail: entries.len(),
135 count,
136 }
137 }
138
139 #[must_use]
141 #[inline]
142 pub const fn len(&self) -> usize {
143 self.count
144 }
145
146 #[must_use]
148 #[inline]
149 pub const fn is_empty(&self) -> bool {
150 self.count == 0
151 }
152
153 #[must_use]
155 pub fn memory_bytes(&self) -> usize {
156 self.bytes.capacity() + size_of::<Chunk>()
157 }
158
159 #[must_use]
161 #[inline]
162 pub const fn live_bytes(&self) -> usize {
163 self.tail - self.head
164 }
165
166 #[must_use]
174 #[inline]
175 pub fn entries(&self) -> &[u8] {
176 &self.bytes[self.head..self.tail]
177 }
178
179 pub fn push_back(&mut self, value: &[u8]) -> bool {
185 if self.count >= CHUNK_ENTRIES {
186 return false;
187 }
188 let need = entry_len(value);
189 if self.tail + need > self.bytes.len() && !self.shift(need, false) {
190 return false;
191 }
192 write_entry(&mut self.bytes[self.tail..], value);
193 self.tail += need;
194 self.count += 1;
195 true
196 }
197
198 pub fn push_front(&mut self, value: &[u8]) -> bool {
200 if self.count >= CHUNK_ENTRIES {
201 return false;
202 }
203 let need = entry_len(value);
204 if need > self.head && !self.shift(need, true) {
205 return false;
206 }
207 self.head -= need;
208 write_entry(&mut self.bytes[self.head..], value);
209 self.count += 1;
210 true
211 }
212
213 fn shift(&mut self, need: usize, front: bool) -> bool {
221 let live = self.tail - self.head;
222 let free = self.bytes.len() - live;
223 if free < need {
224 return false;
225 }
226 let spare = (free - need) / 2;
227 let head = if front { need + spare } else { spare };
228 self.bytes.copy_within(self.head..self.tail, head);
229 self.head = head;
230 self.tail = head + live;
231 true
232 }
233
234 #[must_use]
236 pub fn front(&self) -> Option<Entry<'_>> {
237 if self.count == 0 {
238 return None;
239 }
240 decode(&self.bytes[self.head..self.tail]).map(|(e, _)| e)
241 }
242
243 #[must_use]
245 pub fn back(&self) -> Option<Entry<'_>> {
246 let at = self.back_at()?;
247 decode(&self.bytes[at..self.tail]).map(|(e, _)| e)
248 }
249
250 #[must_use]
252 pub fn get(&self, index: usize) -> Option<Entry<'_>> {
253 let at = self.offset_of(index)?;
254 decode(&self.bytes[at..self.tail]).map(|(e, _)| e)
255 }
256
257 pub fn drop_front(&mut self) -> bool {
263 if self.count == 0 {
264 return false;
265 }
266 let Some(step) = self.step(self.head) else {
267 return false;
268 };
269 self.head += step;
270 self.count -= 1;
271 true
272 }
273
274 pub fn drop_back(&mut self) -> bool {
276 let Some(at) = self.back_at() else {
277 return false;
278 };
279 self.tail = at;
280 self.count -= 1;
281 true
282 }
283
284 pub fn drop_front_n(&mut self, n: usize) -> usize {
291 let mut at = self.head;
292 let took = n.min(self.count);
293 for _ in 0..took {
294 let Some(step) = self.step(at) else {
295 break;
296 };
297 at += step;
298 }
299 self.count -= took;
300 self.head = at;
301 took
302 }
303
304 pub fn drop_back_n(&mut self, n: usize) -> usize {
306 let took = n.min(self.count);
307 for _ in 0..took {
308 let Some(at) = self.back_at() else {
309 break;
310 };
311 self.tail = at;
312 self.count -= 1;
313 }
314 took
315 }
316
317 pub fn insert_at(&mut self, index: usize, value: &[u8]) -> bool {
327 if index > self.count {
328 return false;
329 }
330 if index == self.count {
331 return self.push_back(value);
332 }
333 if index == 0 {
334 return self.push_front(value);
335 }
336 if self.count >= CHUNK_ENTRIES {
337 return false;
338 }
339 let need = entry_len(value);
340 let Some(at) = self.offset_of(index) else {
341 return false;
342 };
343 let front = need <= self.head;
346 let back = self.tail + need <= self.bytes.len();
347 let at = if (front && !back) || (front && back && index * 2 <= self.count) {
348 self.bytes.copy_within(self.head..at, self.head - need);
349 self.head -= need;
350 at - need
351 } else if back {
352 self.bytes.copy_within(at..self.tail, at + need);
353 self.tail += need;
354 at
355 } else {
356 if !self.shift(need, false) {
359 return false;
360 }
361 let at = self.offset_of(index).expect("the entries did not move");
362 self.bytes.copy_within(at..self.tail, at + need);
363 self.tail += need;
364 at
365 };
366 write_entry(&mut self.bytes[at..], value);
367 self.count += 1;
368 true
369 }
370
371 pub fn remove_at(&mut self, index: usize) -> bool {
373 if index >= self.count {
374 return false;
375 }
376 if index == 0 {
377 return self.drop_front();
378 }
379 if index + 1 == self.count {
380 return self.drop_back();
381 }
382 let Some(at) = self.offset_of(index) else {
383 return false;
384 };
385 let Some(span) = self.step(at) else {
386 return false;
387 };
388 if index * 2 <= self.count {
390 self.bytes.copy_within(self.head..at, self.head + span);
391 self.head += span;
392 } else {
393 self.bytes.copy_within(at + span..self.tail, at);
394 self.tail -= span;
395 }
396 self.count -= 1;
397 true
398 }
399
400 pub fn replace_at(&mut self, index: usize, value: &[u8]) -> bool {
406 let Some(at) = self.offset_of(index) else {
407 return false;
408 };
409 let need = entry_len(value);
410 if self.step(at) == Some(need) {
411 write_entry(&mut self.bytes[at..], value);
412 return true;
413 }
414 if !self.insert_at(index, value) {
417 return false;
418 }
419 self.remove_at(index + 1)
420 }
421
422 #[must_use]
429 pub fn split_off(&mut self, index: usize) -> Chunk {
430 let at = self.offset_of(index).unwrap_or(self.tail);
431 let rest = Chunk::adopt(&self.bytes[at..self.tail], self.count - index);
432 self.tail = at;
433 self.count = index;
434 rest
435 }
436
437 pub fn seal(&mut self) {
443 if self.head > 0 {
444 self.bytes.copy_within(self.head..self.tail, 0);
445 self.tail -= self.head;
446 self.head = 0;
447 }
448 self.bytes.truncate(self.tail);
449 self.bytes.shrink_to_fit();
450 }
451
452 #[must_use]
461 pub fn find(&self, value: &[u8], as_int: Option<i64>) -> Option<usize> {
462 crate::listpack::scan_for(&self.bytes[self.head..self.tail], value, as_int, 1)
463 }
464
465 pub fn find_each(
471 &self,
472 value: &[u8],
473 as_int: Option<i64>,
474 limit: usize,
475 hit: &mut dyn FnMut(usize) -> bool,
476 ) -> usize {
477 crate::listpack::scan_each(&self.bytes[self.head..self.tail], value, as_int, limit, hit)
478 }
479
480 pub fn find_each_back(
482 &self,
483 value: &[u8],
484 as_int: Option<i64>,
485 limit: usize,
486 hit: &mut dyn FnMut(usize) -> bool,
487 ) -> usize {
488 crate::listpack::scan_each_back(
489 &self.bytes[self.head..self.tail],
490 value,
491 as_int,
492 limit,
493 hit,
494 )
495 }
496
497 #[must_use]
499 pub fn iter(&self) -> Iter<'_> {
500 Iter {
501 bytes: &self.bytes[self.head..self.tail],
502 at: 0,
503 }
504 }
505
506 #[must_use]
513 pub fn iter_back(&self) -> RevIter<'_> {
514 RevIter {
515 bytes: &self.bytes[self.head..self.tail],
516 at: self.tail - self.head,
517 }
518 }
519
520 #[must_use]
527 pub fn iter_from(&self, index: usize) -> Iter<'_> {
528 let at = self.offset_of(index).unwrap_or(self.tail);
529 Iter {
530 bytes: &self.bytes[self.head..self.tail],
531 at: at - self.head,
532 }
533 }
534
535 fn offset_of(&self, index: usize) -> Option<usize> {
543 if index >= self.count {
544 return None;
545 }
546 if index * 2 <= self.count {
547 let mut at = self.head;
548 for _ in 0..index {
549 at += self.step(at)?;
550 }
551 return Some(at);
552 }
553 let mut end = self.tail;
554 for _ in index..self.count {
555 let len = read_backlen(&self.bytes[self.head..end])?;
556 end = end.checked_sub(len + backlen_len(len))?;
557 }
558 Some(end)
559 }
560
561 fn back_at(&self) -> Option<usize> {
563 if self.count == 0 {
564 return None;
565 }
566 let len = read_backlen(&self.bytes[self.head..self.tail])?;
567 self.tail.checked_sub(len + backlen_len(len))
568 }
569
570 fn step(&self, at: usize) -> Option<usize> {
572 let (_, len) = decode(&self.bytes[at..self.tail])?;
573 Some(len + backlen_len(len))
574 }
575}
576
577#[derive(Debug)]
579pub struct Iter<'a> {
580 bytes: &'a [u8],
581 at: usize,
582}
583
584impl<'a> Iterator for Iter<'a> {
585 type Item = Entry<'a>;
586
587 #[inline]
588 fn next(&mut self) -> Option<Entry<'a>> {
589 if self.at >= self.bytes.len() {
590 return None;
591 }
592 let (entry, len) = decode(&self.bytes[self.at..])?;
593 self.at += len + backlen_len(len);
594 Some(entry)
595 }
596}
597
598#[derive(Debug)]
600pub struct RevIter<'a> {
601 bytes: &'a [u8],
602 at: usize,
603}
604
605impl<'a> Iterator for RevIter<'a> {
606 type Item = Entry<'a>;
607
608 #[inline]
609 fn next(&mut self) -> Option<Entry<'a>> {
610 if self.at == 0 {
611 return None;
612 }
613 let len = read_backlen(&self.bytes[..self.at])?;
614 let start = self.at.checked_sub(len + backlen_len(len))?;
615 let (entry, _) = decode(&self.bytes[start..self.at])?;
616 self.at = start;
617 Some(entry)
618 }
619}
620
621#[cfg(test)]
622mod tests {
623 use super::*;
624
625 fn all(c: &Chunk) -> Vec<Vec<u8>> {
626 c.iter().map(|e| e.to_vec()).collect()
627 }
628
629 #[test]
630 fn a_back_chunk_fills_from_the_front_of_its_buffer() {
631 let mut c = Chunk::for_back();
632 assert!(c.push_back(b"a"));
633 assert!(c.push_back(b"b"));
634 assert_eq!(all(&c), vec![b"a".to_vec(), b"b".to_vec()]);
635 assert_eq!(c.len(), 2);
636 assert_eq!(c.front().unwrap().to_vec(), b"a");
637 assert_eq!(c.back().unwrap().to_vec(), b"b");
638 }
639
640 #[test]
641 fn a_front_chunk_fills_backward_and_reads_forward() {
642 let mut c = Chunk::for_front();
643 assert!(c.push_front(b"b"));
644 assert!(c.push_front(b"a"));
645 assert_eq!(all(&c), vec![b"a".to_vec(), b"b".to_vec()]);
646 assert_eq!(c.front().unwrap().to_vec(), b"a");
647 assert_eq!(c.back().unwrap().to_vec(), b"b");
648 }
649
650 #[test]
653 fn pushing_and_popping_at_both_ends_stays_in_order() {
654 let mut c = Chunk::for_back();
655 for m in [b"c", b"d"] {
656 assert!(c.push_back(m));
657 }
658 for m in [b"b", b"a"] {
659 assert!(c.push_front(m));
660 }
661 assert_eq!(
662 all(&c),
663 vec![b"a".to_vec(), b"b".to_vec(), b"c".to_vec(), b"d".to_vec()]
664 );
665 assert!(c.drop_front());
666 assert!(c.drop_back());
667 assert_eq!(all(&c), vec![b"b".to_vec(), b"c".to_vec()]);
668 assert_eq!(c.len(), 2);
669 }
670
671 #[test]
676 fn a_back_chunk_makes_room_at_the_front_once() {
677 let mut c = Chunk::for_back();
678 assert!(c.push_back(b"a"));
679 assert!(c.push_front(b"z"));
680 assert_eq!(all(&c), vec![b"z".to_vec(), b"a".to_vec()]);
681 let head = c.head;
682 for i in 0..100 {
683 assert!(c.push_front(i.to_string().as_bytes()), "at {i}");
684 }
685 assert!(c.head < head, "the front pushes went somewhere else");
686 assert_eq!(c.len(), 102);
687 assert_eq!(c.back().unwrap().to_vec(), b"a");
688 }
689
690 #[test]
693 fn a_full_chunk_refuses_both_ends() {
694 let mut c = Chunk::for_back();
695 let big = vec![b'x'; 500];
696 while c.push_back(&big) {}
697 assert!(!c.push_back(&big));
698 assert!(!c.push_front(&big));
699 assert!(c.push_front(b"1"), "there is still room for a short one");
700 }
701
702 #[test]
703 fn an_empty_chunk_answers_nothing_rather_than_panicking() {
704 let mut c = Chunk::for_back();
705 assert!(c.front().is_none());
706 assert!(c.back().is_none());
707 assert!(c.get(0).is_none());
708 assert!(!c.drop_front());
709 assert!(!c.drop_back());
710 }
711
712 #[test]
713 fn the_element_cap_is_what_stops_a_chunk_of_small_members() {
714 let mut c = Chunk::for_back();
715 for i in 0..CHUNK_ENTRIES {
716 assert!(c.push_back(i.to_string().as_bytes()), "at {i}");
717 }
718 assert!(!c.push_back(b"1"));
719 assert_eq!(c.len(), CHUNK_ENTRIES);
720 }
721
722 #[test]
723 fn the_byte_cap_is_what_stops_a_chunk_of_large_members() {
724 let mut c = Chunk::for_back();
725 let big = vec![b'x'; 300];
726 let mut n = 0;
727 while c.push_back(&big) {
728 n += 1;
729 }
730 assert!(n < CHUNK_ENTRIES, "{n} entries fitted, which is too many");
731 assert_eq!(c.len(), n);
732 assert!(c.live_bytes() <= CHUNK_BYTES);
733 }
734
735 #[test]
736 fn indexing_walks_from_the_head_cursor_and_not_from_the_buffer() {
737 let mut c = Chunk::for_front();
738 for m in [b"d", b"c", b"b", b"a"] {
739 assert!(c.push_front(m));
740 }
741 for (i, want) in [b"a", b"b", b"c", b"d"].iter().enumerate() {
742 assert_eq!(c.get(i).unwrap().to_vec(), want.to_vec(), "at {i}");
743 }
744 assert!(c.get(4).is_none());
745 }
746
747 #[test]
748 fn sealing_keeps_the_elements_and_gives_back_the_room() {
749 let mut c = Chunk::for_front();
750 for m in [b"c", b"b", b"a"] {
751 assert!(c.push_front(m));
752 }
753 let before = c.memory_bytes();
754 let live = c.live_bytes();
755 c.seal();
756 assert_eq!(
757 all(&c),
758 vec![b"a".to_vec(), b"b".to_vec(), b"c".to_vec()],
759 "sealing changed what is in it"
760 );
761 assert_eq!(c.live_bytes(), live);
762 assert!(c.memory_bytes() < before);
763 assert_eq!(c.front().unwrap().to_vec(), b"a");
769 assert_eq!(c.back().unwrap().to_vec(), b"c");
770 assert_eq!(c.get(1).unwrap().to_vec(), b"b");
771 assert!(!c.push_back(b"d"));
772 assert!(!c.push_front(b"d"));
773 assert!(c.drop_front());
774 assert_eq!(c.front().unwrap().to_vec(), b"b");
775 }
776
777 #[test]
780 fn integers_come_back_as_integers() {
781 let mut c = Chunk::for_back();
782 assert!(c.push_back(b"42"));
783 assert!(c.push_back(b"007"));
784 assert_eq!(c.get(0), Some(Entry::Int(42)));
785 assert_eq!(c.get(1), Some(Entry::Str(b"007")));
786 }
787
788 #[test]
791 fn the_back_walk_survives_a_long_entry() {
792 for len in [1usize, 63, 64, 120, 126, 127, 128, 200] {
793 let mut c = Chunk::for_back();
794 let v = vec![b'x'; len];
795 assert!(c.push_back(b"first"));
796 assert!(c.push_back(&v), "{len} did not fit");
797 assert_eq!(c.back().unwrap().to_vec(), v, "back of a {len} byte entry");
798 assert!(c.drop_back());
799 assert_eq!(c.back().unwrap().to_vec(), b"first");
800 }
801 }
802
803 fn abcde() -> Chunk {
805 let mut c = Chunk::for_back();
806 for m in [b"c", b"d", b"e"] {
807 assert!(c.push_back(m));
808 }
809 for m in [b"b", b"a"] {
810 assert!(c.push_front(m));
811 }
812 c
813 }
814
815 #[test]
816 fn an_insert_lands_where_it_was_asked_to_from_either_side() {
817 for at in 0..=5 {
818 let mut c = abcde();
819 assert!(c.insert_at(at, b"new"), "inserting at {at}");
820 let mut want: Vec<Vec<u8>> = [b"a", b"b", b"c", b"d", b"e"]
821 .iter()
822 .map(|m| m.to_vec())
823 .collect();
824 want.insert(at, b"new".to_vec());
825 assert_eq!(all(&c), want, "inserting at {at}");
826 assert_eq!(c.len(), 6);
827 }
828 let mut c = abcde();
829 assert!(!c.insert_at(6, b"new"), "past the end is not an insert");
830 }
831
832 #[test]
833 fn a_remove_closes_the_gap_from_either_side() {
834 for at in 0..5 {
835 let mut c = abcde();
836 assert!(c.remove_at(at), "removing at {at}");
837 let mut want: Vec<Vec<u8>> = [b"a", b"b", b"c", b"d", b"e"]
838 .iter()
839 .map(|m| m.to_vec())
840 .collect();
841 want.remove(at);
842 assert_eq!(all(&c), want, "removing at {at}");
843 assert_eq!(c.len(), 4);
844 assert_eq!(c.back().unwrap().to_vec(), want[3]);
845 }
846 let mut c = abcde();
847 assert!(!c.remove_at(5));
848 }
849
850 #[test]
853 fn a_replace_takes_a_value_of_any_length() {
854 for value in [&b"z"[..], &b"much longer than what was there"[..], b"7"] {
855 for at in 0..5 {
856 let mut c = abcde();
857 assert!(c.replace_at(at, value), "replacing at {at}");
858 let mut want: Vec<Vec<u8>> = [b"a", b"b", b"c", b"d", b"e"]
859 .iter()
860 .map(|m| m.to_vec())
861 .collect();
862 want[at] = value.to_vec();
863 assert_eq!(all(&c), want, "replacing at {at}");
864 assert_eq!(c.len(), 5);
865 }
866 }
867 let mut c = abcde();
868 assert!(!c.replace_at(5, b"z"));
869 }
870
871 #[test]
872 fn dropping_many_from_an_end_is_the_walk_and_nothing_else() {
873 let mut c = abcde();
874 assert_eq!(c.drop_front_n(2), 2);
875 assert_eq!(all(&c), vec![b"c".to_vec(), b"d".to_vec(), b"e".to_vec()]);
876 assert_eq!(c.drop_back_n(2), 2);
877 assert_eq!(all(&c), vec![b"c".to_vec()]);
878 assert_eq!(c.drop_front_n(9), 1, "it stops when it runs out");
879 assert!(c.is_empty());
880 assert_eq!(c.drop_back_n(3), 0);
881 }
882
883 #[test]
884 fn a_split_leaves_both_halves_readable_and_with_room() {
885 for at in 0..=5 {
886 let mut c = abcde();
887 let mut rest = c.split_off(at);
888 let want: Vec<Vec<u8>> = [b"a", b"b", b"c", b"d", b"e"]
889 .iter()
890 .map(|m| m.to_vec())
891 .collect();
892 assert_eq!(all(&c), want[..at].to_vec(), "the front half of {at}");
893 assert_eq!(all(&rest), want[at..].to_vec(), "the back half of {at}");
894 assert_eq!(c.len() + rest.len(), 5);
895 assert!(rest.push_back(b"more"), "the back half has no room");
896 assert_eq!(rest.back().unwrap().to_vec(), b"more");
897 }
898 }
899
900 #[test]
903 fn a_full_chunk_refuses_an_insert_and_a_split_fixes_it() {
904 let mut c = Chunk::for_back();
905 let big = vec![b'x'; 500];
906 while c.push_back(&big) {}
907 let held = c.len();
908 assert!(!c.insert_at(held / 2, &big));
909 let mut rest = c.split_off(held / 2);
910 assert!(c.push_back(&big) || rest.push_front(&big));
911 assert_eq!(c.len() + rest.len(), held + 1);
912 }
913}