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    /// Returns an iterator over the buffered data, one slice per page.
238    ///
239    /// The current writable page is yielded last, if it holds data. The
240    /// pages are stored on the heap, so their data stays at the same address
241    /// when `self` is moved, until `self` is modified or dropped.
242    pub fn iter(&self) -> impl Iterator<Item = &[u8]> {
243        self.pages().iter().map(BytePage::as_ref).chain(
244            self.current
245                .as_ref()
246                .map(StorageVec::as_ref)
247                .filter(|s| !s.is_empty()),
248        )
249    }
250
251    /// Advance the internal cursor.
252    ///
253    /// Afterwards `self` contains elements `[cnt, len)`. Fully consumed pages
254    /// are dropped, the current writable page keeps its spare capacity.
255    ///
256    /// # Panics
257    ///
258    /// Panics if `cnt > len`.
259    pub fn advance_to(&mut self, mut cnt: usize) {
260        assert!(
261            cnt <= self.len(),
262            "cannot advance past the end of the buffer, cnt:{cnt} len:{}",
263            self.len()
264        );
265
266        while cnt > 0
267            && let Some(mut page) = self.pop_front()
268        {
269            if cnt < page.len() {
270                page.advance_to(cnt);
271                self.push_front(page);
272                return;
273            }
274            cnt -= page.len();
275        }
276        if cnt > 0
277            && let Some(st) = self.current.as_mut()
278        {
279            // SAFETY: `cnt <= st.len()`, checked by the assert above
280            unsafe { st.set_start(cnt) };
281        }
282    }
283
284    #[inline]
285    /// Appends all buffered data to another [`BytePages`] value, `self` is
286    /// left unchanged.
287    ///
288    /// Pages are shared with `pages` rather than copied, unless they are small
289    /// enough to be copied into the current page of `pages`, see
290    /// [`append`](Self::append).
291    pub fn copy_to(&self, pages: &mut BytePages) {
292        for p in self.pages() {
293            pages.append(p.clone());
294        }
295
296        if let Some(st) = &self.current {
297            // an immutable view, `st` stays the only handle that can write
298            // to the spare capacity
299            pages.append(Bytes {
300                storage: st.shallow_freeze(),
301            });
302        }
303    }
304
305    /// Moves all buffered data to the back of another [`BytePages`] value,
306    /// leaving `self` empty.
307    ///
308    /// Pages are moved as is, without copying or merging. The filled part of
309    /// the current page of `pages` is split off in front of the moved data,
310    /// its spare capacity stays available for later writes. The current page
311    /// of `self` is moved as a regular page.
312    pub fn move_to(&mut self, pages: &mut BytePages) {
313        if self.is_empty() {
314            return;
315        }
316
317        if let Some(st) = pages.current.as_mut()
318            && st.len() != 0
319        {
320            let head = st.split_to(st.len());
321            pages.push_back(<BytePage as From<Bytes>>::from(Bytes { storage: head }));
322        }
323
324        let src = self.st.as_mut().unwrap();
325        let dst = pages.st.as_mut().unwrap();
326        if dst.pages.is_empty() {
327            mem::swap(&mut src.pages, &mut dst.pages);
328            dst.len = mem::take(&mut src.len);
329        } else {
330            while let Some(page) = self.pop_front() {
331                pages.push_back(page);
332            }
333        }
334
335        if self.current_len() != 0
336            && let Some(st) = self.current.take()
337        {
338            pages.push_back(BytePage::from(st));
339        }
340    }
341
342    /// Splits the buffer into two at the given index.
343    ///
344    /// Afterwards, `self` contains elements `[at, len)`, and the returned [`BytePages`]
345    /// contains elements `[0, at)`. If `at > len`, all data is moved.
346    ///
347    /// Depending on the underlying storage, this operation might be `O(1)` or could
348    /// involve a memory copy.
349    #[must_use]
350    pub fn split_to(&mut self, at: usize) -> BytePages {
351        let mut pages = BytePages::new(self.page_size());
352        self.split_into(at, &mut pages);
353        pages
354    }
355
356    /// Splits the buffer, adding the resulting items to the supplied pages object.
357    ///
358    /// Afterwards, `self` contains elements `[at, len)`, and elements `[0, at)`
359    /// are appended to `to`. If `at > len`, all data is moved.
360    ///
361    /// Depending on the underlying storage, this operation might be `O(1)` or could
362    /// involve a memory copy.
363    pub fn split_into(&mut self, mut at: usize, to: &mut BytePages) {
364        while let Some(mut page) = self.pop_front() {
365            let len = cmp::min(page.len(), at);
366            to.append(page.split_to(len));
367
368            if !page.is_empty() {
369                self.push_front(page);
370                return;
371            }
372            at -= len;
373        }
374        if at > 0
375            && let Some(mut st) = self.current.take()
376        {
377            if at < st.len() {
378                // the remainder stays writable, so its spare capacity is kept
379                to.append(Bytes {
380                    storage: st.split_to(at),
381                });
382                self.current = Some(st);
383            } else if st.len() == 0 {
384                self.current = Some(st);
385            } else {
386                to.append(BytePage::from(st));
387            }
388        }
389    }
390
391    /// Clears the buffer, removing all data.
392    #[inline]
393    pub fn clear(&mut self) {
394        while self.take().is_some() {}
395    }
396
397    /// Drains all pages into one immutable [`Bytes`] value.
398    #[inline]
399    #[must_use]
400    pub fn freeze(&mut self) -> Bytes {
401        let pages = self.num_pages();
402        if pages == 0 || self.is_empty() {
403            Bytes::new()
404        } else if pages == 1 {
405            self.take().unwrap().freeze()
406        } else {
407            let mut buf = BytesMut::with_capacity(self.len());
408            while let Some(p) = self.take() {
409                buf.extend_from_slice(&p);
410            }
411            buf.freeze()
412        }
413    }
414
415    #[inline]
416    /// Moves the current writable page from `pages` if this value is empty.
417    pub fn try_get_current_from(&mut self, pages: &mut BytePages) {
418        if self.pages().is_empty()
419            && self.current.is_none()
420            && let Some(st) = pages.current.take()
421        {
422            self.current = Some(st);
423        }
424    }
425
426    /// Passes a new mutable buffer to `f` and appends its contents.
427    ///
428    /// After `f` returns, the buffer is appended according to the rules of
429    /// [`append`](Self::append). Existing pages and the current writable page
430    /// are not exposed to `f`. If `f` panics, the temporary buffer is dropped
431    /// and this collection is unchanged.
432    ///
433    /// This is a low-level API intended for ntex internals and may change
434    /// without notice.
435    #[doc(hidden)]
436    #[deprecated(
437        since = "1.10.0",
438        note = "use the `BufMut` methods of `BytePages` instead"
439    )]
440    pub fn with_bytes_mut<F, R>(&mut self, f: F) -> R
441    where
442        F: FnOnce(&mut BytesMut) -> R,
443    {
444        let mut buf = BytesMut::new();
445        let res = f(&mut buf);
446        self.append(buf);
447        res
448    }
449
450    fn with_current<F, R>(&mut self, f: F) -> R
451    where
452        F: FnOnce(&mut StorageVec) -> R,
453    {
454        let mut st = self
455            .current
456            .take()
457            .unwrap_or_else(|| StorageVec::sized(self.page_size()));
458        let result = f(&mut st);
459
460        // a full page moves to the page list
461        if st.is_full() {
462            self.push_back(BytePage::from(st));
463        } else {
464            self.current = Some(st);
465        }
466
467        result
468    }
469}
470
471impl Drop for BytePages {
472    fn drop(&mut self) {
473        if let Some(mut st) = self.st.take() {
474            st.pages.clear();
475            // a large write must not pin its page list in the cache
476            st.pages.shrink_to(8);
477            st.len = 0;
478            // the cache is unavailable while the thread-local is being destroyed
479            let _ = CACHE.try_with(move |c| {
480                if let Some(mut cache) = c.take() {
481                    if cache.len() < CACHE_SIZE {
482                        cache.push(st);
483                    }
484                    c.set(Some(cache));
485                }
486            });
487        }
488    }
489}
490
491impl fmt::Debug for BytePages {
492    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
493        let mut f = fmt.debug_tuple("BytePages");
494        for p in self.pages() {
495            f.field(p);
496        }
497        if let Some(st) = &self.current {
498            f.field(&crate::debug::BsDebug(st.as_ref()));
499        }
500        f.finish()
501    }
502}
503
504impl Default for BytePages {
505    fn default() -> Self {
506        BytePages::new(BytePageSize::Size16)
507    }
508}
509
510/// Pages are allocated on demand, so `remaining_mut()` reports
511/// `usize::MAX - len` and `chunk_mut()` is never empty. The chunk covers the
512/// spare capacity of the current page only.
513impl BufMut for BytePages {
514    #[inline]
515    fn remaining_mut(&self) -> usize {
516        usize::MAX - self.len()
517    }
518
519    #[inline]
520    unsafe fn advance_mut(&mut self, cnt: usize) {
521        if cnt == 0 {
522            return;
523        }
524        let spare = self.spare();
525        assert!(
526            cnt <= spare,
527            "cannot advance past the current page: {cnt:?} <= {spare:?}"
528        );
529        let st = self.current.as_mut().unwrap();
530        st.set_len(st.len() + cnt);
531    }
532
533    #[inline]
534    fn chunk_mut(&mut self) -> &mut UninitSlice {
535        if self.spare() == 0 {
536            if let Some(st) = self.current.take() {
537                self.push_back(BytePage::from(st));
538            }
539            self.current = Some(StorageVec::sized(self.page_size()));
540        }
541        // `current` is set, a new page is allocated above if there is no spare capacity
542        self.current.as_mut().unwrap().spare_mut()
543    }
544
545    fn put<T: Buf>(&mut self, mut src: T)
546    where
547        Self: Sized,
548    {
549        while src.has_remaining() {
550            let chunk = src.chunk();
551            let len = chunk.len();
552            self.put_slice(chunk);
553            src.advance(len);
554        }
555    }
556
557    fn put_slice(&mut self, mut src: &[u8]) {
558        while !src.is_empty() {
559            let amount = self.with_current(|st| st.put_slice_partial(src));
560
561            src = &src[amount..];
562        }
563    }
564
565    #[inline]
566    fn put_u8(&mut self, n: u8) {
567        self.with_current(|st| st.put_u8(n));
568    }
569
570    #[inline]
571    fn put_i8(&mut self, n: i8) {
572        self.put_u8(n as u8);
573    }
574}
575
576impl Clone for BytePages {
577    fn clone(&self) -> Self {
578        let size = self.page_size();
579        let mut pages = BytePages::new(size);
580        self.copy_to(&mut pages);
581        pages
582    }
583}
584
585impl io::Write for BytePages {
586    fn write(&mut self, src: &[u8]) -> Result<usize, io::Error> {
587        self.put_slice(src);
588        Ok(src.len())
589    }
590
591    fn flush(&mut self) -> Result<(), io::Error> {
592        Ok(())
593    }
594}
595
596impl From<BytePages> for Bytes {
597    /// A single page is converted without copying.
598    fn from(mut pages: BytePages) -> Bytes {
599        pages.freeze()
600    }
601}
602
603impl From<BytePages> for BytesMut {
604    /// A single page is converted without copying if nothing else refers to
605    /// its buffer.
606    fn from(mut pages: BytePages) -> BytesMut {
607        if pages.num_pages() == 1 {
608            return BytesMut::from(pages.take().unwrap());
609        }
610
611        let mut buf = BytesMut::with_capacity(pages.len());
612        while let Some(p) = pages.take() {
613            buf.extend_from_slice(&p);
614        }
615        buf
616    }
617}
618
619/// A contiguous chunk stored by [`BytePages`].
620pub struct BytePage {
621    inner: StorageType,
622}
623
624enum StorageType {
625    Bytes(Bytes),
626    Storage(StorageVec),
627    Vec(Vec<u8>),
628}
629
630impl BytePage {
631    #[inline]
632    /// Returns the number of bytes contained in this `BytePage`.
633    pub fn len(&self) -> usize {
634        self.as_ref().len()
635    }
636
637    #[inline]
638    /// Returns `true` if the page is empty.
639    pub fn is_empty(&self) -> bool {
640        self.len() == 0
641    }
642
643    #[inline]
644    /// Returns a raw pointer to the data.
645    ///
646    /// # Safety
647    ///
648    /// The returned pointer may only be dereferenced while the page is neither
649    /// moved, modified nor dropped, and only for [`len`](Self::len) bytes. An
650    /// inline page stores its data inside the `BytePage` itself, so moving the
651    /// page invalidates the pointer, see [`is_inline`](Self::is_inline).
652    pub unsafe fn as_ptr(&self) -> *const u8 {
653        unsafe {
654            match &self.inner {
655                StorageType::Bytes(b) => b.storage.as_ptr(),
656                StorageType::Storage(b) => b.as_ptr(),
657                StorageType::Vec(b) => b.as_ptr(),
658            }
659        }
660    }
661
662    #[inline]
663    #[doc(hidden)]
664    /// Returns the kind of storage backing this page.
665    pub fn info(&self) -> crate::info::PageKind {
666        match &self.inner {
667            StorageType::Bytes(_) => crate::info::PageKind::Bytes,
668            StorageType::Storage(_) => crate::info::PageKind::Storage,
669            StorageType::Vec(_) => crate::info::PageKind::Vec,
670        }
671    }
672
673    #[inline]
674    #[doc(hidden)]
675    /// Returns `true` if the data is stored inside the `BytePage` itself.
676    ///
677    /// Moving an inline page moves its data, pointers from `as_ptr()` do not
678    /// survive the move.
679    pub fn is_inline(&self) -> bool {
680        matches!(&self.inner, StorageType::Bytes(b) if b.is_inline())
681    }
682
683    /// Splits the buffer into two at the given index.
684    ///
685    /// Afterwards, `self` contains elements `[at, len)`, and the returned `BytePage`
686    /// contains elements `[0, at)`. If `at > len`, all data is moved.
687    ///
688    /// Depending on the underlying storage, this operation might be `O(1)` or could
689    /// involve a memory copy.
690    #[must_use]
691    pub fn split_to(&mut self, at: usize) -> BytePage {
692        match &mut self.inner {
693            StorageType::Bytes(b) => {
694                let buf = b.split_to(cmp::min(at, b.len()));
695                BytePage {
696                    inner: StorageType::Bytes(buf),
697                }
698            }
699            StorageType::Storage(_) => {
700                let inner = mem::replace(&mut self.inner, StorageType::Bytes(Bytes::new()));
701                if let StorageType::Storage(st) = inner {
702                    self.inner = StorageType::Bytes(Bytes {
703                        storage: st.freeze(),
704                    });
705                    self.split_to(at)
706                } else {
707                    unreachable!()
708                }
709            }
710            StorageType::Vec(_) => {
711                let inner = mem::replace(&mut self.inner, StorageType::Bytes(Bytes::new()));
712                if let StorageType::Vec(b) = inner {
713                    self.inner = StorageType::Bytes(Bytes::copy_from_slice(&b));
714                    self.split_to(at)
715                } else {
716                    unreachable!()
717                }
718            }
719        }
720    }
721
722    /// Advance the internal cursor.
723    ///
724    /// Afterwards `self` contains elements `[cnt, len)`.
725    /// This is an `O(1)` operation, except for pages backed by a `Vec<u8>`,
726    /// whose remaining data is copied.
727    ///
728    /// # Panics
729    ///
730    /// Panics if `cnt > len`.
731    #[inline]
732    pub fn advance_to(&mut self, cnt: usize) {
733        match &mut self.inner {
734            StorageType::Bytes(b) => b.advance_to(cnt),
735            StorageType::Storage(b) => unsafe { b.set_start(cnt) },
736            StorageType::Vec(b) => {
737                assert!(
738                    cnt <= b.len(),
739                    "cannot advance past the end of the buffer, cnt:{cnt} len:{}",
740                    b.len()
741                );
742                self.inner = StorageType::Bytes(Bytes::copy_from_slice(&b[cnt..]));
743            }
744        }
745    }
746
747    /// Converts `self` into an immutable `Bytes`.
748    #[inline]
749    #[must_use]
750    pub fn freeze(self) -> Bytes {
751        match self.inner {
752            StorageType::Bytes(b) => b,
753            StorageType::Storage(st) => Bytes {
754                storage: st.freeze(),
755            },
756            StorageType::Vec(v) => Bytes::from(v),
757        }
758    }
759
760    fn into_storage(self) -> Result<StorageVec, Self> {
761        if let StorageType::Storage(st) = self.inner {
762            // SAFETY: Converting back to `StorageVec` requires uniqueness.
763            if !st.is_full() && st.is_unique() {
764                Ok(st)
765            } else {
766                Err(Self {
767                    inner: StorageType::Storage(st),
768                })
769            }
770        } else {
771            Err(self)
772        }
773    }
774}
775
776impl Clone for BytePage {
777    fn clone(&self) -> Self {
778        let inner = match &self.inner {
779            StorageType::Bytes(b) => StorageType::Bytes(b.clone()),
780            // The clone is an immutable view, `st` must stay the only
781            // handle that can modify the shared header and spare capacity
782            StorageType::Storage(st) => StorageType::Bytes(Bytes {
783                storage: st.shallow_freeze(),
784            }),
785            StorageType::Vec(b) => StorageType::Bytes(Bytes::copy_from_slice(b)),
786        };
787
788        Self { inner }
789    }
790}
791
792impl AsRef<[u8]> for BytePage {
793    #[inline]
794    fn as_ref(&self) -> &[u8] {
795        match &self.inner {
796            StorageType::Bytes(b) => b.as_ref(),
797            StorageType::Storage(b) => b.as_ref(),
798            StorageType::Vec(b) => b.as_ref(),
799        }
800    }
801}
802
803impl Borrow<[u8]> for BytePage {
804    #[inline]
805    fn borrow(&self) -> &[u8] {
806        self.as_ref()
807    }
808}
809
810impl From<Bytes> for BytePage {
811    fn from(buf: Bytes) -> Self {
812        BytePage {
813            inner: StorageType::Bytes(buf),
814        }
815    }
816}
817
818impl<'a> From<&'a Bytes> for BytePage {
819    fn from(buf: &'a Bytes) -> Self {
820        BytePage {
821            inner: StorageType::Bytes(buf.clone()),
822        }
823    }
824}
825
826impl From<BytesMut> for BytePage {
827    fn from(buf: BytesMut) -> Self {
828        BytePage {
829            inner: StorageType::Storage(buf.storage),
830        }
831    }
832}
833
834impl From<ByteString> for BytePage {
835    fn from(s: ByteString) -> Self {
836        s.into_bytes().into()
837    }
838}
839
840impl<'a> From<&'a ByteString> for BytePage {
841    fn from(s: &'a ByteString) -> Self {
842        s.clone().into_bytes().into()
843    }
844}
845
846impl From<StorageVec> for BytePage {
847    fn from(buf: StorageVec) -> Self {
848        BytePage {
849            inner: StorageType::Storage(buf),
850        }
851    }
852}
853
854impl From<Vec<u8>> for BytePage {
855    fn from(buf: Vec<u8>) -> Self {
856        BytePage {
857            inner: StorageType::Vec(buf),
858        }
859    }
860}
861
862impl From<&'static str> for BytePage {
863    fn from(buf: &'static str) -> Self {
864        Bytes::from_static(buf.as_bytes()).into()
865    }
866}
867
868impl From<&'static [u8]> for BytePage {
869    fn from(buf: &'static [u8]) -> Self {
870        Bytes::from_static(buf).into()
871    }
872}
873
874impl<const N: usize> From<&'static [u8; N]> for BytePage {
875    fn from(buf: &'static [u8; N]) -> Self {
876        Bytes::from_static(buf).into()
877    }
878}
879
880impl From<BytePage> for Bytes {
881    fn from(page: BytePage) -> Self {
882        match page.inner {
883            StorageType::Bytes(b) => b,
884            StorageType::Storage(storage) => BytesMut { storage }.freeze(),
885            StorageType::Vec(v) => Bytes::copy_from_slice(&v),
886        }
887    }
888}
889
890impl From<BytePage> for BytesMut {
891    fn from(page: BytePage) -> Self {
892        match page.inner {
893            StorageType::Bytes(b) => b.into(),
894            // clones of the page may still read the data
895            StorageType::Storage(storage) => {
896                if storage.is_unique() {
897                    BytesMut { storage }
898                } else {
899                    BytesMut::copy_from_slice(storage.as_ref())
900                }
901            }
902            StorageType::Vec(v) => BytesMut::copy_from_slice(&v),
903        }
904    }
905}
906
907impl PartialEq for BytePage {
908    fn eq(&self, other: &BytePage) -> bool {
909        self.as_ref() == other.as_ref()
910    }
911}
912
913impl_partial_eq!(BytePage);
914
915impl_read!(BytePage);
916
917impl ops::Deref for BytePage {
918    type Target = [u8];
919
920    #[inline]
921    fn deref(&self) -> &[u8] {
922        self.as_ref()
923    }
924}
925
926impl fmt::Debug for BytePage {
927    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
928        fmt::Debug::fmt(&crate::debug::BsDebug(self.as_ref()), fmt)
929    }
930}
931
932#[cfg(test)]
933mod tests {
934    use rand::Rng;
935
936    use super::*;
937
938    #[test]
939    #[allow(clippy::op_ref, clippy::cmp_owned)]
940    fn page_eq_and_read() {
941        use std::io::Read;
942
943        let mut page = BytePage::from(Vec::from(&b"hello"[..]));
944        assert_eq!(page, b"hello"[..]);
945        assert_eq!(page, *b"hello");
946        assert_eq!(page, b"hello");
947        assert_eq!(page, &b"hello"[..]);
948        assert_eq!(page, "hello");
949        assert_eq!(page, *"hello");
950        assert_eq!(page, b"hello".to_vec());
951        assert_eq!(page, String::from("hello"));
952        assert_eq!(b"hello"[..], page);
953        assert_eq!(*b"hello", page);
954        assert_eq!(b"hello", page);
955        assert_eq!(&b"hello"[..], page);
956        assert_eq!("hello", page);
957        assert_eq!(*"hello", page);
958        assert_eq!(b"hello".to_vec(), page);
959        assert_eq!(String::from("hello"), page);
960        assert_ne!(page, "hell");
961
962        let mut buf = [0u8; 3];
963        assert_eq!(page.read(&mut buf).unwrap(), 3);
964        assert_eq!(&buf, b"hel");
965        assert_eq!(page, "lo");
966        assert_eq!(page.read(&mut buf).unwrap(), 2);
967        assert_eq!(page.read(&mut buf).unwrap(), 0);
968        assert!(page.is_empty());
969    }
970
971    #[test]
972    fn page_info() {
973        use crate::info::PageKind;
974
975        let p = BytePage::from(Bytes::copy_from_slice(&[1; 64]));
976        assert_eq!(p.info(), PageKind::Bytes);
977        let p = BytePage::from(BytesMut::copy_from_slice(&[1; 64][..]));
978        assert_eq!(p.info(), PageKind::Storage);
979        let p = BytePage::from(vec![1; 64]);
980        assert_eq!(p.info(), PageKind::Vec);
981        assert!(!p.is_inline());
982
983        assert!(BytePage::from(Bytes::copy_from_slice(&[1; 4])).is_inline());
984        assert!(!BytePage::from(Bytes::copy_from_slice(&[1; 64])).is_inline());
985        assert!(!BytePage::from(BytesMut::copy_from_slice(&[1; 4][..])).is_inline());
986    }
987
988    #[test]
989    fn append_copies_small_and_splits_for_large() {
990        let cap = BytePageSize::Size16.capacity();
991        let mut pages = BytePages::new(BytePageSize::Size16);
992        pages.extend_from_slice(b"head\r\n");
993
994        // small data is copied into the current page
995        pages.append(Bytes::copy_from_slice(&[1; APPEND_COPY_LIMIT]));
996        assert_eq!(pages.num_pages(), 1);
997        assert_eq!(pages.current_len(), 6 + APPEND_COPY_LIMIT);
998
999        // large data is not copied, the filled part is split off in front
1000        let body = Bytes::copy_from_slice(&[2; APPEND_COPY_LIMIT + 1]);
1001        let body_ptr = body.as_ptr();
1002        pages.append(body.clone());
1003        assert_eq!(pages.num_pages(), 2);
1004        assert_eq!(pages.current_len(), 0);
1005        assert_eq!(pages.spare(), cap - 6 - APPEND_COPY_LIMIT);
1006
1007        // later writes use the spare capacity of the current page
1008        let page_ptr = pages.pages()[0].as_ref().as_ptr();
1009        pages.extend_from_slice(b"\r\n");
1010        assert_eq!(pages.num_pages(), 3);
1011        let tail_ptr = pages.current.as_ref().unwrap().as_ref().as_ptr();
1012        assert_eq!(tail_ptr, page_ptr.wrapping_add(6 + APPEND_COPY_LIMIT));
1013
1014        let mut expected = b"head\r\n".to_vec();
1015        expected.extend_from_slice(&[1; APPEND_COPY_LIMIT]);
1016        expected.extend_from_slice(&body);
1017        expected.extend_from_slice(b"\r\n");
1018        assert_eq!(pages.len(), expected.len());
1019
1020        let first = pages.take().unwrap();
1021        let second = pages.take().unwrap();
1022        assert_eq!(second.as_ref().as_ptr(), body_ptr);
1023        let third = pages.take().unwrap();
1024        assert!(pages.take().is_none());
1025        let data = [first.as_ref(), second.as_ref(), third.as_ref()].concat();
1026        assert_eq!(data, expected);
1027
1028        // draining the pages keeps an empty current page for later writes
1029        pages.extend_from_slice(b"x");
1030        pages.append(body);
1031        assert_eq!(pages.take().unwrap().as_ref(), b"x");
1032        assert_eq!(pages.take().unwrap().len(), APPEND_COPY_LIMIT + 1);
1033        assert!(pages.take().is_none());
1034        assert_eq!(pages.num_pages(), 0);
1035        assert_eq!(pages.spare(), cap - 1);
1036    }
1037
1038    #[test]
1039    fn pages() {
1040        let cap = BytePageSize::Size8.capacity();
1041        unsafe {
1042            // pages
1043            let mut pages = BytePages::new(BytePageSize::Size8);
1044            assert!(pages.is_empty());
1045            assert_eq!(pages.len(), 0);
1046            assert_eq!(pages.num_pages(), 0);
1047            pages.extend_from_slice(b"b");
1048            assert_eq!(pages.len(), 1);
1049            assert_eq!(pages.num_pages(), 1);
1050            pages.extend_from_slice("a".repeat(9 * 1024).as_bytes());
1051            assert_eq!(pages.len(), 9217);
1052            assert_eq!(pages.num_pages(), 2);
1053            assert!(!pages.is_empty());
1054
1055            let mut pgs = BytePages::new(BytePageSize::Size8);
1056            pgs.put_i8(b'a' as i8);
1057            let p = pgs.take().unwrap();
1058            assert_eq!(p.len(), 1);
1059            assert_eq!(p.as_ref(), b"a");
1060
1061            pgs.extend_from_slice("a".repeat(cap - 1).as_bytes());
1062            assert_eq!(pgs.num_pages(), 1);
1063            pgs.put_u8(b'a');
1064            assert_eq!(pgs.num_pages(), 1);
1065            assert!(pgs.current.is_none());
1066
1067            pgs.put_u8(b'a');
1068            assert_eq!(pgs.num_pages(), 2);
1069
1070            pgs.append(Bytes::copy_from_slice("a".repeat(cap).as_bytes()));
1071            assert_eq!(pgs.num_pages(), 3);
1072            assert_eq!(pgs.current_len(), 0);
1073            assert_eq!(pgs.spare(), cap - 1);
1074
1075            // page
1076            let p = pages.take().unwrap();
1077            assert_eq!(p.len(), cap);
1078            let p = pages.take().unwrap();
1079            assert_eq!(p.len(), 9217 - cap);
1080            assert!(!p.is_empty());
1081            assert_eq!(p.as_ref().as_ptr(), p.as_ptr());
1082            assert_eq!(p.as_ref(), "a".repeat(9217 - cap).as_bytes());
1083            assert!(pages.take().is_none());
1084
1085            let p = BytePage::from(Bytes::copy_from_slice(b"123"));
1086            assert_eq!(p.len(), 3);
1087            assert!(!p.is_empty());
1088            assert_eq!(p.as_ref(), b"123");
1089            assert_eq!(p.as_ref().as_ptr(), p.as_ptr());
1090
1091            let p = BytePage::from(&b"123"[..]);
1092            assert_eq!(p.len(), 3);
1093            assert!(!p.is_empty());
1094            assert_eq!(p.as_ref(), b"123");
1095            assert_eq!(p.as_ref().as_ptr(), p.as_ptr());
1096
1097            let p = BytePage::from(b"123");
1098            assert_eq!(p.len(), 3);
1099            assert!(!p.is_empty());
1100            assert_eq!(p.as_ref(), b"123");
1101            assert_eq!(p.as_ref().as_ptr(), p.as_ptr());
1102
1103            let p = BytePage::from("123");
1104            assert_eq!(p.len(), 3);
1105            assert!(!p.is_empty());
1106            assert_eq!(p.as_ref(), b"123");
1107            assert_eq!(p.as_ref().as_ptr(), p.as_ptr());
1108            assert_eq!(p.freeze(), b"123");
1109
1110            let p = BytePage::from(vec![b'1', b'2', b'3']);
1111            assert_eq!(p.len(), 3);
1112            assert!(!p.is_empty());
1113            assert_eq!(p.as_ref(), b"123");
1114            assert_eq!(p.as_ref().as_ptr(), p.as_ptr());
1115            assert_eq!(p.freeze(), b"123");
1116
1117            let mut p = BytePage::from(vec![b'1', b'2', b'3']);
1118            p.advance_to(1);
1119            assert_eq!(p.len(), 2);
1120            assert!(!p.is_empty());
1121            assert_eq!(p.as_ref(), b"23");
1122
1123            // debug
1124            let mut pages = BytePages::new(BytePageSize::Size8);
1125            pages.extend_from_slice(b"b");
1126            assert_eq!(format!("{pages:?}"), "BytePages(b\"b\")");
1127            let p = pages.take().unwrap();
1128            assert_eq!(p.as_ref(), b"b");
1129
1130            let mut pages = BytePages::new(BytePageSize::Size8);
1131            pages.extend_from_slice(b"a");
1132            pages.append(Bytes::copy_from_slice(b"123"));
1133            pages.push_back(p);
1134            assert_eq!(format!("{pages:?}"), "BytePages(b\"b\", b\"a123\")");
1135
1136            assert_eq!(pages.len(), 5);
1137            pages.clear();
1138            assert_eq!(pages.len(), 0);
1139        }
1140    }
1141
1142    /// Checks the tracked length against the pages.
1143    fn assert_len(pages: &BytePages) {
1144        let len = pages.pages().iter().map(BytePage::len).sum::<usize>() + pages.current_len();
1145        assert_eq!(pages.len(), len);
1146        assert_eq!(pages.is_empty(), len == 0);
1147    }
1148
1149    #[test]
1150    fn pages_len_tracking() {
1151        let mut rng = rand::rng();
1152        let mut pages = BytePages::new(BytePageSize::Size8);
1153        let mut other = BytePages::new(BytePageSize::Size8);
1154        let mut expected = 0;
1155
1156        let (iters, max) = if cfg!(miri) { (100, 256) } else { (2000, 12 * 1024) };
1157        for _ in 0..iters {
1158            let n = rng.random_range(0..max);
1159            match rng.random_range(0..9) {
1160                0 => {
1161                    pages.extend_from_slice(&vec![1; n]);
1162                    expected += n;
1163                }
1164                1 => {
1165                    pages.append(Bytes::copy_from_slice(&vec![2; n]));
1166                    expected += n;
1167                }
1168                2 => {
1169                    if pages.prepend(BytesMut::copy_from_slice(vec![3; n])) {
1170                        expected += n;
1171                    }
1172                }
1173                3 => {
1174                    if let Some(p) = pages.take() {
1175                        expected -= p.len();
1176                    }
1177                }
1178                4 => {
1179                    let at = cmp::min(n, expected);
1180                    let split = pages.split_to(at);
1181                    assert_len(&split);
1182                    assert_eq!(split.len(), at);
1183                    expected -= at;
1184                }
1185                5 => {
1186                    let at = cmp::min(n, expected);
1187                    pages.split_into(at, &mut other);
1188                    expected -= at;
1189                }
1190                6 => {
1191                    other.move_to(&mut pages);
1192                    assert_len(&other);
1193                    assert!(other.is_empty());
1194                    expected = pages.len();
1195                }
1196                7 => {
1197                    let mut copy = BytePages::new(BytePageSize::Size8);
1198                    pages.copy_to(&mut copy);
1199                    assert_len(&copy);
1200                    assert_eq!(copy.len(), expected);
1201                }
1202                _ => {
1203                    pages.put_u8(4);
1204                    expected += 1;
1205                }
1206            }
1207            assert_len(&pages);
1208            assert_len(&other);
1209            assert_eq!(pages.len(), expected);
1210        }
1211
1212        let len = pages.len();
1213        assert_eq!(pages.freeze().len(), len);
1214        assert_len(&pages);
1215        assert!(pages.is_empty());
1216        pages.extend_from_slice(b"123");
1217        pages.clear();
1218        assert_len(&pages);
1219        assert!(pages.is_empty());
1220    }
1221
1222    #[test]
1223    fn pages_len_after_cache_reuse() {
1224        let mut pages = BytePages::new(BytePageSize::Size8);
1225        pages.append(Bytes::copy_from_slice(&[1; 64]));
1226        pages.append(Bytes::copy_from_slice(&[1; 64]));
1227        drop(pages);
1228
1229        let pages = BytePages::new(BytePageSize::Size8);
1230        assert_len(&pages);
1231        assert!(pages.is_empty());
1232    }
1233
1234    #[test]
1235    fn pages_copy_to_shares_current() {
1236        let mut pages = BytePages::new(BytePageSize::Size8);
1237        pages.put_slice(&[1; 64]);
1238        let ptr = unsafe { pages.current.as_ref().unwrap().as_ptr() };
1239
1240        let mut copy = BytePages::new(BytePageSize::Size8);
1241        pages.copy_to(&mut copy);
1242        let page = copy.take().unwrap();
1243        assert_eq!(unsafe { page.as_ptr() }, ptr.cast_const());
1244        assert_eq!(page.as_ref(), &[1; 64][..]);
1245
1246        // the source keeps writing to the page it shares with the copy
1247        pages.put_slice(&[2; 64]);
1248        assert_eq!(unsafe { pages.current.as_ref().unwrap().as_ptr() }, ptr);
1249        assert_eq!(page.as_ref(), &[1; 64][..]);
1250        assert_eq!(pages.len(), 128);
1251
1252        drop(pages);
1253        assert_eq!(page.as_ref(), &[1; 64][..]);
1254    }
1255
1256    #[test]
1257    fn pages_split_keeps_current_writable() {
1258        let mut pages = BytePages::new(BytePageSize::Size8);
1259        pages.put_slice(&[1; 64]);
1260        let ptr = unsafe { pages.current.as_ref().unwrap().as_ptr() };
1261        let remaining = pages.spare();
1262
1263        let mut head = pages.split_to(40);
1264        assert_eq!(head.len(), 40);
1265        assert_eq!(pages.len(), 24);
1266        assert_eq!(pages.num_pages(), 1);
1267        assert_eq!(pages.spare(), remaining);
1268
1269        // new data goes into the same page
1270        pages.put_slice(&[2; 16]);
1271        assert_eq!(pages.num_pages(), 1);
1272        assert_eq!(
1273            unsafe { pages.current.as_ref().unwrap().as_ptr() },
1274            ptr.wrapping_add(40)
1275        );
1276        let mut expected = vec![1; 24];
1277        expected.extend_from_slice(&[2; 16]);
1278        assert_eq!(&pages.freeze()[..], &expected[..]);
1279        assert_eq!(&head.freeze()[..], &[1; 40][..]);
1280
1281        // an inline head
1282        let mut pages = BytePages::new(BytePageSize::Size8);
1283        pages.put_slice(&[1; 64]);
1284        let mut to = BytePages::new(BytePageSize::Size8);
1285        pages.split_into(2, &mut to);
1286        assert_eq!(&to.freeze()[..], &[1; 2][..]);
1287        assert_eq!(pages.spare(), remaining);
1288        assert_eq!(pages.len(), 62);
1289
1290        // the whole current page moves with its spare capacity
1291        let mut pages = BytePages::new(BytePageSize::Size8);
1292        pages.put_slice(&[1; 64]);
1293        let ptr = unsafe { pages.current.as_ref().unwrap().as_ptr() };
1294        let to = pages.split_to(64);
1295        assert!(pages.is_empty());
1296        assert_eq!(pages.num_pages(), 0);
1297        assert_eq!(to.spare(), remaining);
1298        assert_eq!(unsafe { to.current.as_ref().unwrap().as_ptr() }, ptr);
1299
1300        // an empty current page stays in place
1301        let mut pages = BytePages::new(BytePageSize::Size8);
1302        let _ = pages.chunk_mut();
1303        let head = pages.split_to(10);
1304        assert!(head.is_empty());
1305        assert_eq!(pages.spare(), remaining + 64);
1306    }
1307
1308    #[test]
1309    fn pages_buf_mut_grows() {
1310        let mut pages = BytePages::new(BytePageSize::Size8);
1311        assert!(pages.has_remaining_mut());
1312        assert_eq!(pages.remaining_mut(), usize::MAX);
1313        unsafe { pages.advance_mut(0) };
1314
1315        // filling the current page through `chunk_mut` starts a new one
1316        let n = pages.chunk_mut().len();
1317        unsafe {
1318            std::ptr::write_bytes(pages.chunk_mut().as_mut_ptr(), 1, n);
1319            pages.advance_mut(n);
1320        }
1321        assert!(pages.chunk_mut().len() > 0);
1322        // the new current page holds no data yet
1323        assert_eq!(pages.num_pages(), 1);
1324        unsafe {
1325            *pages.chunk_mut().as_mut_ptr() = 2;
1326            pages.advance_mut(1);
1327        }
1328        assert_eq!(pages.len(), n + 1);
1329        assert_eq!(pages.remaining_mut(), usize::MAX - n - 1);
1330
1331        // `put` and `io::Write` are not limited to the current page
1332        let mut pages = BytePages::new(BytePageSize::Size8);
1333        pages.put(&[3u8; 200][..]);
1334        pages.put(Bytes::from_static(b"abcd"));
1335        io::Write::write_all(&mut pages, &[4; 100]).unwrap();
1336        let mut expected = vec![3; 200];
1337        expected.extend_from_slice(b"abcd");
1338        expected.extend_from_slice(&[4; 100]);
1339        assert_eq!(&pages.freeze()[..], &expected[..]);
1340    }
1341
1342    #[test]
1343    #[should_panic(expected = "cannot advance past the current page")]
1344    fn pages_advance_past_current_page() {
1345        let mut pages = BytePages::new(BytePageSize::Size8);
1346        let n = pages.chunk_mut().len();
1347        unsafe { pages.advance_mut(n + 1) };
1348    }
1349
1350    #[test]
1351    #[should_panic(expected = "Page size cannot be Unset")]
1352    fn pages_new_unset() {
1353        let _ = BytePages::new(BytePageSize::Unset);
1354    }
1355
1356    #[test]
1357    #[should_panic(expected = "Page size cannot be Unset")]
1358    fn pages_set_page_size_unset() {
1359        let mut pages = BytePages::new(BytePageSize::Size8);
1360        pages.set_page_size(BytePageSize::Unset);
1361    }
1362
1363    #[test]
1364    fn cached_pages_list_is_shrunk() {
1365        let mut pages = BytePages::new(BytePageSize::Size4);
1366        for _ in 0..200 {
1367            pages.append(Bytes::from_static(b"page"));
1368        }
1369        assert!(pages.pages().capacity() >= 200);
1370        drop(pages);
1371
1372        let pages = BytePages::new(BytePageSize::Size4);
1373        assert!(
1374            pages.pages().capacity() < 200,
1375            "{}",
1376            pages.pages().capacity()
1377        );
1378    }
1379
1380    #[test]
1381    fn pages_into_bytes_single_page() {
1382        // the current page
1383        let mut pages = BytePages::new(BytePageSize::Size8);
1384        pages.put_slice(&[1; 64]);
1385        let ptr = unsafe { pages.current.as_ref().unwrap().as_ptr() };
1386        let mut buf = BytesMut::from(pages);
1387        assert_eq!(buf.as_ptr(), ptr.cast_const());
1388        assert_eq!(&buf[..], &[1; 64][..]);
1389        // the rest of the page is spare capacity
1390        assert_eq!(buf.capacity(), BytePageSize::Size8.capacity());
1391        buf.extend_from_slice(&[2; 64]);
1392        assert_eq!(buf.as_ptr(), ptr.cast_const());
1393
1394        let mut pages = BytePages::new(BytePageSize::Size8);
1395        pages.put_slice(&[1; 64]);
1396        let ptr = unsafe { pages.current.as_ref().unwrap().as_ptr() };
1397        let b = Bytes::from(pages);
1398        assert_eq!(b.as_ptr(), ptr.cast_const());
1399        assert_eq!(&b[..], &[1; 64][..]);
1400
1401        // a `Bytes` page
1402        let src = Bytes::copy_from_slice(&[3; 64]);
1403        let ptr = src.as_ptr();
1404        let mut pages = BytePages::new(BytePageSize::Size8);
1405        pages.prepend(src);
1406        assert_eq!(BytesMut::from(pages).as_ptr(), ptr);
1407
1408        // a shared page is copied
1409        let src = Bytes::copy_from_slice(&[3; 64]);
1410        let mut pages = BytePages::new(BytePageSize::Size8);
1411        pages.prepend(&src);
1412        let mut buf = BytesMut::from(pages);
1413        assert_ne!(buf.as_ptr(), src.as_ptr());
1414        buf[0] = 4;
1415        assert_eq!(&src[..], &[3; 64][..]);
1416    }
1417
1418    #[test]
1419    fn pages_into_bytes_multiple_pages() {
1420        let mut pages = BytePages::new(BytePageSize::Size8);
1421        pages.prepend(Bytes::copy_from_slice(&[1; 64]));
1422        pages.put_slice(&[2; 64]);
1423        assert_eq!(pages.num_pages(), 2);
1424        let buf = BytesMut::from(pages);
1425        assert_eq!(&buf[..64], &[1; 64][..]);
1426        assert_eq!(&buf[64..], &[2; 64][..]);
1427
1428        let mut pages = BytePages::new(BytePageSize::Size8);
1429        pages.prepend(Bytes::copy_from_slice(&[1; 64]));
1430        pages.put_slice(&[2; 64]);
1431        let b = Bytes::from(pages);
1432        assert_eq!(&b[..64], &[1; 64][..]);
1433        assert_eq!(&b[64..], &[2; 64][..]);
1434
1435        assert!(BytesMut::from(BytePages::new(BytePageSize::Size8)).is_empty());
1436        assert!(Bytes::from(BytePages::new(BytePageSize::Size8)).is_empty());
1437    }
1438
1439    #[test]
1440    fn pages_copy_to() {
1441        let mut pages = BytePages::default();
1442        let mut pages2 = BytePages::default();
1443        pages.put_slice(b"456");
1444        pages.prepend(BytePage::from(Bytes::copy_from_slice(b"123")));
1445        pages.copy_to(&mut pages2);
1446        let p = pages.freeze();
1447        assert_eq!(p, b"123456");
1448        let p2 = pages2.freeze();
1449        assert_eq!(p2, b"123456");
1450
1451        let mut pages = BytePages::default();
1452        let mut pages2 = BytePages::default();
1453        pages.put_slice(b"456");
1454        pages.prepend(BytePage::from(Bytes::copy_from_slice(b"123")));
1455        pages.copy_to(&mut pages2);
1456        pages.put_u8(b'7');
1457        let p = pages.freeze();
1458        assert_eq!(p, b"1234567");
1459        let p2 = pages2.freeze();
1460        assert_eq!(p2, b"123456");
1461
1462        let mut pages = BytePages::default();
1463        pages.put_slice(b"456");
1464        pages.prepend(BytePage::from(Bytes::copy_from_slice(b"123")));
1465        let mut pages2 = pages.clone();
1466        pages.put_u8(b'7');
1467        let p = pages.freeze();
1468        assert_eq!(p, b"1234567");
1469        let p2 = pages2.freeze();
1470        assert_eq!(p2, b"123456");
1471    }
1472
1473    #[test]
1474    fn pages_methods() {
1475        // .split_to()
1476        let mut pages = BytePages::default();
1477        pages.put_slice(b"456");
1478        pages.prepend(BytePage::from(&Bytes::copy_from_slice(b"123")));
1479        let mut pages2 = pages.split_to(1);
1480        let p = pages.freeze();
1481        assert_eq!(p, b"23456");
1482        let p2 = pages2.freeze();
1483        assert_eq!(p2, b"1");
1484
1485        let mut pages = BytePages::default();
1486        pages.put_slice(b"456");
1487        pages.prepend(BytePage::from(Bytes::copy_from_slice(b"123")));
1488        let mut pages2 = pages.split_to(4);
1489        let p = pages.freeze();
1490        assert_eq!(p, b"56");
1491        let p2 = pages2.freeze();
1492        assert_eq!(p2, b"1234");
1493
1494        // .split_into()
1495        let mut pages = BytePages::default();
1496        pages.put_slice(b"456");
1497        pages.prepend(BytePage::from(crate::ByteString::from_static("123")));
1498        let mut pages2 = BytePages::default();
1499        pages.split_into(1, &mut pages2);
1500        let p = pages.freeze();
1501        assert_eq!(p, b"23456");
1502        let p2 = pages2.freeze();
1503        assert_eq!(p2, b"1");
1504
1505        // .with_bytes_mut()
1506        let mut pages = BytePages::default();
1507        #[allow(deprecated)]
1508        pages.with_bytes_mut(|buf| buf.extend_from_slice(b"123"));
1509        assert_eq!(pages.len(), 3);
1510        let p = pages.freeze();
1511        assert_eq!(p, b"123");
1512
1513        let data = rand::rng()
1514            .sample_iter(&rand::distr::Alphanumeric)
1515            .take(65_536)
1516            .map(char::from)
1517            .collect::<String>();
1518
1519        let mut pages = BytePages::default();
1520        #[allow(deprecated)]
1521        pages.with_bytes_mut(|buf| buf.extend_from_slice(data.as_bytes()));
1522        assert_eq!(pages.len(), 65_536);
1523        let p = pages.freeze();
1524        assert_eq!(p, data.as_bytes());
1525
1526        // into bytes
1527        let page = BytePage::from(Bytes::copy_from_slice(b"123"));
1528        assert_eq!(page, b"123");
1529        assert_eq!(<BytePage as Borrow<[u8]>>::borrow(&page), b"123");
1530        let b = Bytes::from(page);
1531        assert_eq!(b, b"123");
1532    }
1533
1534    #[test]
1535    fn page_clone() {
1536        // Bytes storage
1537        let p = BytePage::from(Bytes::copy_from_slice(b"123"));
1538        let p2 = p.clone();
1539        assert_eq!(p, p2);
1540
1541        // StorageVec
1542        let mut p = BytePage::from(BytesMut::copy_from_slice(b"123"));
1543        if let StorageType::Storage(ref mut st) = p.inner {
1544            assert!(st.is_unique());
1545        } else {
1546            panic!()
1547        }
1548        let p2 = p.clone();
1549        assert_eq!(p, p2);
1550        // short data is copied into an inline view
1551        assert!(matches!(p2.inner, StorageType::Bytes(_)));
1552        if let StorageType::Storage(st) = p.inner {
1553            assert!(st.is_unique());
1554        } else {
1555            panic!()
1556        }
1557
1558        let mut p = BytePage::from(BytesMut::copy_from_slice([b'1'; 64]));
1559        let p2 = p.clone();
1560        assert_eq!(p, p2);
1561        assert!(matches!(p2.inner, StorageType::Bytes(_)));
1562        if let StorageType::Storage(ref mut st) = p.inner {
1563            assert!(!st.is_unique());
1564        } else {
1565            panic!()
1566        }
1567        drop(p2);
1568        if let StorageType::Storage(st) = p.inner {
1569            assert!(st.is_unique());
1570        } else {
1571            panic!()
1572        }
1573
1574        // Vec<u8> storage
1575        let p = BytePage::from(vec![b'1', b'2', b'3']);
1576        let p2 = p.clone();
1577        assert_eq!(p, p2);
1578        if let StorageType::Bytes(_) = p2.inner {
1579        } else {
1580            panic!()
1581        }
1582    }
1583
1584    #[test]
1585    fn page_split_to() {
1586        // Bytes storage
1587        let mut p = BytePage::from(Bytes::copy_from_slice(b"123"));
1588        let p2 = p.split_to(1);
1589        assert_eq!(p, b"23");
1590        assert_eq!(p2, b"1");
1591
1592        // StorageVec
1593        let mut p = BytePage::from(BytesMut::copy_from_slice(b"123"));
1594        let p2 = p.split_to(1);
1595        assert_eq!(p, b"23");
1596        assert_eq!(p2, b"1");
1597
1598        // Vec<u8> storage
1599        let mut p = BytePage::from(vec![b'1', b'2', b'3']);
1600        let p2 = p.split_to(1);
1601        assert_eq!(p, b"23");
1602        assert_eq!(p2, b"1");
1603    }
1604
1605    #[test]
1606    fn page_read() {
1607        use std::io::Read;
1608
1609        let mut page = BytePage::from(Bytes::copy_from_slice(b"123"));
1610
1611        let mut buf = [0; 10];
1612        assert_eq!(page.read(&mut buf).unwrap(), 3);
1613        assert_eq!(page.len(), 0);
1614        assert_eq!(buf, [49, 50, 51, 0, 0, 0, 0, 0, 0, 0]);
1615    }
1616
1617    #[test]
1618    fn pages_misc() {
1619        let mut pages = BytePages::new(BytePageSize::Size4);
1620        pages.set_page_size(BytePageSize::Size8);
1621        assert_eq!(pages.page_size(), BytePageSize::Size8);
1622        assert!(!pages.prepend(Bytes::new()));
1623        assert!(pages.prepend(Bytes::from_static(b"a")));
1624
1625        io::Write::write_all(&mut pages, b"bc").unwrap();
1626        io::Write::flush(&mut pages).unwrap();
1627        assert_eq!(pages.freeze(), "abc");
1628
1629        let s = ByteString::from_static("str");
1630        pages.append(&s);
1631        assert_eq!(pages.freeze(), "str");
1632    }
1633
1634    #[test]
1635    fn pages_try_get_current_from() {
1636        let mut src = BytePages::new(BytePageSize::Size4);
1637        src.extend_from_slice(b"data");
1638
1639        // the target already holds data
1640        let mut dst = BytePages::new(BytePageSize::Size4);
1641        dst.append(Bytes::from_static(b"x"));
1642        dst.try_get_current_from(&mut src);
1643        assert_eq!(src.len(), 4);
1644        assert_eq!(dst.len(), 1);
1645
1646        let mut dst = BytePages::new(BytePageSize::Size4);
1647        dst.try_get_current_from(&mut src);
1648        assert_eq!(src.len(), 0);
1649        assert_eq!(dst.len(), 4);
1650        dst.extend_from_slice(b"!");
1651        assert_eq!(dst.freeze(), "data!");
1652    }
1653
1654    #[test]
1655    fn pages_drop_cache() {
1656        CACHE.with(|c| c.set(Some(Box::default())));
1657        let cached = || {
1658            CACHE.with(|c| {
1659                let cache = c.take().unwrap();
1660                let len = cache.len();
1661                c.set(Some(cache));
1662                len
1663            })
1664        };
1665
1666        // the cache is full
1667        let pages: Vec<_> = (0..=CACHE_SIZE)
1668            .map(|_| BytePages::new(BytePageSize::Size4))
1669            .collect();
1670        drop(pages);
1671        assert_eq!(cached(), CACHE_SIZE);
1672
1673        // the cache is in use
1674        CACHE.with(|c| c.set(Some(Box::default())));
1675        let pages = BytePages::new(BytePageSize::Size4);
1676        let cache = CACHE.with(Cell::take);
1677        drop(pages);
1678        CACHE.with(|c| c.set(cache));
1679        assert_eq!(cached(), 0);
1680    }
1681
1682    #[test]
1683    fn page_conversions() {
1684        let page = BytePage::from(BytesMut::copy_from_slice([1; 64]));
1685        assert_eq!(page.info(), crate::info::PageKind::Storage);
1686        assert_eq!(Bytes::from(page), &[1; 64][..]);
1687
1688        let page = BytePage::from(vec![2; 64]);
1689        assert_eq!(page.info(), crate::info::PageKind::Vec);
1690        assert_eq!(Bytes::from(page), &[2; 64][..]);
1691
1692        let page = BytePage::from(vec![3; 64]);
1693        assert_eq!(BytesMut::from(page), &[3; 64][..]);
1694
1695        let s = ByteString::from_static("string");
1696        assert_eq!(BytePage::from(&s), "string");
1697    }
1698
1699    #[test]
1700    fn append_storage_page() {
1701        // a page with spare capacity becomes the current page
1702        let mut pages = BytePages::new(BytePageSize::Size4);
1703        let mut buf = BytesMut::with_capacity(64);
1704        buf.extend_from_slice(b"a");
1705        pages.append(buf);
1706        pages.extend_from_slice(b"b");
1707        assert_eq!(pages.num_pages(), 1);
1708        assert_eq!(pages.freeze(), "ab");
1709
1710        // full and shared pages are added to the page list
1711        let mut buf = BytesMut::with_capacity(64);
1712        let cap = buf.capacity();
1713        buf.resize(cap, b'x');
1714        pages.append(buf);
1715        let page = BytePage::from(BytesMut::copy_from_slice([b'y'; 64]));
1716        let shared = page.clone();
1717        pages.append(page);
1718        pages.extend_from_slice(b"z");
1719        assert_eq!(pages.num_pages(), 3);
1720        assert_eq!(pages.len(), cap + 65);
1721        assert_eq!(shared, &[b'y'; 64][..]);
1722    }
1723
1724    // inline page, shared page, then the current page
1725    fn mixed_pages() -> BytePages {
1726        let mut pages = BytePages::new(BytePageSize::Size4);
1727        pages.extend_from_slice(b"current");
1728        pages.prepend(Bytes::copy_from_slice(&[b'b'; 64]));
1729        pages.prepend(Bytes::copy_from_slice(b"ab"));
1730        assert!(pages.pages()[0].is_inline());
1731        pages
1732    }
1733
1734    #[test]
1735    fn iter_pages() {
1736        let pages = BytePages::default();
1737        assert_eq!(pages.iter().count(), 0);
1738
1739        let pages = mixed_pages();
1740        let chunks: Vec<&[u8]> = pages.iter().collect();
1741        assert_eq!(chunks, [&b"ab"[..], &[b'b'; 64][..], &b"current"[..]]);
1742        assert_eq!(chunks.len(), pages.num_pages());
1743
1744        // data, including inline pages, does not move with `self`
1745        let ptrs: Vec<*const u8> = pages.iter().map(<[u8]>::as_ptr).collect();
1746        let moved = Box::new(pages);
1747        let moved_ptrs: Vec<*const u8> = moved.iter().map(<[u8]>::as_ptr).collect();
1748        assert_eq!(ptrs, moved_ptrs);
1749
1750        // an empty current page is skipped
1751        let mut pages = BytePages::new(BytePageSize::Size4);
1752        pages.extend_from_slice(b"data");
1753        pages.prepend(Bytes::copy_from_slice(b"ab"));
1754        pages.advance_to(6);
1755        assert_eq!(pages.iter().count(), 0);
1756        assert_eq!(pages.num_pages(), 0);
1757    }
1758
1759    #[test]
1760    fn advance_to_pages() {
1761        let mut pages = mixed_pages();
1762        let len = pages.len();
1763        pages.advance_to(0);
1764        assert_eq!(pages.len(), len);
1765
1766        // whole page
1767        pages.advance_to(2);
1768        assert_eq!(pages.len(), len - 2);
1769        assert_eq!(pages.num_pages(), 2);
1770        assert_eq!(pages.iter().next().unwrap(), &[b'b'; 64][..]);
1771
1772        // part of a page
1773        pages.advance_to(60);
1774        assert_eq!(pages.len(), 11);
1775        assert_eq!(pages.num_pages(), 2);
1776        let chunks: Vec<&[u8]> = pages.iter().collect();
1777        assert_eq!(chunks, [&b"bbbb"[..], &b"current"[..]]);
1778
1779        // rest of the page and part of the current page
1780        pages.advance_to(6);
1781        assert_eq!(pages.len(), 5);
1782        assert_eq!(pages.num_pages(), 1);
1783        assert_eq!(pages.iter().next().unwrap(), b"rrent");
1784
1785        // the current page keeps its spare capacity
1786        let ptr = pages.iter().next().unwrap().as_ptr();
1787        pages.advance_to(5);
1788        assert!(pages.is_empty());
1789        assert_eq!(pages.num_pages(), 0);
1790        pages.extend_from_slice(b"next");
1791        assert_eq!(pages.num_pages(), 1);
1792        assert_eq!(pages.iter().next().unwrap().as_ptr(), ptr.wrapping_add(5));
1793        assert_eq!(pages.freeze(), "next");
1794    }
1795
1796    #[test]
1797    fn move_to_keeps_pages() {
1798        // into empty pages, the page list is swapped
1799        let mut src = mixed_pages();
1800        let ptrs: Vec<*const u8> = src
1801            .iter()
1802            .filter(|s| s.len() > 2)
1803            .map(<[u8]>::as_ptr)
1804            .collect();
1805        let mut dst = BytePages::new(BytePageSize::Size16);
1806        src.move_to(&mut dst);
1807        assert!(src.is_empty());
1808        assert_eq!(src.num_pages(), 0);
1809        assert_eq!(dst.page_size(), BytePageSize::Size16);
1810        assert_eq!(dst.num_pages(), 3);
1811        assert_eq!(dst.len(), 73);
1812        let moved: Vec<*const u8> = dst
1813            .iter()
1814            .filter(|s| s.len() > 2)
1815            .map(<[u8]>::as_ptr)
1816            .collect();
1817        assert_eq!(ptrs, moved);
1818
1819        // small pages are not merged, the filled part of the current page
1820        // of `dst` goes first and its spare capacity is kept
1821        let mut dst = BytePages::new(BytePageSize::Size4);
1822        dst.extend_from_slice(b"first");
1823        dst.prepend(Bytes::copy_from_slice(b"0"));
1824        let mut src = mixed_pages();
1825        src.move_to(&mut dst);
1826        let chunks: Vec<&[u8]> = dst.iter().collect();
1827        assert_eq!(
1828            chunks,
1829            [
1830                &b"0"[..],
1831                &b"first"[..],
1832                &b"ab"[..],
1833                &[b'b'; 64][..],
1834                &b"current"[..]
1835            ]
1836        );
1837        assert_eq!(dst.len(), 79);
1838        dst.extend_from_slice(b"last");
1839        assert_eq!(dst.num_pages(), 6);
1840
1841        // empty source
1842        let mut src = BytePages::default();
1843        src.move_to(&mut dst);
1844        assert_eq!(dst.num_pages(), 6);
1845    }
1846
1847    #[test]
1848    fn advance_to_vec_page() {
1849        let mut pages = BytePages::default();
1850        pages.prepend(b"hello world".to_vec());
1851        pages.advance_to(6);
1852        assert_eq!(pages.len(), 5);
1853        assert_eq!(pages.freeze(), "world");
1854    }
1855
1856    #[test]
1857    #[should_panic(expected = "cannot advance past the end of the buffer")]
1858    fn advance_to_past_end() {
1859        let mut pages = mixed_pages();
1860        pages.advance_to(pages.len() + 1);
1861    }
1862}