1#![allow(clippy::missing_panics_doc, clippy::box_collection)]
2use std::{borrow::Borrow, cell::Cell, cmp, collections::VecDeque, fmt, io, mem, ops};
3
4use crate::{Buf, BufMut, BytePageSize, ByteString, Bytes, BytesMut};
5use crate::{buf::UninitSlice, stvec::StorageVec};
6
7pub struct BytePages {
12 st: Option<Box<Inner>>,
13 current: Option<StorageVec>,
14}
15
16#[derive(Debug)]
17struct Inner {
18 size: BytePageSize,
19 len: usize,
21 pages: VecDeque<BytePage>,
22}
23
24thread_local! {
25 static CACHE: Cell<Option<Box<Vec<Box<Inner>>>>> = Cell::new(Some(Box::default()));
26}
27const CACHE_SIZE: usize = 128;
28
29const APPEND_COPY_LIMIT: usize = 4096;
31
32impl BytePages {
33 pub fn new(size: BytePageSize) -> Self {
41 assert!(size != BytePageSize::Unset, "Page size cannot be Unset");
42
43 let cached = CACHE
45 .try_with(|c| {
46 let mut cache = c.take()?;
47 let item = cache.pop();
48 c.set(Some(cache));
49 item
50 })
51 .ok()
52 .flatten();
53
54 let st = if let Some(mut item) = cached {
55 item.size = size;
56 item
57 } else {
58 Box::new(Inner {
59 size,
60 len: 0,
61 pages: VecDeque::with_capacity(8),
62 })
63 };
64
65 BytePages {
66 st: Some(st),
67 current: None,
68 }
69 }
70
71 fn pages(&self) -> &VecDeque<BytePage> {
72 &self.st.as_ref().unwrap().pages
73 }
74
75 fn push_front(&mut self, page: BytePage) {
78 let st = self.st.as_mut().unwrap();
79 st.len += page.len();
80 st.pages.push_front(page);
81 }
82
83 fn pop_front(&mut self) -> Option<BytePage> {
84 let st = self.st.as_mut().unwrap();
85 let page = st.pages.pop_front()?;
86 st.len -= page.len();
87 Some(page)
88 }
89
90 fn push_back(&mut self, page: BytePage) {
91 let st = self.st.as_mut().unwrap();
92 st.len += page.len();
93 let pages = &mut st.pages;
94 pages.push_back(page);
95
96 #[cfg(feature = "overuse")]
97 if pages.len() == 128 {
98 log::debug!(
99 "Number of pages {}\n{:?}",
100 pages.len(),
101 backtrace::Backtrace::new()
102 );
103 }
104 }
105
106 pub fn page_size(&self) -> BytePageSize {
108 self.st.as_ref().unwrap().size
109 }
110
111 pub fn set_page_size(&mut self, size: BytePageSize) {
117 assert!(size != BytePageSize::Unset, "Page size cannot be Unset");
118 self.st.as_mut().unwrap().size = size;
119 }
120
121 pub fn prepend<T>(&mut self, buf: T) -> bool
125 where
126 BytePage: From<T>,
127 {
128 let p = BytePage::from(buf);
129 if p.is_empty() {
130 false
131 } else {
132 self.push_front(p);
133 true
134 }
135 }
136
137 pub fn append<T>(&mut self, buf: T)
147 where
148 BytePage: From<T>,
149 {
150 let p = BytePage::from(buf);
151 if !p.is_empty() {
152 if self.current_len() == 0 {
153 match p.into_storage() {
154 Ok(st) => {
155 self.current = Some(st);
156 }
157 Err(page) => {
158 self.push_back(page);
160 }
161 }
162 } else if p.len() <= APPEND_COPY_LIMIT {
163 self.put_slice(p.as_ref());
164 } else {
165 if let Some(st) = self.current.as_mut() {
167 let head = st.split_to(st.len());
168 self.push_back(<BytePage as From<Bytes>>::from(Bytes { storage: head }));
169 }
170 self.push_back(p);
171 }
172 }
173 }
174
175 #[inline]
176 pub fn extend_from_slice(&mut self, extend: &[u8]) {
182 self.put_slice(extend);
183 }
184
185 #[inline]
186 pub fn len(&self) -> usize {
188 self.st.as_ref().unwrap().len + self.current_len()
189 }
190
191 fn current_len(&self) -> usize {
192 self.current
193 .as_ref()
194 .map(StorageVec::len)
195 .unwrap_or_default()
196 }
197
198 fn spare(&self) -> usize {
200 self.current
201 .as_ref()
202 .map(StorageVec::remaining)
203 .unwrap_or_default()
204 }
205
206 #[inline]
207 pub fn is_empty(&self) -> bool {
209 self.len() == 0
210 }
211
212 #[inline]
213 pub fn num_pages(&self) -> usize {
215 if self.current_len() == 0 {
216 self.pages().len()
217 } else {
218 self.pages().len() + 1
219 }
220 }
221
222 pub fn take(&mut self) -> Option<BytePage> {
228 if let Some(page) = self.pop_front() {
229 Some(page)
230 } else if self.current_len() == 0 {
231 None
232 } else {
233 self.current.take().map(BytePage::from)
234 }
235 }
236
237 #[inline]
238 pub fn copy_to(&self, pages: &mut BytePages) {
245 for p in self.pages() {
246 pages.append(p.clone());
247 }
248
249 if let Some(st) = &self.current {
250 pages.append(Bytes {
253 storage: st.shallow_freeze(),
254 });
255 }
256 }
257
258 #[inline]
259 pub fn move_to(&mut self, pages: &mut BytePages) {
264 while let Some(page) = self.take() {
265 pages.append(page);
266 }
267 }
268
269 #[must_use]
277 pub fn split_to(&mut self, at: usize) -> BytePages {
278 let mut pages = BytePages::new(self.page_size());
279 self.split_into(at, &mut pages);
280 pages
281 }
282
283 pub fn split_into(&mut self, mut at: usize, to: &mut BytePages) {
291 while let Some(mut page) = self.pop_front() {
292 let len = cmp::min(page.len(), at);
293 to.append(page.split_to(len));
294
295 if !page.is_empty() {
296 self.push_front(page);
297 return;
298 }
299 at -= len;
300 }
301 if at > 0
302 && let Some(mut st) = self.current.take()
303 {
304 if at < st.len() {
305 to.append(Bytes {
307 storage: st.split_to(at),
308 });
309 self.current = Some(st);
310 } else if st.len() == 0 {
311 self.current = Some(st);
312 } else {
313 to.append(BytePage::from(st));
314 }
315 }
316 }
317
318 #[inline]
320 pub fn clear(&mut self) {
321 while self.take().is_some() {}
322 }
323
324 #[inline]
326 #[must_use]
327 pub fn freeze(&mut self) -> Bytes {
328 let pages = self.num_pages();
329 if pages == 0 || self.is_empty() {
330 Bytes::new()
331 } else if pages == 1 {
332 self.take().unwrap().freeze()
333 } else {
334 let mut buf = BytesMut::with_capacity(self.len());
335 while let Some(p) = self.take() {
336 buf.extend_from_slice(&p);
337 }
338 buf.freeze()
339 }
340 }
341
342 #[inline]
343 pub fn try_get_current_from(&mut self, pages: &mut BytePages) {
345 if self.pages().is_empty()
346 && self.current.is_none()
347 && let Some(st) = pages.current.take()
348 {
349 self.current = Some(st);
350 }
351 }
352
353 #[doc(hidden)]
370 #[deprecated(
371 since = "1.10.0",
372 note = "not panic safe, use the `BufMut` methods of `BytePages` instead"
373 )]
374 pub fn with_bytes_mut<F, R>(&mut self, f: F) -> R
375 where
376 F: FnOnce(&mut BytesMut) -> R,
377 {
378 let mut st = self
379 .current
380 .take()
381 .unwrap_or_else(|| StorageVec::sized(self.page_size()));
382
383 let cap = st.capacity();
384 let mut buf = BytesMut {
385 storage: StorageVec(st.0),
386 };
387
388 let res = f(&mut buf);
389
390 st.0 = buf.storage.0;
392 if buf.capacity() != cap {
393 buf.storage.unsize();
394 }
395 mem::forget(buf);
397
398 if st.len() >= self.page_size().capacity() {
400 self.push_back(BytePage::from(st));
401 } else {
402 self.current = Some(st);
403 }
404
405 res
406 }
407
408 fn with_current<F, R>(&mut self, f: F) -> R
409 where
410 F: FnOnce(&mut StorageVec) -> R,
411 {
412 let mut st = self
413 .current
414 .take()
415 .unwrap_or_else(|| StorageVec::sized(self.page_size()));
416 let result = f(&mut st);
417
418 if st.is_full() {
420 self.push_back(BytePage::from(st));
421 } else {
422 self.current = Some(st);
423 }
424
425 result
426 }
427}
428
429impl Drop for BytePages {
430 fn drop(&mut self) {
431 if let Some(mut st) = self.st.take() {
432 st.pages.clear();
433 st.pages.shrink_to(8);
435 st.len = 0;
436 let _ = CACHE.try_with(move |c| {
438 if let Some(mut cache) = c.take() {
439 if cache.len() < CACHE_SIZE {
440 cache.push(st);
441 }
442 c.set(Some(cache));
443 }
444 });
445 }
446 }
447}
448
449impl fmt::Debug for BytePages {
450 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
451 let mut f = fmt.debug_tuple("BytePages");
452 for p in self.pages() {
453 f.field(p);
454 }
455 if let Some(st) = &self.current {
456 f.field(&crate::debug::BsDebug(st.as_ref()));
457 }
458 f.finish()
459 }
460}
461
462impl Default for BytePages {
463 fn default() -> Self {
464 BytePages::new(BytePageSize::Size16)
465 }
466}
467
468impl BufMut for BytePages {
472 #[inline]
473 fn remaining_mut(&self) -> usize {
474 usize::MAX - self.len()
475 }
476
477 #[inline]
478 unsafe fn advance_mut(&mut self, cnt: usize) {
479 if cnt == 0 {
480 return;
481 }
482 let spare = self.spare();
483 assert!(
484 cnt <= spare,
485 "cannot advance past the current page: {cnt:?} <= {spare:?}"
486 );
487 let st = self.current.as_mut().unwrap();
488 st.set_len(st.len() + cnt);
489 }
490
491 #[inline]
492 fn chunk_mut(&mut self) -> &mut UninitSlice {
493 if self.spare() == 0 {
494 if let Some(st) = self.current.take() {
495 self.push_back(BytePage::from(st));
496 }
497 self.current = Some(StorageVec::sized(self.page_size()));
498 }
499 self.current.as_mut().unwrap().spare_mut()
501 }
502
503 fn put<T: Buf>(&mut self, mut src: T)
504 where
505 Self: Sized,
506 {
507 while src.has_remaining() {
508 let chunk = src.chunk();
509 let len = chunk.len();
510 self.put_slice(chunk);
511 src.advance(len);
512 }
513 }
514
515 fn put_slice(&mut self, mut src: &[u8]) {
516 while !src.is_empty() {
517 let amount = self.with_current(|st| st.put_slice_partial(src));
518
519 src = &src[amount..];
520 }
521 }
522
523 #[inline]
524 fn put_u8(&mut self, n: u8) {
525 self.with_current(|st| st.put_u8(n));
526 }
527
528 #[inline]
529 fn put_i8(&mut self, n: i8) {
530 self.put_u8(n as u8);
531 }
532}
533
534impl Clone for BytePages {
535 fn clone(&self) -> Self {
536 let size = self.page_size();
537 let mut pages = BytePages::new(size);
538 self.copy_to(&mut pages);
539 pages
540 }
541}
542
543impl io::Write for BytePages {
544 fn write(&mut self, src: &[u8]) -> Result<usize, io::Error> {
545 self.put_slice(src);
546 Ok(src.len())
547 }
548
549 fn flush(&mut self) -> Result<(), io::Error> {
550 Ok(())
551 }
552}
553
554impl From<BytePages> for Bytes {
555 fn from(mut pages: BytePages) -> Bytes {
557 pages.freeze()
558 }
559}
560
561impl From<BytePages> for BytesMut {
562 fn from(mut pages: BytePages) -> BytesMut {
565 if pages.num_pages() == 1 {
566 return BytesMut::from(pages.take().unwrap());
567 }
568
569 let mut buf = BytesMut::with_capacity(pages.len());
570 while let Some(p) = pages.take() {
571 buf.extend_from_slice(&p);
572 }
573 buf
574 }
575}
576
577pub struct BytePage {
579 inner: StorageType,
580}
581
582enum StorageType {
583 Bytes(Bytes),
584 Storage(StorageVec),
585 Vec(Vec<u8>),
586}
587
588impl BytePage {
589 #[inline]
590 pub fn len(&self) -> usize {
592 self.as_ref().len()
593 }
594
595 #[inline]
596 pub fn is_empty(&self) -> bool {
598 self.len() == 0
599 }
600
601 #[inline]
602 pub unsafe fn as_ptr(&self) -> *const u8 {
611 unsafe {
612 match &self.inner {
613 StorageType::Bytes(b) => b.storage.as_ptr(),
614 StorageType::Storage(b) => b.as_ptr(),
615 StorageType::Vec(b) => b.as_ptr(),
616 }
617 }
618 }
619
620 #[inline]
621 #[doc(hidden)]
622 pub fn info(&self) -> crate::info::PageKind {
624 match &self.inner {
625 StorageType::Bytes(_) => crate::info::PageKind::Bytes,
626 StorageType::Storage(_) => crate::info::PageKind::Storage,
627 StorageType::Vec(_) => crate::info::PageKind::Vec,
628 }
629 }
630
631 #[inline]
632 #[doc(hidden)]
633 pub fn is_inline(&self) -> bool {
638 matches!(&self.inner, StorageType::Bytes(b) if b.is_inline())
639 }
640
641 #[must_use]
649 pub fn split_to(&mut self, at: usize) -> BytePage {
650 match &mut self.inner {
651 StorageType::Bytes(b) => {
652 let buf = b.split_to(cmp::min(at, b.len()));
653 BytePage {
654 inner: StorageType::Bytes(buf),
655 }
656 }
657 StorageType::Storage(_) => {
658 let inner = mem::replace(&mut self.inner, StorageType::Bytes(Bytes::new()));
659 if let StorageType::Storage(st) = inner {
660 self.inner = StorageType::Bytes(Bytes {
661 storage: st.freeze(),
662 });
663 self.split_to(at)
664 } else {
665 unreachable!()
666 }
667 }
668 StorageType::Vec(_) => {
669 let inner = mem::replace(&mut self.inner, StorageType::Bytes(Bytes::new()));
670 if let StorageType::Vec(b) = inner {
671 self.inner = StorageType::Bytes(Bytes::copy_from_slice(&b));
672 self.split_to(at)
673 } else {
674 unreachable!()
675 }
676 }
677 }
678 }
679
680 #[inline]
690 pub fn advance_to(&mut self, cnt: usize) {
691 match &mut self.inner {
692 StorageType::Bytes(b) => b.advance_to(cnt),
693 StorageType::Storage(b) => unsafe { b.set_start(cnt) },
694 StorageType::Vec(b) => {
695 assert!(
696 cnt <= b.len(),
697 "cannot advance past the end of the buffer, cnt:{cnt} len:{}",
698 b.len()
699 );
700 self.inner = StorageType::Bytes(Bytes::copy_from_slice(&b[cnt..]));
701 }
702 }
703 }
704
705 #[inline]
707 #[must_use]
708 pub fn freeze(self) -> Bytes {
709 match self.inner {
710 StorageType::Bytes(b) => b,
711 StorageType::Storage(st) => Bytes {
712 storage: st.freeze(),
713 },
714 StorageType::Vec(v) => Bytes::from(v),
715 }
716 }
717
718 fn into_storage(self) -> Result<StorageVec, Self> {
719 if let StorageType::Storage(st) = self.inner {
720 if !st.is_full() && st.is_unique() {
722 Ok(st)
723 } else {
724 Err(Self {
725 inner: StorageType::Storage(st),
726 })
727 }
728 } else {
729 Err(self)
730 }
731 }
732}
733
734impl Clone for BytePage {
735 fn clone(&self) -> Self {
736 let inner = match &self.inner {
737 StorageType::Bytes(b) => StorageType::Bytes(b.clone()),
738 StorageType::Storage(st) => StorageType::Bytes(Bytes {
741 storage: st.shallow_freeze(),
742 }),
743 StorageType::Vec(b) => StorageType::Bytes(Bytes::copy_from_slice(b)),
744 };
745
746 Self { inner }
747 }
748}
749
750impl AsRef<[u8]> for BytePage {
751 #[inline]
752 fn as_ref(&self) -> &[u8] {
753 match &self.inner {
754 StorageType::Bytes(b) => b.as_ref(),
755 StorageType::Storage(b) => b.as_ref(),
756 StorageType::Vec(b) => b.as_ref(),
757 }
758 }
759}
760
761impl Borrow<[u8]> for BytePage {
762 #[inline]
763 fn borrow(&self) -> &[u8] {
764 self.as_ref()
765 }
766}
767
768impl From<Bytes> for BytePage {
769 fn from(buf: Bytes) -> Self {
770 BytePage {
771 inner: StorageType::Bytes(buf),
772 }
773 }
774}
775
776impl<'a> From<&'a Bytes> for BytePage {
777 fn from(buf: &'a Bytes) -> Self {
778 BytePage {
779 inner: StorageType::Bytes(buf.clone()),
780 }
781 }
782}
783
784impl From<BytesMut> for BytePage {
785 fn from(buf: BytesMut) -> Self {
786 BytePage {
787 inner: StorageType::Storage(buf.storage),
788 }
789 }
790}
791
792impl From<ByteString> for BytePage {
793 fn from(s: ByteString) -> Self {
794 s.into_bytes().into()
795 }
796}
797
798impl<'a> From<&'a ByteString> for BytePage {
799 fn from(s: &'a ByteString) -> Self {
800 s.clone().into_bytes().into()
801 }
802}
803
804impl From<StorageVec> for BytePage {
805 fn from(buf: StorageVec) -> Self {
806 BytePage {
807 inner: StorageType::Storage(buf),
808 }
809 }
810}
811
812impl From<Vec<u8>> for BytePage {
813 fn from(buf: Vec<u8>) -> Self {
814 BytePage {
815 inner: StorageType::Vec(buf),
816 }
817 }
818}
819
820impl From<&'static str> for BytePage {
821 fn from(buf: &'static str) -> Self {
822 Bytes::from_static(buf.as_bytes()).into()
823 }
824}
825
826impl From<&'static [u8]> for BytePage {
827 fn from(buf: &'static [u8]) -> Self {
828 Bytes::from_static(buf).into()
829 }
830}
831
832impl<const N: usize> From<&'static [u8; N]> for BytePage {
833 fn from(buf: &'static [u8; N]) -> Self {
834 Bytes::from_static(buf).into()
835 }
836}
837
838impl From<BytePage> for Bytes {
839 fn from(page: BytePage) -> Self {
840 match page.inner {
841 StorageType::Bytes(b) => b,
842 StorageType::Storage(storage) => BytesMut { storage }.freeze(),
843 StorageType::Vec(v) => Bytes::copy_from_slice(&v),
844 }
845 }
846}
847
848impl From<BytePage> for BytesMut {
849 fn from(page: BytePage) -> Self {
850 match page.inner {
851 StorageType::Bytes(b) => b.into(),
852 StorageType::Storage(storage) => {
854 if storage.is_unique() {
855 BytesMut { storage }
856 } else {
857 BytesMut::copy_from_slice(storage.as_ref())
858 }
859 }
860 StorageType::Vec(v) => BytesMut::copy_from_slice(&v),
861 }
862 }
863}
864
865impl PartialEq for BytePage {
866 fn eq(&self, other: &BytePage) -> bool {
867 self.as_ref() == other.as_ref()
868 }
869}
870
871impl_partial_eq!(BytePage);
872
873impl_read!(BytePage);
874
875impl ops::Deref for BytePage {
876 type Target = [u8];
877
878 #[inline]
879 fn deref(&self) -> &[u8] {
880 self.as_ref()
881 }
882}
883
884impl fmt::Debug for BytePage {
885 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
886 fmt::Debug::fmt(&crate::debug::BsDebug(self.as_ref()), fmt)
887 }
888}
889
890#[cfg(test)]
891mod tests {
892 use rand::Rng;
893
894 use super::*;
895
896 #[test]
897 #[allow(clippy::op_ref, clippy::cmp_owned)]
898 fn page_eq_and_read() {
899 use std::io::Read;
900
901 let mut page = BytePage::from(Vec::from(&b"hello"[..]));
902 assert_eq!(page, b"hello"[..]);
903 assert_eq!(page, *b"hello");
904 assert_eq!(page, b"hello");
905 assert_eq!(page, &b"hello"[..]);
906 assert_eq!(page, "hello");
907 assert_eq!(page, *"hello");
908 assert_eq!(page, b"hello".to_vec());
909 assert_eq!(page, String::from("hello"));
910 assert_eq!(b"hello"[..], page);
911 assert_eq!(*b"hello", page);
912 assert_eq!(b"hello", page);
913 assert_eq!(&b"hello"[..], page);
914 assert_eq!("hello", page);
915 assert_eq!(*"hello", page);
916 assert_eq!(b"hello".to_vec(), page);
917 assert_eq!(String::from("hello"), page);
918 assert_ne!(page, "hell");
919
920 let mut buf = [0u8; 3];
921 assert_eq!(page.read(&mut buf).unwrap(), 3);
922 assert_eq!(&buf, b"hel");
923 assert_eq!(page, "lo");
924 assert_eq!(page.read(&mut buf).unwrap(), 2);
925 assert_eq!(page.read(&mut buf).unwrap(), 0);
926 assert!(page.is_empty());
927 }
928
929 #[test]
930 fn page_info() {
931 use crate::info::PageKind;
932
933 let p = BytePage::from(Bytes::copy_from_slice(&[1; 64]));
934 assert_eq!(p.info(), PageKind::Bytes);
935 let p = BytePage::from(BytesMut::copy_from_slice(&[1; 64][..]));
936 assert_eq!(p.info(), PageKind::Storage);
937 let p = BytePage::from(vec![1; 64]);
938 assert_eq!(p.info(), PageKind::Vec);
939 assert!(!p.is_inline());
940
941 assert!(BytePage::from(Bytes::copy_from_slice(&[1; 4])).is_inline());
942 assert!(!BytePage::from(Bytes::copy_from_slice(&[1; 64])).is_inline());
943 assert!(!BytePage::from(BytesMut::copy_from_slice(&[1; 4][..])).is_inline());
944 }
945
946 #[test]
947 fn append_copies_small_and_splits_for_large() {
948 let cap = BytePageSize::Size16.capacity();
949 let mut pages = BytePages::new(BytePageSize::Size16);
950 pages.extend_from_slice(b"head\r\n");
951
952 pages.append(Bytes::copy_from_slice(&[1; APPEND_COPY_LIMIT]));
954 assert_eq!(pages.num_pages(), 1);
955 assert_eq!(pages.current_len(), 6 + APPEND_COPY_LIMIT);
956
957 let body = Bytes::copy_from_slice(&[2; APPEND_COPY_LIMIT + 1]);
959 let body_ptr = body.as_ptr();
960 pages.append(body.clone());
961 assert_eq!(pages.num_pages(), 2);
962 assert_eq!(pages.current_len(), 0);
963 assert_eq!(pages.spare(), cap - 6 - APPEND_COPY_LIMIT);
964
965 let page_ptr = pages.pages()[0].as_ref().as_ptr();
967 pages.extend_from_slice(b"\r\n");
968 assert_eq!(pages.num_pages(), 3);
969 let tail_ptr = pages.current.as_ref().unwrap().as_ref().as_ptr();
970 assert_eq!(tail_ptr, page_ptr.wrapping_add(6 + APPEND_COPY_LIMIT));
971
972 let mut expected = b"head\r\n".to_vec();
973 expected.extend_from_slice(&[1; APPEND_COPY_LIMIT]);
974 expected.extend_from_slice(&body);
975 expected.extend_from_slice(b"\r\n");
976 assert_eq!(pages.len(), expected.len());
977
978 let first = pages.take().unwrap();
979 let second = pages.take().unwrap();
980 assert_eq!(second.as_ref().as_ptr(), body_ptr);
981 let third = pages.take().unwrap();
982 assert!(pages.take().is_none());
983 let data = [first.as_ref(), second.as_ref(), third.as_ref()].concat();
984 assert_eq!(data, expected);
985
986 pages.extend_from_slice(b"x");
988 pages.append(body);
989 assert_eq!(pages.take().unwrap().as_ref(), b"x");
990 assert_eq!(pages.take().unwrap().len(), APPEND_COPY_LIMIT + 1);
991 assert!(pages.take().is_none());
992 assert_eq!(pages.num_pages(), 0);
993 assert_eq!(pages.spare(), cap - 1);
994 }
995
996 #[test]
997 fn pages() {
998 let cap = BytePageSize::Size8.capacity();
999 unsafe {
1000 let mut pages = BytePages::new(BytePageSize::Size8);
1002 assert!(pages.is_empty());
1003 assert_eq!(pages.len(), 0);
1004 assert_eq!(pages.num_pages(), 0);
1005 pages.extend_from_slice(b"b");
1006 assert_eq!(pages.len(), 1);
1007 assert_eq!(pages.num_pages(), 1);
1008 pages.extend_from_slice("a".repeat(9 * 1024).as_bytes());
1009 assert_eq!(pages.len(), 9217);
1010 assert_eq!(pages.num_pages(), 2);
1011 assert!(!pages.is_empty());
1012
1013 let mut pgs = BytePages::new(BytePageSize::Size8);
1014 pgs.put_i8(b'a' as i8);
1015 let p = pgs.take().unwrap();
1016 assert_eq!(p.len(), 1);
1017 assert_eq!(p.as_ref(), b"a");
1018
1019 pgs.extend_from_slice("a".repeat(cap - 1).as_bytes());
1020 assert_eq!(pgs.num_pages(), 1);
1021 pgs.put_u8(b'a');
1022 assert_eq!(pgs.num_pages(), 1);
1023 assert!(pgs.current.is_none());
1024
1025 pgs.put_u8(b'a');
1026 assert_eq!(pgs.num_pages(), 2);
1027
1028 pgs.append(Bytes::copy_from_slice("a".repeat(cap).as_bytes()));
1029 assert_eq!(pgs.num_pages(), 3);
1030 assert_eq!(pgs.current_len(), 0);
1031 assert_eq!(pgs.spare(), cap - 1);
1032
1033 let p = pages.take().unwrap();
1035 assert_eq!(p.len(), cap);
1036 let p = pages.take().unwrap();
1037 assert_eq!(p.len(), 9217 - cap);
1038 assert!(!p.is_empty());
1039 assert_eq!(p.as_ref().as_ptr(), p.as_ptr());
1040 assert_eq!(p.as_ref(), "a".repeat(9217 - cap).as_bytes());
1041 assert!(pages.take().is_none());
1042
1043 let p = BytePage::from(Bytes::copy_from_slice(b"123"));
1044 assert_eq!(p.len(), 3);
1045 assert!(!p.is_empty());
1046 assert_eq!(p.as_ref(), b"123");
1047 assert_eq!(p.as_ref().as_ptr(), p.as_ptr());
1048
1049 let p = BytePage::from(&b"123"[..]);
1050 assert_eq!(p.len(), 3);
1051 assert!(!p.is_empty());
1052 assert_eq!(p.as_ref(), b"123");
1053 assert_eq!(p.as_ref().as_ptr(), p.as_ptr());
1054
1055 let p = BytePage::from(b"123");
1056 assert_eq!(p.len(), 3);
1057 assert!(!p.is_empty());
1058 assert_eq!(p.as_ref(), b"123");
1059 assert_eq!(p.as_ref().as_ptr(), p.as_ptr());
1060
1061 let p = BytePage::from("123");
1062 assert_eq!(p.len(), 3);
1063 assert!(!p.is_empty());
1064 assert_eq!(p.as_ref(), b"123");
1065 assert_eq!(p.as_ref().as_ptr(), p.as_ptr());
1066 assert_eq!(p.freeze(), b"123");
1067
1068 let p = BytePage::from(vec![b'1', b'2', b'3']);
1069 assert_eq!(p.len(), 3);
1070 assert!(!p.is_empty());
1071 assert_eq!(p.as_ref(), b"123");
1072 assert_eq!(p.as_ref().as_ptr(), p.as_ptr());
1073 assert_eq!(p.freeze(), b"123");
1074
1075 let mut p = BytePage::from(vec![b'1', b'2', b'3']);
1076 p.advance_to(1);
1077 assert_eq!(p.len(), 2);
1078 assert!(!p.is_empty());
1079 assert_eq!(p.as_ref(), b"23");
1080
1081 let mut pages = BytePages::new(BytePageSize::Size8);
1083 pages.extend_from_slice(b"b");
1084 assert_eq!(format!("{pages:?}"), "BytePages(b\"b\")");
1085 let p = pages.take().unwrap();
1086 assert_eq!(p.as_ref(), b"b");
1087
1088 let mut pages = BytePages::new(BytePageSize::Size8);
1089 pages.extend_from_slice(b"a");
1090 pages.append(Bytes::copy_from_slice(b"123"));
1091 pages.push_back(p);
1092 assert_eq!(format!("{pages:?}"), "BytePages(b\"b\", b\"a123\")");
1093
1094 assert_eq!(pages.len(), 5);
1095 pages.clear();
1096 assert_eq!(pages.len(), 0);
1097 }
1098 }
1099
1100 fn assert_len(pages: &BytePages) {
1102 let len = pages.pages().iter().map(BytePage::len).sum::<usize>() + pages.current_len();
1103 assert_eq!(pages.len(), len);
1104 assert_eq!(pages.is_empty(), len == 0);
1105 }
1106
1107 #[test]
1108 fn pages_len_tracking() {
1109 let mut rng = rand::rng();
1110 let mut pages = BytePages::new(BytePageSize::Size8);
1111 let mut other = BytePages::new(BytePageSize::Size8);
1112 let mut expected = 0;
1113
1114 let (iters, max) = if cfg!(miri) { (100, 256) } else { (2000, 12 * 1024) };
1115 for _ in 0..iters {
1116 let n = rng.random_range(0..max);
1117 match rng.random_range(0..9) {
1118 0 => {
1119 pages.extend_from_slice(&vec![1; n]);
1120 expected += n;
1121 }
1122 1 => {
1123 pages.append(Bytes::copy_from_slice(&vec![2; n]));
1124 expected += n;
1125 }
1126 2 => {
1127 if pages.prepend(BytesMut::copy_from_slice(vec![3; n])) {
1128 expected += n;
1129 }
1130 }
1131 3 => {
1132 if let Some(p) = pages.take() {
1133 expected -= p.len();
1134 }
1135 }
1136 4 => {
1137 let at = cmp::min(n, expected);
1138 let split = pages.split_to(at);
1139 assert_len(&split);
1140 assert_eq!(split.len(), at);
1141 expected -= at;
1142 }
1143 5 => {
1144 let at = cmp::min(n, expected);
1145 pages.split_into(at, &mut other);
1146 expected -= at;
1147 }
1148 6 => {
1149 other.move_to(&mut pages);
1150 assert_len(&other);
1151 assert!(other.is_empty());
1152 expected = pages.len();
1153 }
1154 7 => {
1155 let mut copy = BytePages::new(BytePageSize::Size8);
1156 pages.copy_to(&mut copy);
1157 assert_len(©);
1158 assert_eq!(copy.len(), expected);
1159 }
1160 _ => {
1161 pages.put_u8(4);
1162 expected += 1;
1163 }
1164 }
1165 assert_len(&pages);
1166 assert_len(&other);
1167 assert_eq!(pages.len(), expected);
1168 }
1169
1170 let len = pages.len();
1171 assert_eq!(pages.freeze().len(), len);
1172 assert_len(&pages);
1173 assert!(pages.is_empty());
1174 pages.extend_from_slice(b"123");
1175 pages.clear();
1176 assert_len(&pages);
1177 assert!(pages.is_empty());
1178 }
1179
1180 #[test]
1181 fn pages_len_after_cache_reuse() {
1182 let mut pages = BytePages::new(BytePageSize::Size8);
1183 pages.append(Bytes::copy_from_slice(&[1; 64]));
1184 pages.append(Bytes::copy_from_slice(&[1; 64]));
1185 drop(pages);
1186
1187 let pages = BytePages::new(BytePageSize::Size8);
1188 assert_len(&pages);
1189 assert!(pages.is_empty());
1190 }
1191
1192 #[test]
1193 fn pages_copy_to_shares_current() {
1194 let mut pages = BytePages::new(BytePageSize::Size8);
1195 pages.put_slice(&[1; 64]);
1196 let ptr = unsafe { pages.current.as_ref().unwrap().as_ptr() };
1197
1198 let mut copy = BytePages::new(BytePageSize::Size8);
1199 pages.copy_to(&mut copy);
1200 let page = copy.take().unwrap();
1201 assert_eq!(unsafe { page.as_ptr() }, ptr.cast_const());
1202 assert_eq!(page.as_ref(), &[1; 64][..]);
1203
1204 pages.put_slice(&[2; 64]);
1206 assert_eq!(unsafe { pages.current.as_ref().unwrap().as_ptr() }, ptr);
1207 assert_eq!(page.as_ref(), &[1; 64][..]);
1208 assert_eq!(pages.len(), 128);
1209
1210 drop(pages);
1211 assert_eq!(page.as_ref(), &[1; 64][..]);
1212 }
1213
1214 #[test]
1215 fn pages_split_keeps_current_writable() {
1216 let mut pages = BytePages::new(BytePageSize::Size8);
1217 pages.put_slice(&[1; 64]);
1218 let ptr = unsafe { pages.current.as_ref().unwrap().as_ptr() };
1219 let remaining = pages.spare();
1220
1221 let mut head = pages.split_to(40);
1222 assert_eq!(head.len(), 40);
1223 assert_eq!(pages.len(), 24);
1224 assert_eq!(pages.num_pages(), 1);
1225 assert_eq!(pages.spare(), remaining);
1226
1227 pages.put_slice(&[2; 16]);
1229 assert_eq!(pages.num_pages(), 1);
1230 assert_eq!(
1231 unsafe { pages.current.as_ref().unwrap().as_ptr() },
1232 ptr.wrapping_add(40)
1233 );
1234 let mut expected = vec![1; 24];
1235 expected.extend_from_slice(&[2; 16]);
1236 assert_eq!(&pages.freeze()[..], &expected[..]);
1237 assert_eq!(&head.freeze()[..], &[1; 40][..]);
1238
1239 let mut pages = BytePages::new(BytePageSize::Size8);
1241 pages.put_slice(&[1; 64]);
1242 let mut to = BytePages::new(BytePageSize::Size8);
1243 pages.split_into(2, &mut to);
1244 assert_eq!(&to.freeze()[..], &[1; 2][..]);
1245 assert_eq!(pages.spare(), remaining);
1246 assert_eq!(pages.len(), 62);
1247
1248 let mut pages = BytePages::new(BytePageSize::Size8);
1250 pages.put_slice(&[1; 64]);
1251 let ptr = unsafe { pages.current.as_ref().unwrap().as_ptr() };
1252 let to = pages.split_to(64);
1253 assert!(pages.is_empty());
1254 assert_eq!(pages.num_pages(), 0);
1255 assert_eq!(to.spare(), remaining);
1256 assert_eq!(unsafe { to.current.as_ref().unwrap().as_ptr() }, ptr);
1257
1258 let mut pages = BytePages::new(BytePageSize::Size8);
1260 let _ = pages.chunk_mut();
1261 let head = pages.split_to(10);
1262 assert!(head.is_empty());
1263 assert_eq!(pages.spare(), remaining + 64);
1264 }
1265
1266 #[test]
1267 fn pages_buf_mut_grows() {
1268 let mut pages = BytePages::new(BytePageSize::Size8);
1269 assert!(pages.has_remaining_mut());
1270 assert_eq!(pages.remaining_mut(), usize::MAX);
1271 unsafe { pages.advance_mut(0) };
1272
1273 let n = pages.chunk_mut().len();
1275 unsafe {
1276 std::ptr::write_bytes(pages.chunk_mut().as_mut_ptr(), 1, n);
1277 pages.advance_mut(n);
1278 }
1279 assert!(pages.chunk_mut().len() > 0);
1280 assert_eq!(pages.num_pages(), 1);
1282 unsafe {
1283 *pages.chunk_mut().as_mut_ptr() = 2;
1284 pages.advance_mut(1);
1285 }
1286 assert_eq!(pages.len(), n + 1);
1287 assert_eq!(pages.remaining_mut(), usize::MAX - n - 1);
1288
1289 let mut pages = BytePages::new(BytePageSize::Size8);
1291 pages.put(&[3u8; 200][..]);
1292 pages.put(Bytes::from_static(b"abcd"));
1293 io::Write::write_all(&mut pages, &[4; 100]).unwrap();
1294 let mut expected = vec![3; 200];
1295 expected.extend_from_slice(b"abcd");
1296 expected.extend_from_slice(&[4; 100]);
1297 assert_eq!(&pages.freeze()[..], &expected[..]);
1298 }
1299
1300 #[test]
1301 #[should_panic(expected = "cannot advance past the current page")]
1302 fn pages_advance_past_current_page() {
1303 let mut pages = BytePages::new(BytePageSize::Size8);
1304 let n = pages.chunk_mut().len();
1305 unsafe { pages.advance_mut(n + 1) };
1306 }
1307
1308 #[test]
1309 #[should_panic(expected = "Page size cannot be Unset")]
1310 fn pages_new_unset() {
1311 let _ = BytePages::new(BytePageSize::Unset);
1312 }
1313
1314 #[test]
1315 #[should_panic(expected = "Page size cannot be Unset")]
1316 fn pages_set_page_size_unset() {
1317 let mut pages = BytePages::new(BytePageSize::Size8);
1318 pages.set_page_size(BytePageSize::Unset);
1319 }
1320
1321 #[test]
1322 fn cached_pages_list_is_shrunk() {
1323 let mut pages = BytePages::new(BytePageSize::Size4);
1324 for _ in 0..200 {
1325 pages.append(Bytes::from_static(b"page"));
1326 }
1327 assert!(pages.pages().capacity() >= 200);
1328 drop(pages);
1329
1330 let pages = BytePages::new(BytePageSize::Size4);
1331 assert!(
1332 pages.pages().capacity() < 200,
1333 "{}",
1334 pages.pages().capacity()
1335 );
1336 }
1337
1338 #[test]
1339 fn pages_into_bytes_single_page() {
1340 let mut pages = BytePages::new(BytePageSize::Size8);
1342 pages.put_slice(&[1; 64]);
1343 let ptr = unsafe { pages.current.as_ref().unwrap().as_ptr() };
1344 let mut buf = BytesMut::from(pages);
1345 assert_eq!(buf.as_ptr(), ptr.cast_const());
1346 assert_eq!(&buf[..], &[1; 64][..]);
1347 assert_eq!(buf.capacity(), BytePageSize::Size8.capacity());
1349 buf.extend_from_slice(&[2; 64]);
1350 assert_eq!(buf.as_ptr(), ptr.cast_const());
1351
1352 let mut pages = BytePages::new(BytePageSize::Size8);
1353 pages.put_slice(&[1; 64]);
1354 let ptr = unsafe { pages.current.as_ref().unwrap().as_ptr() };
1355 let b = Bytes::from(pages);
1356 assert_eq!(b.as_ptr(), ptr.cast_const());
1357 assert_eq!(&b[..], &[1; 64][..]);
1358
1359 let src = Bytes::copy_from_slice(&[3; 64]);
1361 let ptr = src.as_ptr();
1362 let mut pages = BytePages::new(BytePageSize::Size8);
1363 pages.prepend(src);
1364 assert_eq!(BytesMut::from(pages).as_ptr(), ptr);
1365
1366 let src = Bytes::copy_from_slice(&[3; 64]);
1368 let mut pages = BytePages::new(BytePageSize::Size8);
1369 pages.prepend(&src);
1370 let mut buf = BytesMut::from(pages);
1371 assert_ne!(buf.as_ptr(), src.as_ptr());
1372 buf[0] = 4;
1373 assert_eq!(&src[..], &[3; 64][..]);
1374 }
1375
1376 #[test]
1377 fn pages_into_bytes_multiple_pages() {
1378 let mut pages = BytePages::new(BytePageSize::Size8);
1379 pages.prepend(Bytes::copy_from_slice(&[1; 64]));
1380 pages.put_slice(&[2; 64]);
1381 assert_eq!(pages.num_pages(), 2);
1382 let buf = BytesMut::from(pages);
1383 assert_eq!(&buf[..64], &[1; 64][..]);
1384 assert_eq!(&buf[64..], &[2; 64][..]);
1385
1386 let mut pages = BytePages::new(BytePageSize::Size8);
1387 pages.prepend(Bytes::copy_from_slice(&[1; 64]));
1388 pages.put_slice(&[2; 64]);
1389 let b = Bytes::from(pages);
1390 assert_eq!(&b[..64], &[1; 64][..]);
1391 assert_eq!(&b[64..], &[2; 64][..]);
1392
1393 assert!(BytesMut::from(BytePages::new(BytePageSize::Size8)).is_empty());
1394 assert!(Bytes::from(BytePages::new(BytePageSize::Size8)).is_empty());
1395 }
1396
1397 #[test]
1398 fn pages_copy_to() {
1399 let mut pages = BytePages::default();
1400 let mut pages2 = BytePages::default();
1401 pages.put_slice(b"456");
1402 pages.prepend(BytePage::from(Bytes::copy_from_slice(b"123")));
1403 pages.copy_to(&mut pages2);
1404 let p = pages.freeze();
1405 assert_eq!(p, b"123456");
1406 let p2 = pages2.freeze();
1407 assert_eq!(p2, b"123456");
1408
1409 let mut pages = BytePages::default();
1410 let mut pages2 = BytePages::default();
1411 pages.put_slice(b"456");
1412 pages.prepend(BytePage::from(Bytes::copy_from_slice(b"123")));
1413 pages.copy_to(&mut pages2);
1414 pages.put_u8(b'7');
1415 let p = pages.freeze();
1416 assert_eq!(p, b"1234567");
1417 let p2 = pages2.freeze();
1418 assert_eq!(p2, b"123456");
1419
1420 let mut pages = BytePages::default();
1421 pages.put_slice(b"456");
1422 pages.prepend(BytePage::from(Bytes::copy_from_slice(b"123")));
1423 let mut pages2 = pages.clone();
1424 pages.put_u8(b'7');
1425 let p = pages.freeze();
1426 assert_eq!(p, b"1234567");
1427 let p2 = pages2.freeze();
1428 assert_eq!(p2, b"123456");
1429 }
1430
1431 #[test]
1432 fn pages_methods() {
1433 let mut pages = BytePages::default();
1435 pages.put_slice(b"456");
1436 pages.prepend(BytePage::from(&Bytes::copy_from_slice(b"123")));
1437 let mut pages2 = pages.split_to(1);
1438 let p = pages.freeze();
1439 assert_eq!(p, b"23456");
1440 let p2 = pages2.freeze();
1441 assert_eq!(p2, b"1");
1442
1443 let mut pages = BytePages::default();
1444 pages.put_slice(b"456");
1445 pages.prepend(BytePage::from(Bytes::copy_from_slice(b"123")));
1446 let mut pages2 = pages.split_to(4);
1447 let p = pages.freeze();
1448 assert_eq!(p, b"56");
1449 let p2 = pages2.freeze();
1450 assert_eq!(p2, b"1234");
1451
1452 let mut pages = BytePages::default();
1454 pages.put_slice(b"456");
1455 pages.prepend(BytePage::from(crate::ByteString::from_static("123")));
1456 let mut pages2 = BytePages::default();
1457 pages.split_into(1, &mut pages2);
1458 let p = pages.freeze();
1459 assert_eq!(p, b"23456");
1460 let p2 = pages2.freeze();
1461 assert_eq!(p2, b"1");
1462
1463 let mut pages = BytePages::default();
1465 #[allow(deprecated)]
1466 pages.with_bytes_mut(|buf| buf.extend_from_slice(b"123"));
1467 assert_eq!(pages.len(), 3);
1468 let p = pages.freeze();
1469 assert_eq!(p, b"123");
1470
1471 let data = rand::rng()
1472 .sample_iter(&rand::distr::Alphanumeric)
1473 .take(65_536)
1474 .map(char::from)
1475 .collect::<String>();
1476
1477 let mut pages = BytePages::default();
1478 #[allow(deprecated)]
1479 pages.with_bytes_mut(|buf| buf.extend_from_slice(data.as_bytes()));
1480 assert_eq!(pages.len(), 65_536);
1481 let p = pages.freeze();
1482 assert_eq!(p, data.as_bytes());
1483
1484 let page = BytePage::from(Bytes::copy_from_slice(b"123"));
1486 assert_eq!(page, b"123");
1487 assert_eq!(<BytePage as Borrow<[u8]>>::borrow(&page), b"123");
1488 let b = Bytes::from(page);
1489 assert_eq!(b, b"123");
1490 }
1491
1492 #[test]
1493 fn page_clone() {
1494 let p = BytePage::from(Bytes::copy_from_slice(b"123"));
1496 let p2 = p.clone();
1497 assert_eq!(p, p2);
1498
1499 let mut p = BytePage::from(BytesMut::copy_from_slice(b"123"));
1501 if let StorageType::Storage(ref mut st) = p.inner {
1502 assert!(st.is_unique());
1503 } else {
1504 panic!()
1505 }
1506 let p2 = p.clone();
1507 assert_eq!(p, p2);
1508 assert!(matches!(p2.inner, StorageType::Bytes(_)));
1510 if let StorageType::Storage(st) = p.inner {
1511 assert!(st.is_unique());
1512 } else {
1513 panic!()
1514 }
1515
1516 let mut p = BytePage::from(BytesMut::copy_from_slice([b'1'; 64]));
1517 let p2 = p.clone();
1518 assert_eq!(p, p2);
1519 assert!(matches!(p2.inner, StorageType::Bytes(_)));
1520 if let StorageType::Storage(ref mut st) = p.inner {
1521 assert!(!st.is_unique());
1522 } else {
1523 panic!()
1524 }
1525 drop(p2);
1526 if let StorageType::Storage(st) = p.inner {
1527 assert!(st.is_unique());
1528 } else {
1529 panic!()
1530 }
1531
1532 let p = BytePage::from(vec![b'1', b'2', b'3']);
1534 let p2 = p.clone();
1535 assert_eq!(p, p2);
1536 if let StorageType::Bytes(_) = p2.inner {
1537 } else {
1538 panic!()
1539 }
1540 }
1541
1542 #[test]
1543 fn page_split_to() {
1544 let mut p = BytePage::from(Bytes::copy_from_slice(b"123"));
1546 let p2 = p.split_to(1);
1547 assert_eq!(p, b"23");
1548 assert_eq!(p2, b"1");
1549
1550 let mut p = BytePage::from(BytesMut::copy_from_slice(b"123"));
1552 let p2 = p.split_to(1);
1553 assert_eq!(p, b"23");
1554 assert_eq!(p2, b"1");
1555
1556 let mut p = BytePage::from(vec![b'1', b'2', b'3']);
1558 let p2 = p.split_to(1);
1559 assert_eq!(p, b"23");
1560 assert_eq!(p2, b"1");
1561 }
1562
1563 #[test]
1564 fn page_read() {
1565 use std::io::Read;
1566
1567 let mut page = BytePage::from(Bytes::copy_from_slice(b"123"));
1568
1569 let mut buf = [0; 10];
1570 assert_eq!(page.read(&mut buf).unwrap(), 3);
1571 assert_eq!(page.len(), 0);
1572 assert_eq!(buf, [49, 50, 51, 0, 0, 0, 0, 0, 0, 0]);
1573 }
1574
1575 #[test]
1576 fn pages_misc() {
1577 let mut pages = BytePages::new(BytePageSize::Size4);
1578 pages.set_page_size(BytePageSize::Size8);
1579 assert_eq!(pages.page_size(), BytePageSize::Size8);
1580 assert!(!pages.prepend(Bytes::new()));
1581 assert!(pages.prepend(Bytes::from_static(b"a")));
1582
1583 io::Write::write_all(&mut pages, b"bc").unwrap();
1584 io::Write::flush(&mut pages).unwrap();
1585 assert_eq!(pages.freeze(), "abc");
1586
1587 let s = ByteString::from_static("str");
1588 pages.append(&s);
1589 assert_eq!(pages.freeze(), "str");
1590 }
1591
1592 #[test]
1593 fn pages_try_get_current_from() {
1594 let mut src = BytePages::new(BytePageSize::Size4);
1595 src.extend_from_slice(b"data");
1596
1597 let mut dst = BytePages::new(BytePageSize::Size4);
1599 dst.append(Bytes::from_static(b"x"));
1600 dst.try_get_current_from(&mut src);
1601 assert_eq!(src.len(), 4);
1602 assert_eq!(dst.len(), 1);
1603
1604 let mut dst = BytePages::new(BytePageSize::Size4);
1605 dst.try_get_current_from(&mut src);
1606 assert_eq!(src.len(), 0);
1607 assert_eq!(dst.len(), 4);
1608 dst.extend_from_slice(b"!");
1609 assert_eq!(dst.freeze(), "data!");
1610 }
1611
1612 #[test]
1613 fn pages_drop_cache() {
1614 CACHE.with(|c| c.set(Some(Box::default())));
1615 let cached = || {
1616 CACHE.with(|c| {
1617 let cache = c.take().unwrap();
1618 let len = cache.len();
1619 c.set(Some(cache));
1620 len
1621 })
1622 };
1623
1624 let pages: Vec<_> = (0..=CACHE_SIZE)
1626 .map(|_| BytePages::new(BytePageSize::Size4))
1627 .collect();
1628 drop(pages);
1629 assert_eq!(cached(), CACHE_SIZE);
1630
1631 CACHE.with(|c| c.set(Some(Box::default())));
1633 let pages = BytePages::new(BytePageSize::Size4);
1634 let cache = CACHE.with(Cell::take);
1635 drop(pages);
1636 CACHE.with(|c| c.set(cache));
1637 assert_eq!(cached(), 0);
1638 }
1639
1640 #[test]
1641 fn page_conversions() {
1642 let page = BytePage::from(BytesMut::copy_from_slice([1; 64]));
1643 assert_eq!(page.info(), crate::info::PageKind::Storage);
1644 assert_eq!(Bytes::from(page), &[1; 64][..]);
1645
1646 let page = BytePage::from(vec![2; 64]);
1647 assert_eq!(page.info(), crate::info::PageKind::Vec);
1648 assert_eq!(Bytes::from(page), &[2; 64][..]);
1649
1650 let page = BytePage::from(vec![3; 64]);
1651 assert_eq!(BytesMut::from(page), &[3; 64][..]);
1652
1653 let s = ByteString::from_static("string");
1654 assert_eq!(BytePage::from(&s), "string");
1655 }
1656
1657 #[test]
1658 fn append_storage_page() {
1659 let mut pages = BytePages::new(BytePageSize::Size4);
1661 let mut buf = BytesMut::with_capacity(64);
1662 buf.extend_from_slice(b"a");
1663 pages.append(buf);
1664 pages.extend_from_slice(b"b");
1665 assert_eq!(pages.num_pages(), 1);
1666 assert_eq!(pages.freeze(), "ab");
1667
1668 let mut buf = BytesMut::with_capacity(64);
1670 let cap = buf.capacity();
1671 buf.resize(cap, b'x');
1672 pages.append(buf);
1673 let page = BytePage::from(BytesMut::copy_from_slice([b'y'; 64]));
1674 let shared = page.clone();
1675 pages.append(page);
1676 pages.extend_from_slice(b"z");
1677 assert_eq!(pages.num_pages(), 3);
1678 assert_eq!(pages.len(), cap + 65);
1679 assert_eq!(shared, &[b'y'; 64][..]);
1680 }
1681}