use core::ops::Deref;
use kernel::prelude::*;
pub(crate) struct SBufferIter<I: Iterator> {
cur_slice: Option<I::Item>,
slices: I,
}
impl<'a, I> SBufferIter<I>
where
I: Iterator,
{
pub(crate) fn new_reader(slices: impl IntoIterator<IntoIter = I>) -> Self
where
I: Iterator<Item = &'a [u8]>,
{
Self::new(slices)
}
pub(crate) fn new_writer(slices: impl IntoIterator<IntoIter = I>) -> Self
where
I: Iterator<Item = &'a mut [u8]>,
{
Self::new(slices)
}
fn new(slices: impl IntoIterator<IntoIter = I>) -> Self
where
I::Item: Deref<Target = [u8]>,
{
let mut slices = slices.into_iter();
Self {
cur_slice: slices.find(|s| !s.deref().is_empty()),
slices,
}
}
fn get_slice_internal(
&mut self,
len: usize,
mut f: impl FnMut(I::Item, usize) -> (I::Item, I::Item),
) -> Option<I::Item>
where
I::Item: Deref<Target = [u8]>,
{
match self.cur_slice.take() {
None => None,
Some(cur_slice) => {
if len >= cur_slice.len() {
self.cur_slice = self.slices.find(|s| !s.is_empty());
Some(cur_slice)
} else {
let (ret, next) = f(cur_slice, len);
self.cur_slice = Some(next);
Some(ret)
}
}
}
}
pub(crate) fn is_empty(&self) -> bool {
self.cur_slice.is_none()
}
}
impl<'a, I> SBufferIter<I>
where
I: Iterator<Item = &'a [u8]>,
{
fn get_slice(&mut self, len: usize) -> Option<&'a [u8]> {
self.get_slice_internal(len, |s, pos| s.split_at(pos))
}
#[expect(unused)]
pub(crate) fn read_exact(&mut self, mut dst: &mut [u8]) -> Result {
while !dst.is_empty() {
match self.get_slice(dst.len()) {
None => return Err(EINVAL),
Some(src) => {
let dst_slice;
(dst_slice, dst) = dst.split_at_mut(src.len());
dst_slice.copy_from_slice(src);
}
}
}
Ok(())
}
pub(crate) fn flush_into_kvec(&mut self, flags: kernel::alloc::Flags) -> Result<KVec<u8>> {
let mut buf = KVec::<u8>::new();
if let Some(slice) = core::mem::take(&mut self.cur_slice) {
buf.extend_from_slice(slice, flags)?;
}
for slice in &mut self.slices {
buf.extend_from_slice(slice, flags)?;
}
Ok(buf)
}
}
impl<'a, I> SBufferIter<I>
where
I: Iterator<Item = &'a mut [u8]>,
{
fn get_slice_mut(&mut self, len: usize) -> Option<&'a mut [u8]> {
self.get_slice_internal(len, |s, pos| s.split_at_mut(pos))
}
pub(crate) fn write_all(&mut self, mut src: &[u8]) -> Result {
while !src.is_empty() {
match self.get_slice_mut(src.len()) {
None => return Err(ETOOSMALL),
Some(dst) => {
let src_slice;
(src_slice, src) = src.split_at(dst.len());
dst.copy_from_slice(src_slice);
}
}
}
Ok(())
}
}
impl<'a, I> Iterator for SBufferIter<I>
where
I: Iterator<Item = &'a [u8]>,
{
type Item = u8;
fn next(&mut self) -> Option<Self::Item> {
self.get_slice(1).map(|s| s[0])
}
}