use crate::prelude::*;
use std::vec::IntoIter;
#[cfg(feature = "encode")]
impl<T: Encodable> Encodable for Vec<T> {
type EncoderArray = VecArrayEncoder<T::EncoderArray>;
fn encode_root<O: EncodeOptions>(&self, stream: &mut EncoderStream<'_, O>) -> RootTypeId {
profile_method!(encode_root);
match self.len() {
0 => RootTypeId::Array0,
1 => {
stream.encode_with_id(|stream| (&self[0]).encode_root(stream));
RootTypeId::Array1
}
_ => {
encode_usize(self.len(), stream);
stream.encode_with_id(|stream| T::EncoderArray::encode_all(&self[..], stream));
RootTypeId::ArrayN
}
}
}
}
#[cfg(feature = "decode")]
impl<T: Decodable> Decodable for Vec<T>
where
DecodeError: From<<<T as Decodable>::DecoderArray as DecoderArray>::Error>,
{
type DecoderArray = Option<VecArrayDecoder<T::DecoderArray>>;
fn decode(sticks: DynRootBranch<'_>, options: &impl DecodeOptions) -> DecodeResult<Self> {
profile_method!(decode);
match sticks {
DynRootBranch::Array0 => Ok(Vec::new()),
DynRootBranch::Array1(inner) => {
let inner = T::decode(*inner, options)?;
Ok(vec![inner])
}
DynRootBranch::Array { len, values } => {
let mut v = Vec::with_capacity(len);
let mut decoder = T::DecoderArray::new(values, options)?;
for _ in 0..len {
v.push(decoder.decode_next()?);
}
Ok(v)
}
_ => Err(DecodeError::SchemaMismatch),
}
}
}
#[cfg(feature = "encode")]
#[derive(Debug, Default)]
pub struct VecArrayEncoder<T> {
len: <u64 as Encodable>::EncoderArray,
values: Option<T>,
}
enum FixedOrVariableLength {
Fixed(usize),
Variable(IntoIter<u64>),
}
impl FixedOrVariableLength {
fn next(&mut self) -> usize {
match self {
Self::Fixed(v) => *v,
Self::Variable(i) => i.decode_next_infallible() as usize,
}
}
}
#[cfg(feature = "decode")]
pub struct VecArrayDecoder<T> {
len: FixedOrVariableLength,
values: T,
}
#[cfg(feature = "encode")]
impl<T: Encodable> EncoderArray<Vec<T>> for VecArrayEncoder<T::EncoderArray> {
fn buffer_one<'a, 'b: 'a>(&'a mut self, value: &'b Vec<T>) {
self.len.buffer_one(&(value.len() as u64));
let values = self.values.get_or_insert_with(Default::default);
values.buffer_many(&value[..]);
}
fn flush<O: EncodeOptions>(self, stream: &mut EncoderStream<'_, O>) -> ArrayTypeId {
profile_method!(flush);
let Self { len, values } = self;
if let Some(values) = values {
if len.iter().all(|l| *l == len[0]) {
encode_usize(len[0] as usize, stream);
stream.encode_with_id(|stream| values.flush(stream));
return ArrayTypeId::ArrayFixed;
}
stream.encode_with_id(|stream| len.flush(stream));
stream.encode_with_id(|stream| values.flush(stream));
} else {
stream.encode_with_id(|_| ArrayTypeId::Void);
}
ArrayTypeId::ArrayVar
}
}
#[cfg(feature = "decode")]
impl<T: DecoderArray> DecoderArray for Option<VecArrayDecoder<T>> {
type Decode = Vec<T::Decode>;
type Error = T::Error;
fn new(sticks: DynArrayBranch<'_>, options: &impl DecodeOptions) -> DecodeResult<Self> {
profile_method!(new);
match sticks {
DynArrayBranch::Array0 => Ok(None),
DynArrayBranch::Array { len, values } => {
let (values, len) = parallel(
|| T::new(*values, options),
|| <<u64 as Decodable>::DecoderArray as DecoderArray>::new(*len, options),
options,
);
let values = values?;
let len = FixedOrVariableLength::Variable(len?);
Ok(Some(VecArrayDecoder { len, values }))
}
DynArrayBranch::ArrayFixed { len, values } => Ok(if len == 0 {
None
} else {
let len = FixedOrVariableLength::Fixed(len);
let values = T::new(*values, options)?;
Some(VecArrayDecoder { len, values })
}),
_ => Err(DecodeError::SchemaMismatch),
}
}
fn decode_next(&mut self) -> Result<Self::Decode, Self::Error> {
if let Some(inner) = self {
let len = inner.len.next();
let mut result = Vec::with_capacity(len);
for _ in 0..len {
result.push(inner.values.decode_next()?);
}
Ok(result)
} else {
Ok(Vec::new())
}
}
}