use crate::coder::{Buffer, Decoder, Encoder, Result, View, MAX_VECTORED_CHUNK};
use crate::derive::variant::{VariantDecoder, VariantEncoder};
use crate::derive::{Decode, Encode};
use crate::fast::{FastArrayVec, PushUnchecked};
use alloc::vec::Vec;
use core::mem::MaybeUninit;
use core::num::NonZeroUsize;
pub struct OptionEncoder<T: Encode> {
variants: VariantEncoder<2>,
some: T::Encoder,
}
impl<T: Encode> Default for OptionEncoder<T> {
fn default() -> Self {
Self {
variants: Default::default(),
some: Default::default(),
}
}
}
impl<T: Encode> Encoder<Option<T>> for OptionEncoder<T> {
#[inline(always)]
fn encode(&mut self, t: &Option<T>) {
self.variants.encode(&(t.is_some() as u8));
if let Some(t) = t {
self.some.reserve(NonZeroUsize::new(1).unwrap());
self.some.encode(t);
}
}
fn encode_vectored<'a>(&mut self, i: impl Iterator<Item = &'a Option<T>> + Clone)
where
Option<T>: 'a,
{
if core::mem::size_of::<T>() >= 64 {
let mut uninit = MaybeUninit::uninit();
let mut refs = FastArrayVec::<_, MAX_VECTORED_CHUNK>::new(&mut uninit);
for t in i {
self.variants.encode(&(t.is_some() as u8));
if let Some(t) = t {
unsafe { refs.push_unchecked(t) };
}
}
let refs = refs.as_slice();
let Some(some_count) = NonZeroUsize::new(refs.len()) else {
return;
};
self.some.reserve(some_count);
self.some.encode_vectored(refs.iter().copied());
} else {
let size_hint =
unsafe { NonZeroUsize::new(i.size_hint().1.unwrap()).unwrap_unchecked() };
self.some.reserve(size_hint);
for option in i {
self.variants.encode(&(option.is_some() as u8));
if let Some(t) = option {
self.some.encode(t);
}
}
}
}
}
impl<T: Encode> Buffer for OptionEncoder<T> {
fn collect_into(&mut self, out: &mut Vec<u8>) {
self.variants.collect_into(out);
self.some.collect_into(out);
}
fn reserve(&mut self, additional: NonZeroUsize) {
self.variants.reserve(additional);
}
}
pub struct OptionDecoder<'a, T: Decode<'a>> {
variants: VariantDecoder<'a, 2, false>,
some: T::Decoder,
}
impl<'a, T: Decode<'a>> Default for OptionDecoder<'a, T> {
fn default() -> Self {
Self {
variants: Default::default(),
some: Default::default(),
}
}
}
impl<'a, T: Decode<'a>> View<'a> for OptionDecoder<'a, T> {
fn populate(&mut self, input: &mut &'a [u8], length: usize) -> Result<()> {
self.variants.populate(input, length)?;
self.some.populate(input, self.variants.length(1))
}
}
impl<'a, T: Decode<'a>> Decoder<'a, Option<T>> for OptionDecoder<'a, T> {
#[inline(always)]
fn decode_in_place(&mut self, out: &mut MaybeUninit<Option<T>>) {
if self.variants.decode() != 0 {
out.write(Some(self.some.decode()));
} else {
out.write(None);
}
}
}
#[cfg(test)]
mod tests {
use alloc::vec::Vec;
#[rustfmt::skip]
fn bench_data() -> Vec<Option<(u64, u32, u8, i32, u64, u32, u8, i32, u64, (u32, u8, i32, u64, u32, u8, i32))>> {
crate::random_data(1000)
}
crate::bench_encode_decode!(option_vec: Vec<_>);
}
#[cfg(test)]
mod tests2 {
use alloc::vec::Vec;
#[rustfmt::skip]
fn bench_data() -> Vec<Option<u16>> {
crate::random_data(1000)
}
crate::bench_encode_decode!(option_u16_vec: Vec<_>);
}