use core::{borrow::Borrow, cell::RefCell, ops::DerefMut};
use crate::prelude::*;
use ser::*;
#[cfg(not(feature = "std"))]
use alloc::boxed::Box;
pub struct SerIter<T, I: ExactSizeIterator>(RefCell<I>, core::marker::PhantomData<T>);
impl<T, I: ExactSizeIterator + core::fmt::Debug> core::fmt::Debug for SerIter<T, I> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self.0.try_borrow() {
Ok(iter) => f.debug_tuple("SerIter").field(&&*iter).finish(),
Err(_) => f
.debug_tuple("SerIter")
.field(&format_args!("<borrowed>"))
.finish(),
}
}
}
impl<T, I: ExactSizeIterator> SerIter<T, I> {
pub const fn new(iter: I) -> Self {
SerIter(RefCell::new(iter), core::marker::PhantomData)
}
}
impl<T, I: ExactSizeIterator> From<I> for SerIter<T, I> {
fn from(iter: I) -> Self {
SerIter::new(iter)
}
}
impl<T, I> SerInner for SerIter<T, I>
where
I: ExactSizeIterator,
I::Item: Borrow<T>,
T: CopyType + SerInner,
Self: SerHelper<<T as CopyType>::Copy>,
{
type SerType = Box<[T::SerType]>;
const IS_ZERO_COPY: bool = false;
unsafe fn _ser_inner(&self, backend: &mut impl WriteWithNames) -> ser::Result<()> {
unsafe { <Self as SerHelper<<T as CopyType>::Copy>>::_ser_inner(self, backend) }
}
}
impl<T, I> SerHelper<Zero> for SerIter<T, I>
where
I: ExactSizeIterator,
I::Item: Borrow<T>,
T: ZeroCopy,
{
unsafe fn _ser_inner(&self, backend: &mut impl WriteWithNames) -> ser::Result<()> {
check_zero_copy::<T>();
let mut iter = self.0.borrow_mut();
let len = iter.len();
unsafe { backend.write("len", &len) }?;
backend.align::<T>()?;
let mut c = 0;
for item in iter.deref_mut() {
if c == len {
c += 1;
break;
}
unsafe { ser_zero_unchecked(backend, item.borrow()) }?;
c += 1;
}
if c != len {
Err(ser::Error::IteratorLengthMismatch {
actual: c,
expected: len,
})
} else {
Ok(())
}
}
}
impl<T, I> SerHelper<Deep> for SerIter<T, I>
where
I: ExactSizeIterator,
I::Item: Borrow<T>,
T: DeepCopy,
{
unsafe fn _ser_inner(&self, backend: &mut impl WriteWithNames) -> ser::Result<()> {
let mut iter = self.0.borrow_mut();
let len = iter.len();
unsafe { backend.write("len", &len) }?;
let mut c = 0;
for item in iter.deref_mut() {
if c == len {
c += 1;
break;
}
unsafe { backend.write("item", item.borrow())? };
c += 1;
}
if c != len {
Err(ser::Error::IteratorLengthMismatch {
actual: c,
expected: len,
})
} else {
Ok(())
}
}
}