Skip to main content

ntex_bytes/
pages.rs

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
7/// A growable sequence of byte pages.
8///
9/// Data is stored in fixed-capacity pages selected by [`BytePageSize`]. This
10/// avoids reallocating and copying one large contiguous buffer as data grows.
11pub struct BytePages {
12    st: Option<Box<Inner>>,
13    current: Option<StorageVec>,
14}
15
16#[derive(Debug)]
17struct Inner {
18    size: BytePageSize,
19    /// Total length of `pages`, so `len()` does not walk them.
20    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
29/// Appended data up to this size is copied into the current page.
30const APPEND_COPY_LIMIT: usize = 4096;
31
32impl BytePages {
33    /// Creates a new `BytePages` with the specified page size.
34    ///
35    /// Pages are allocated lazily using the specified capacity category.
36    ///
37    /// # Panics
38    ///
39    /// Panics if `size` is [`BytePageSize::Unset`].
40    pub fn new(size: BytePageSize) -> Self {
41        assert!(size != BytePageSize::Unset, "Page size cannot be Unset");
42
43        // the cache is unavailable while the thread-local is being destroyed
44        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    // Pages are only added and removed through these methods, which keep
76    // `Inner::len` up to date. A page in the list is never modified in place.
77    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    /// Returns the capacity category used for new pages.
107    pub fn page_size(&self) -> BytePageSize {
108        self.st.as_ref().unwrap().size
109    }
110
111    /// Sets the page size for new pages.
112    ///
113    /// # Panics
114    ///
115    /// Panics if `size` is [`BytePageSize::Unset`].
116    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    /// Inserts a non-empty page at the front of the collection.
122    ///
123    /// Returns whether a page was inserted.
124    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    /// Appends a page to the back of the collection.
138    ///
139    /// Empty pages are ignored. If the current page holds no data and `buf` is
140    /// a unique buffer with spare capacity, it becomes the new current page.
141    /// Data of up to 4 KiB is copied into the current page, and into new
142    /// pages as needed. Larger data is added as a separate page without
143    /// copying: the filled part of the current page is split off in front of
144    /// it, and the spare capacity of the current page stays available for
145    /// later writes.
146    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                        // add buffer to the page list
159                        self.push_back(page);
160                    }
161                }
162            } else if p.len() <= APPEND_COPY_LIMIT {
163                self.put_slice(p.as_ref());
164            } else {
165                // the current page is never full, its spare capacity is kept
166                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    /// Appends the given bytes to this page object.
177    ///
178    /// Tries to write the data into the current page first. If there
179    /// is insufficient space, one or more new pages are allocated as
180    /// needed, and the remaining data is copied into them.
181    pub fn extend_from_slice(&mut self, extend: &[u8]) {
182        self.put_slice(extend);
183    }
184
185    #[inline]
186    /// Returns the total number of buffered bytes.
187    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    // spare capacity of the current page
199    fn spare(&self) -> usize {
200        self.current
201            .as_ref()
202            .map(StorageVec::remaining)
203            .unwrap_or_default()
204    }
205
206    #[inline]
207    /// Returns `true` if no bytes are buffered.
208    pub fn is_empty(&self) -> bool {
209        self.len() == 0
210    }
211
212    #[inline]
213    /// Returns the number of allocated pages containing buffered data.
214    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    /// Removes and returns the first page from the collection.
223    ///
224    /// The current writable page is returned last. Returns `None` if there are
225    /// no pages with data, an empty current page keeps its spare capacity for
226    /// later writes.
227    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    /// Appends all buffered data to another [`BytePages`] value, `self` is
239    /// left unchanged.
240    ///
241    /// Pages are shared with `pages` rather than copied, unless they are small
242    /// enough to be copied into the current page of `pages`, see
243    /// [`append`](Self::append).
244    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            // an immutable view, `st` stays the only handle that can write
251            // to the spare capacity
252            pages.append(Bytes {
253                storage: st.shallow_freeze(),
254            });
255        }
256    }
257
258    #[inline]
259    /// Moves all buffered data to the back of another [`BytePages`] value,
260    /// leaving `self` empty.
261    ///
262    /// Pages are moved according to the rules of [`append`](Self::append).
263    pub fn move_to(&mut self, pages: &mut BytePages) {
264        while let Some(page) = self.take() {
265            pages.append(page);
266        }
267    }
268
269    /// Splits the buffer into two at the given index.
270    ///
271    /// Afterwards, `self` contains elements `[at, len)`, and the returned [`BytePages`]
272    /// contains elements `[0, at)`. If `at > len`, all data is moved.
273    ///
274    /// Depending on the underlying storage, this operation might be `O(1)` or could
275    /// involve a memory copy.
276    #[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    /// Splits the buffer, adding the resulting items to the supplied pages object.
284    ///
285    /// Afterwards, `self` contains elements `[at, len)`, and elements `[0, at)`
286    /// are appended to `to`. If `at > len`, all data is moved.
287    ///
288    /// Depending on the underlying storage, this operation might be `O(1)` or could
289    /// involve a memory copy.
290    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                // the remainder stays writable, so its spare capacity is kept
306                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    /// Clears the buffer, removing all data.
319    #[inline]
320    pub fn clear(&mut self) {
321        while self.take().is_some() {}
322    }
323
324    /// Drains all pages into one immutable [`Bytes`] value.
325    #[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    /// Moves the current writable page from `pages` if this value is empty.
344    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    /// Provides mutable access to the current writable page.
354    ///
355    /// The current page, or a new page of [`page_size`](Self::page_size) if
356    /// there is none, is passed to `f` as a [`BytesMut`]. After `f` returns,
357    /// the buffer becomes the current page again. If its length has reached
358    /// the page size, it is pushed onto the page list instead. If `f` changed
359    /// the buffer's capacity (for example by reserving more space), the page
360    /// is no longer returned to the page cache when it is released.
361    ///
362    /// This is a low-level API intended for ntex internals and may change
363    /// without notice.
364    ///
365    /// # Panics
366    ///
367    /// `f` must not panic. The page is not reference-counted while `f` runs,
368    /// so unwinding out of `f` releases it twice, which is undefined behavior.
369    #[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        // `f` can re-allocate `buf.storage`, which invalidates `st`
391        st.0 = buf.storage.0;
392        if buf.capacity() != cap {
393            buf.storage.unsize();
394        }
395        // buf.storage.0 uses same pointer as self.current.0
396        mem::forget(buf);
397
398        // a full page moves to the page list
399        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        // a full page moves to the page list
419        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            // a large write must not pin its page list in the cache
434            st.pages.shrink_to(8);
435            st.len = 0;
436            // the cache is unavailable while the thread-local is being destroyed
437            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
468/// Pages are allocated on demand, so `remaining_mut()` reports
469/// `usize::MAX - len` and `chunk_mut()` is never empty. The chunk covers the
470/// spare capacity of the current page only.
471impl 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        // `current` is set, a new page is allocated above if there is no spare capacity
500        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    /// A single page is converted without copying.
556    fn from(mut pages: BytePages) -> Bytes {
557        pages.freeze()
558    }
559}
560
561impl From<BytePages> for BytesMut {
562    /// A single page is converted without copying if nothing else refers to
563    /// its buffer.
564    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
577/// A contiguous chunk stored by [`BytePages`].
578pub 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    /// Returns the number of bytes contained in this `BytePage`.
591    pub fn len(&self) -> usize {
592        self.as_ref().len()
593    }
594
595    #[inline]
596    /// Returns `true` if the page is empty.
597    pub fn is_empty(&self) -> bool {
598        self.len() == 0
599    }
600
601    #[inline]
602    /// Returns a raw pointer to the data.
603    ///
604    /// # Safety
605    ///
606    /// The returned pointer may only be dereferenced while the page is neither
607    /// moved, modified nor dropped, and only for [`len`](Self::len) bytes. An
608    /// inline page stores its data inside the `BytePage` itself, so moving the
609    /// page invalidates the pointer, see [`is_inline`](Self::is_inline).
610    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    /// Returns the kind of storage backing this page.
623    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    /// Returns `true` if the data is stored inside the `BytePage` itself.
634    ///
635    /// Moving an inline page moves its data, pointers from `as_ptr()` do not
636    /// survive the move.
637    pub fn is_inline(&self) -> bool {
638        matches!(&self.inner, StorageType::Bytes(b) if b.is_inline())
639    }
640
641    /// Splits the buffer into two at the given index.
642    ///
643    /// Afterwards, `self` contains elements `[at, len)`, and the returned `BytePage`
644    /// contains elements `[0, at)`. If `at > len`, all data is moved.
645    ///
646    /// Depending on the underlying storage, this operation might be `O(1)` or could
647    /// involve a memory copy.
648    #[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    /// Advance the internal cursor.
681    ///
682    /// Afterwards `self` contains elements `[cnt, len)`.
683    /// This is an `O(1)` operation, except for pages backed by a `Vec<u8>`,
684    /// whose remaining data is copied.
685    ///
686    /// # Panics
687    ///
688    /// Panics if `cnt > len`.
689    #[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    /// Converts `self` into an immutable `Bytes`.
706    #[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            // SAFETY: Converting back to `StorageVec` requires uniqueness.
721            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            // The clone is an immutable view, `st` must stay the only
739            // handle that can modify the shared header and spare capacity
740            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            // clones of the page may still read the data
853            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        // small data is copied into the current page
953        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        // large data is not copied, the filled part is split off in front
958        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        // later writes use the spare capacity of the current page
966        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        // draining the pages keeps an empty current page for later writes
987        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            // pages
1001            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            // page
1034            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            // debug
1082            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    /// Checks the tracked length against the pages.
1101    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(&copy);
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        // the source keeps writing to the page it shares with the copy
1205        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        // new data goes into the same page
1228        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        // an inline head
1240        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        // the whole current page moves with its spare capacity
1249        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        // an empty current page stays in place
1259        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        // filling the current page through `chunk_mut` starts a new one
1274        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        // the new current page holds no data yet
1281        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        // `put` and `io::Write` are not limited to the current page
1290        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        // the current page
1341        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        // the rest of the page is spare capacity
1348        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        // a `Bytes` page
1360        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        // a shared page is copied
1367        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        // .split_to()
1434        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        // .split_into()
1453        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        // .with_bytes_mut()
1464        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        // into bytes
1485        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        // Bytes storage
1495        let p = BytePage::from(Bytes::copy_from_slice(b"123"));
1496        let p2 = p.clone();
1497        assert_eq!(p, p2);
1498
1499        // StorageVec
1500        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        // short data is copied into an inline view
1509        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        // Vec<u8> storage
1533        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        // Bytes storage
1545        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        // StorageVec
1551        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        // Vec<u8> storage
1557        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        // the target already holds data
1598        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        // the cache is full
1625        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        // the cache is in use
1632        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        // a page with spare capacity becomes the current page
1660        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        // full and shared pages are added to the page list
1669        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}