1d416035fSJoel Fernandes // SPDX-License-Identifier: GPL-2.0 2d416035fSJoel Fernandes 3d416035fSJoel Fernandes use core::ops::Deref; 4d416035fSJoel Fernandes 5*9b89cea1SGary Guo use kernel::prelude::*; 6d416035fSJoel Fernandes 7d416035fSJoel Fernandes /// A buffer abstraction for discontiguous byte slices. 8d416035fSJoel Fernandes /// 9d416035fSJoel Fernandes /// This allows you to treat multiple non-contiguous `&mut [u8]` slices 10d416035fSJoel Fernandes /// of the same length as a single stream-like read/write buffer. 11d416035fSJoel Fernandes /// 12d416035fSJoel Fernandes /// # Examples 13d416035fSJoel Fernandes /// 14d416035fSJoel Fernandes /// ``` 15d416035fSJoel Fernandes // let mut buf1 = [0u8; 5]; 16d416035fSJoel Fernandes /// let mut buf2 = [0u8; 5]; 17d416035fSJoel Fernandes /// let mut sbuffer = SBufferIter::new_writer([&mut buf1[..], &mut buf2[..]]); 18d416035fSJoel Fernandes /// 19d416035fSJoel Fernandes /// let data = b"hi world!"; 20d416035fSJoel Fernandes /// sbuffer.write_all(data)?; 21d416035fSJoel Fernandes /// drop(sbuffer); 22d416035fSJoel Fernandes /// 23d416035fSJoel Fernandes /// assert_eq!(buf1, *b"hi wo"); 24d416035fSJoel Fernandes /// assert_eq!(buf2, *b"rld!\0"); 25d416035fSJoel Fernandes /// 26d416035fSJoel Fernandes /// # Ok::<(), Error>(()) 27d416035fSJoel Fernandes /// ``` 28d416035fSJoel Fernandes pub(crate) struct SBufferIter<I: Iterator> { 29d416035fSJoel Fernandes // [`Some`] if we are not at the end of the data yet. 30d416035fSJoel Fernandes cur_slice: Option<I::Item>, 31d416035fSJoel Fernandes // All the slices remaining after `cur_slice`. 32d416035fSJoel Fernandes slices: I, 33d416035fSJoel Fernandes } 34d416035fSJoel Fernandes 35d416035fSJoel Fernandes impl<'a, I> SBufferIter<I> 36d416035fSJoel Fernandes where 37d416035fSJoel Fernandes I: Iterator, 38d416035fSJoel Fernandes { 39d416035fSJoel Fernandes /// Creates a reader buffer for a discontiguous set of byte slices. 40d416035fSJoel Fernandes /// 41d416035fSJoel Fernandes /// # Examples 42d416035fSJoel Fernandes /// 43d416035fSJoel Fernandes /// ``` 44d416035fSJoel Fernandes /// let buf1: [u8; 5] = [0, 1, 2, 3, 4]; 45d416035fSJoel Fernandes /// let buf2: [u8; 5] = [5, 6, 7, 8, 9]; 46d416035fSJoel Fernandes /// let sbuffer = SBufferIter::new_reader([&buf1[..], &buf2[..]]); 47d416035fSJoel Fernandes /// let sum: u8 = sbuffer.sum(); 48d416035fSJoel Fernandes /// assert_eq!(sum, 45); 49d416035fSJoel Fernandes /// ``` 50d416035fSJoel Fernandes pub(crate) fn new_reader(slices: impl IntoIterator<IntoIter = I>) -> Self 51d416035fSJoel Fernandes where 52d416035fSJoel Fernandes I: Iterator<Item = &'a [u8]>, 53d416035fSJoel Fernandes { 54d416035fSJoel Fernandes Self::new(slices) 55d416035fSJoel Fernandes } 56d416035fSJoel Fernandes 57d416035fSJoel Fernandes /// Creates a writeable buffer for a discontiguous set of byte slices. 58d416035fSJoel Fernandes /// 59d416035fSJoel Fernandes /// # Examples 60d416035fSJoel Fernandes /// 61d416035fSJoel Fernandes /// ``` 62d416035fSJoel Fernandes /// let mut buf1 = [0u8; 5]; 63d416035fSJoel Fernandes /// let mut buf2 = [0u8; 5]; 64d416035fSJoel Fernandes /// let mut sbuffer = SBufferIter::new_writer([&mut buf1[..], &mut buf2[..]]); 65d416035fSJoel Fernandes /// sbuffer.write_all(&[0u8, 1, 2, 3, 4, 5, 6, 7, 8, 9][..])?; 66d416035fSJoel Fernandes /// drop(sbuffer); 67d416035fSJoel Fernandes /// assert_eq!(buf1, [0, 1, 2, 3, 4]); 68d416035fSJoel Fernandes /// assert_eq!(buf2, [5, 6, 7, 8, 9]); 69d416035fSJoel Fernandes /// 70d416035fSJoel Fernandes /// ``` 71d416035fSJoel Fernandes pub(crate) fn new_writer(slices: impl IntoIterator<IntoIter = I>) -> Self 72d416035fSJoel Fernandes where 73d416035fSJoel Fernandes I: Iterator<Item = &'a mut [u8]>, 74d416035fSJoel Fernandes { 75d416035fSJoel Fernandes Self::new(slices) 76d416035fSJoel Fernandes } 77d416035fSJoel Fernandes 78d416035fSJoel Fernandes fn new(slices: impl IntoIterator<IntoIter = I>) -> Self 79d416035fSJoel Fernandes where 80d416035fSJoel Fernandes I::Item: Deref<Target = [u8]>, 81d416035fSJoel Fernandes { 82d416035fSJoel Fernandes let mut slices = slices.into_iter(); 83d416035fSJoel Fernandes 84d416035fSJoel Fernandes Self { 85d416035fSJoel Fernandes // Skip empty slices. 86d416035fSJoel Fernandes cur_slice: slices.find(|s| !s.deref().is_empty()), 87d416035fSJoel Fernandes slices, 88d416035fSJoel Fernandes } 89d416035fSJoel Fernandes } 90d416035fSJoel Fernandes 91d416035fSJoel Fernandes /// Returns a slice of at most `len` bytes, or [`None`] if we are at the end of the data. 92d416035fSJoel Fernandes /// 93d416035fSJoel Fernandes /// If a slice shorter than `len` bytes has been returned, the caller can call this method 94d416035fSJoel Fernandes /// again until it returns [`None`] to try and obtain the remainder of the data. 95d416035fSJoel Fernandes /// 96d416035fSJoel Fernandes /// The closure `f` should split the slice received in it's first parameter 97d416035fSJoel Fernandes /// at the position given in the second parameter. 98d416035fSJoel Fernandes fn get_slice_internal( 99d416035fSJoel Fernandes &mut self, 100d416035fSJoel Fernandes len: usize, 101d416035fSJoel Fernandes mut f: impl FnMut(I::Item, usize) -> (I::Item, I::Item), 102d416035fSJoel Fernandes ) -> Option<I::Item> 103d416035fSJoel Fernandes where 104d416035fSJoel Fernandes I::Item: Deref<Target = [u8]>, 105d416035fSJoel Fernandes { 106d416035fSJoel Fernandes match self.cur_slice.take() { 107d416035fSJoel Fernandes None => None, 108d416035fSJoel Fernandes Some(cur_slice) => { 109d416035fSJoel Fernandes if len >= cur_slice.len() { 110d416035fSJoel Fernandes // Caller requested more data than is in the current slice, return it entirely 111d416035fSJoel Fernandes // and prepare the following slice for being used. Skip empty slices to avoid 112d416035fSJoel Fernandes // trouble. 113d416035fSJoel Fernandes self.cur_slice = self.slices.find(|s| !s.is_empty()); 114d416035fSJoel Fernandes 115d416035fSJoel Fernandes Some(cur_slice) 116d416035fSJoel Fernandes } else { 117d416035fSJoel Fernandes // The current slice can satisfy the request, split it and return a slice of 118d416035fSJoel Fernandes // the requested size. 119d416035fSJoel Fernandes let (ret, next) = f(cur_slice, len); 120d416035fSJoel Fernandes self.cur_slice = Some(next); 121d416035fSJoel Fernandes 122d416035fSJoel Fernandes Some(ret) 123d416035fSJoel Fernandes } 124d416035fSJoel Fernandes } 125d416035fSJoel Fernandes } 126d416035fSJoel Fernandes } 127d416035fSJoel Fernandes 128d416035fSJoel Fernandes /// Returns whether this buffer still has data available. 129d416035fSJoel Fernandes pub(crate) fn is_empty(&self) -> bool { 130d416035fSJoel Fernandes self.cur_slice.is_none() 131d416035fSJoel Fernandes } 132d416035fSJoel Fernandes } 133d416035fSJoel Fernandes 134d416035fSJoel Fernandes /// Provides a way to get non-mutable slices of data to read from. 135d416035fSJoel Fernandes impl<'a, I> SBufferIter<I> 136d416035fSJoel Fernandes where 137d416035fSJoel Fernandes I: Iterator<Item = &'a [u8]>, 138d416035fSJoel Fernandes { 139d416035fSJoel Fernandes /// Returns a slice of at most `len` bytes, or [`None`] if we are at the end of the data. 140d416035fSJoel Fernandes /// 141d416035fSJoel Fernandes /// If a slice shorter than `len` bytes has been returned, the caller can call this method 142d416035fSJoel Fernandes /// again until it returns [`None`] to try and obtain the remainder of the data. 143d416035fSJoel Fernandes fn get_slice(&mut self, len: usize) -> Option<&'a [u8]> { 144d416035fSJoel Fernandes self.get_slice_internal(len, |s, pos| s.split_at(pos)) 145d416035fSJoel Fernandes } 146d416035fSJoel Fernandes 147d416035fSJoel Fernandes /// Ideally we would implement `Read`, but it is not available in `core`. 148d416035fSJoel Fernandes /// So mimic `std::io::Read::read_exact`. 149d416035fSJoel Fernandes #[expect(unused)] 150d416035fSJoel Fernandes pub(crate) fn read_exact(&mut self, mut dst: &mut [u8]) -> Result { 151d416035fSJoel Fernandes while !dst.is_empty() { 152d416035fSJoel Fernandes match self.get_slice(dst.len()) { 153d416035fSJoel Fernandes None => return Err(EINVAL), 154d416035fSJoel Fernandes Some(src) => { 155d416035fSJoel Fernandes let dst_slice; 156d416035fSJoel Fernandes (dst_slice, dst) = dst.split_at_mut(src.len()); 157d416035fSJoel Fernandes dst_slice.copy_from_slice(src); 158d416035fSJoel Fernandes } 159d416035fSJoel Fernandes } 160d416035fSJoel Fernandes } 161d416035fSJoel Fernandes 162d416035fSJoel Fernandes Ok(()) 163d416035fSJoel Fernandes } 164d416035fSJoel Fernandes 165d416035fSJoel Fernandes /// Read all the remaining data into a [`KVec`]. 166d416035fSJoel Fernandes /// 167d416035fSJoel Fernandes /// `self` will be empty after this operation. 168d416035fSJoel Fernandes pub(crate) fn flush_into_kvec(&mut self, flags: kernel::alloc::Flags) -> Result<KVec<u8>> { 169d416035fSJoel Fernandes let mut buf = KVec::<u8>::new(); 170d416035fSJoel Fernandes 171d416035fSJoel Fernandes if let Some(slice) = core::mem::take(&mut self.cur_slice) { 172d416035fSJoel Fernandes buf.extend_from_slice(slice, flags)?; 173d416035fSJoel Fernandes } 174d416035fSJoel Fernandes for slice in &mut self.slices { 175d416035fSJoel Fernandes buf.extend_from_slice(slice, flags)?; 176d416035fSJoel Fernandes } 177d416035fSJoel Fernandes 178d416035fSJoel Fernandes Ok(buf) 179d416035fSJoel Fernandes } 180d416035fSJoel Fernandes } 181d416035fSJoel Fernandes 182d416035fSJoel Fernandes /// Provides a way to get mutable slices of data to write into. 183d416035fSJoel Fernandes impl<'a, I> SBufferIter<I> 184d416035fSJoel Fernandes where 185d416035fSJoel Fernandes I: Iterator<Item = &'a mut [u8]>, 186d416035fSJoel Fernandes { 187d416035fSJoel Fernandes /// Returns a mutable slice of at most `len` bytes, or [`None`] if we are at the end of the 188d416035fSJoel Fernandes /// data. 189d416035fSJoel Fernandes /// 190d416035fSJoel Fernandes /// If a slice shorter than `len` bytes has been returned, the caller can call this method 191d416035fSJoel Fernandes /// again until it returns `None` to try and obtain the remainder of the data. 192d416035fSJoel Fernandes fn get_slice_mut(&mut self, len: usize) -> Option<&'a mut [u8]> { 193d416035fSJoel Fernandes self.get_slice_internal(len, |s, pos| s.split_at_mut(pos)) 194d416035fSJoel Fernandes } 195d416035fSJoel Fernandes 196d416035fSJoel Fernandes /// Ideally we would implement [`Write`], but it is not available in `core`. 197d416035fSJoel Fernandes /// So mimic `std::io::Write::write_all`. 198d416035fSJoel Fernandes pub(crate) fn write_all(&mut self, mut src: &[u8]) -> Result { 199d416035fSJoel Fernandes while !src.is_empty() { 200d416035fSJoel Fernandes match self.get_slice_mut(src.len()) { 201d416035fSJoel Fernandes None => return Err(ETOOSMALL), 202d416035fSJoel Fernandes Some(dst) => { 203d416035fSJoel Fernandes let src_slice; 204d416035fSJoel Fernandes (src_slice, src) = src.split_at(dst.len()); 205d416035fSJoel Fernandes dst.copy_from_slice(src_slice); 206d416035fSJoel Fernandes } 207d416035fSJoel Fernandes } 208d416035fSJoel Fernandes } 209d416035fSJoel Fernandes 210d416035fSJoel Fernandes Ok(()) 211d416035fSJoel Fernandes } 212d416035fSJoel Fernandes } 213d416035fSJoel Fernandes 214d416035fSJoel Fernandes impl<'a, I> Iterator for SBufferIter<I> 215d416035fSJoel Fernandes where 216d416035fSJoel Fernandes I: Iterator<Item = &'a [u8]>, 217d416035fSJoel Fernandes { 218d416035fSJoel Fernandes type Item = u8; 219d416035fSJoel Fernandes 220d416035fSJoel Fernandes fn next(&mut self) -> Option<Self::Item> { 221d416035fSJoel Fernandes // Returned slices are guaranteed to not be empty so we can safely index the first entry. 222d416035fSJoel Fernandes self.get_slice(1).map(|s| s[0]) 223d416035fSJoel Fernandes } 224d416035fSJoel Fernandes } 225