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