LCOV - code coverage report
Current view: top level - pageserver/src/virtual_file/owned_buffers_io - io_buf_ext.rs (source / functions) Coverage Total Hit
Test: 07bee600374ccd486c69370d0972d9035964fe68.info Lines: 100.0 % 30 30
Test Date: 2025-02-20 13:11:02 Functions: 94.4 % 18 17

            Line data    Source code
       1              : //! See [`FullSlice`].
       2              : 
       3              : use crate::virtual_file::{IoBuffer, IoBufferMut};
       4              : use bytes::{Bytes, BytesMut};
       5              : use std::ops::{Deref, Range};
       6              : use tokio_epoll_uring::{BoundedBuf, IoBuf, Slice};
       7              : 
       8              : use super::write::CheapCloneForRead;
       9              : 
      10              : /// The true owned equivalent for Rust [`slice`]. Use this for the write path.
      11              : ///
      12              : /// Unlike [`tokio_epoll_uring::Slice`], which we unfortunately inherited from `tokio-uring`,
      13              : /// [`FullSlice`] is guaranteed to have all its bytes initialized. This means that
      14              : /// [`<FullSlice as Deref<Target = [u8]>>::len`] is equal to [`Slice::bytes_init`] and [`Slice::bytes_total`].
      15              : ///
      16              : pub struct FullSlice<B> {
      17              :     slice: Slice<B>,
      18              : }
      19              : 
      20              : impl<B> FullSlice<B>
      21              : where
      22              :     B: IoBuf,
      23              : {
      24     62001637 :     pub(crate) fn must_new(slice: Slice<B>) -> Self {
      25     62001637 :         assert_eq!(slice.bytes_init(), slice.bytes_total());
      26     62001637 :         FullSlice { slice }
      27     62001637 :     }
      28     47905584 :     pub(crate) fn into_raw_slice(self) -> Slice<B> {
      29     47905584 :         let FullSlice { slice: s } = self;
      30     47905584 :         s
      31     47905584 :     }
      32              : }
      33              : 
      34              : impl<B> Deref for FullSlice<B>
      35              : where
      36              :     B: IoBuf,
      37              : {
      38              :     type Target = [u8];
      39              : 
      40     15538615 :     fn deref(&self) -> &[u8] {
      41     15538615 :         let rust_slice = &self.slice[..];
      42     15538615 :         assert_eq!(rust_slice.len(), self.slice.bytes_init());
      43     15538615 :         assert_eq!(rust_slice.len(), self.slice.bytes_total());
      44     15538615 :         rust_slice
      45     15538615 :     }
      46              : }
      47              : 
      48              : impl<B> CheapCloneForRead for FullSlice<B>
      49              : where
      50              :     B: IoBuf + CheapCloneForRead,
      51              : {
      52        13246 :     fn cheap_clone(&self) -> Self {
      53        13246 :         let bounds = self.slice.bounds();
      54        13246 :         let clone = self.slice.get_ref().cheap_clone();
      55        13246 :         let slice = clone.slice(bounds);
      56        13246 :         Self { slice }
      57        13246 :     }
      58              : }
      59              : 
      60              : pub(crate) trait IoBufExt {
      61              :     /// Get a [`FullSlice`] for the entire buffer, i.e., `self[..]` or `self[0..self.len()]`.
      62              :     fn slice_len(self) -> FullSlice<Self>
      63              :     where
      64              :         Self: Sized;
      65              : }
      66              : 
      67              : macro_rules! impl_io_buf_ext {
      68              :     ($T:ty) => {
      69              :         impl IoBufExt for $T {
      70              :             #[inline(always)]
      71     28194875 :             fn slice_len(self) -> FullSlice<Self> {
      72     28194875 :                 let len = self.len();
      73     28194875 :                 let s = if len == 0 {
      74              :                     // `BoundedBuf::slice(0..len)` or `BoundedBuf::slice(..)` has an incorrect assertion,
      75              :                     // causing a panic if len == 0.
      76              :                     // The Slice::from_buf_bounds has the correct assertion (<= instead of <).
      77              :                     // => https://github.com/neondatabase/tokio-epoll-uring/issues/46
      78         2739 :                     let slice = self.slice_full();
      79         2739 :                     let mut bounds: Range<_> = slice.bounds();
      80         2739 :                     bounds.end = bounds.start;
      81         2739 :                     Slice::from_buf_bounds(slice.into_inner(), bounds)
      82              :                 } else {
      83     28192136 :                     self.slice(0..len)
      84              :                 };
      85     28194875 :                 FullSlice::must_new(s)
      86     28194875 :             }
      87              :         }
      88              :     };
      89              : }
      90              : 
      91              : impl_io_buf_ext!(Bytes);
      92              : impl_io_buf_ext!(BytesMut);
      93              : impl_io_buf_ext!(Vec<u8>);
      94              : impl_io_buf_ext!(IoBufferMut);
      95              : impl_io_buf_ext!(IoBuffer);
        

Generated by: LCOV version 2.1-beta