|  | // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. | 
|  | // Copyright by contributors to this project. | 
|  | // SPDX-License-Identifier: (Apache-2.0 OR MIT) | 
|  |  | 
|  | use crate::{MlsDecode, MlsEncode, MlsSize, VarInt}; | 
|  |  | 
|  | use alloc::vec::Vec; | 
|  |  | 
|  | pub fn mls_encoded_len<T>(iter: impl Iterator<Item = T>) -> usize | 
|  | where | 
|  | T: MlsSize, | 
|  | { | 
|  | let len = iter.map(|x| x.mls_encoded_len()).sum::<usize>(); | 
|  |  | 
|  | let header_length = VarInt::try_from(len).unwrap_or(VarInt(0)).mls_encoded_len(); | 
|  |  | 
|  | header_length + len | 
|  | } | 
|  |  | 
|  | #[cfg(feature = "preallocate")] | 
|  | pub fn mls_encode<I>(iter: I, writer: &mut Vec<u8>) -> Result<(), crate::Error> | 
|  | where | 
|  | I: IntoIterator + Clone, | 
|  | I::Item: MlsEncode, | 
|  | { | 
|  | let len = iter | 
|  | .clone() | 
|  | .into_iter() | 
|  | .map(|x| x.mls_encoded_len()) | 
|  | .sum::<usize>(); | 
|  |  | 
|  | let header_length = VarInt::try_from(len)?; | 
|  | header_length.mls_encode(writer)?; | 
|  |  | 
|  | writer.reserve(len); | 
|  |  | 
|  | iter.into_iter().try_for_each(|x| x.mls_encode(writer))?; | 
|  |  | 
|  | Ok(()) | 
|  | } | 
|  |  | 
|  | #[cfg(not(feature = "preallocate"))] | 
|  | pub fn mls_encode<I>(iter: I, writer: &mut Vec<u8>) -> Result<(), crate::Error> | 
|  | where | 
|  | I: IntoIterator + Clone, | 
|  | I::Item: MlsEncode, | 
|  | { | 
|  | let mut buffer = Vec::new(); | 
|  |  | 
|  | iter.into_iter() | 
|  | .try_for_each(|x| x.mls_encode(&mut buffer))?; | 
|  |  | 
|  | let len = VarInt::try_from(buffer.len())?; | 
|  |  | 
|  | len.mls_encode(writer)?; | 
|  | writer.extend(buffer); | 
|  |  | 
|  | Ok(()) | 
|  | } | 
|  |  | 
|  | pub fn mls_decode_collection<T, F>(reader: &mut &[u8], item_decode: F) -> Result<T, crate::Error> | 
|  | where | 
|  | F: Fn(&mut &[u8]) -> Result<T, crate::Error>, | 
|  | { | 
|  | let (mut data, rest) = mls_decode_split_on_collection(reader)?; | 
|  |  | 
|  | let items = item_decode(&mut data)?; | 
|  |  | 
|  | *reader = rest; | 
|  |  | 
|  | Ok(items) | 
|  | } | 
|  |  | 
|  | pub fn mls_decode_split_on_collection<'b>( | 
|  | reader: &mut &'b [u8], | 
|  | ) -> Result<(&'b [u8], &'b [u8]), crate::Error> { | 
|  | let len = VarInt::mls_decode(reader)?.0 as usize; | 
|  |  | 
|  | if len > reader.len() { | 
|  | return Err(crate::Error::UnexpectedEOF); | 
|  | } | 
|  |  | 
|  | Ok(reader.split_at(len)) | 
|  | } |