use core::marker::PhantomData;
use crate::buf::MAX_ARRAY_LENGTH;
use crate::error::ErrorKind;
use crate::{Body, ty};
use crate::{Error, Frame, Read, Result};
pub struct LoadArray<'de, T> {
buf: Body<'de>,
_marker: PhantomData<T>,
}
impl<'de, T> LoadArray<'de, T>
where
T: ty::Aligned,
{
#[inline]
pub(crate) fn from_mut(buf: &mut Body<'de>) -> Result<LoadArray<'de, T>> {
let bytes = buf.load::<u32>()?;
if bytes > MAX_ARRAY_LENGTH {
return Err(Error::new(ErrorKind::ArrayTooLong(bytes)));
}
buf.align::<T::Alignment>()?;
let buf = buf.read_until(bytes as usize);
Ok(LoadArray::new(buf))
}
}
impl<'de, T> LoadArray<'de, T> {
pub(crate) fn new(buf: Body<'de>) -> Self {
LoadArray {
buf,
_marker: PhantomData,
}
}
#[inline]
pub fn is_empty(&self) -> bool {
self.buf.is_empty()
}
pub fn load_with<F, O>(&mut self, f: F) -> Result<Option<O>>
where
F: FnOnce(&mut Body<'de>) -> Result<O>,
{
if self.buf.is_empty() {
return Ok(None);
}
Ok(Some(f(&mut self.buf)?))
}
}
impl<T> LoadArray<'_, T>
where
T: Frame,
{
pub fn load(&mut self) -> Result<Option<T>> {
if self.buf.is_empty() {
return Ok(None);
}
Ok(Some(self.buf.load()?))
}
}
impl<'de, T> LoadArray<'de, T>
where
T: ty::Unsized,
T::Target: Read,
{
pub fn read(&mut self) -> Result<Option<&'de T::Target>> {
if self.buf.is_empty() {
return Ok(None);
}
Ok(Some(T::Target::read_from(&mut self.buf)?))
}
}
impl<'de, T> LoadArray<'de, ty::Array<T>>
where
T: ty::Marker,
{
pub fn load_array(&mut self) -> Result<Option<LoadArray<'de, T>>> {
if self.buf.is_empty() {
return Ok(None);
}
Ok(Some(LoadArray::from_mut(&mut self.buf)?))
}
}
impl<'de, T> LoadArray<'de, T>
where
T: ty::Fields,
{
pub fn load_struct(&mut self) -> Result<Option<T::Return<'de>>> {
if self.buf.is_empty() {
return Ok(None);
}
Ok(Some(self.buf.load_struct::<T>()?))
}
}
impl<'de> LoadArray<'de, ty::Variant> {
pub fn load_variant(&mut self) -> Result<Option<crate::Variant<'de>>> {
if self.buf.is_empty() {
return Ok(None);
}
Ok(Some(self.buf.read_variant()?))
}
pub fn skip_variant(&mut self) -> Result<Option<&'de crate::Signature>> {
if self.buf.is_empty() {
return Ok(None);
}
Ok(Some(self.buf.skip_variant()?))
}
}
impl<'de, K, V> LoadArray<'de, ty::Dict<K, V>>
where
K: ty::Marker,
V: ty::Marker,
{
pub fn load_entry(&mut self) -> Result<Option<(K::Return<'de>, V::Return<'de>)>> {
if self.buf.is_empty() {
return Ok(None);
}
self.buf.align::<u64>()?;
Ok(Some((
K::load_struct(&mut self.buf)?,
V::load_struct(&mut self.buf)?,
)))
}
}
impl<'de, K> LoadArray<'de, ty::Dict<K, ty::Variant>>
where
K: ty::Marker,
{
pub fn load_entry_as<T>(&mut self) -> Result<Option<(K::Return<'de>, T::Return<'de>)>>
where
T: ty::Marker,
{
if self.buf.is_empty() {
return Ok(None);
}
self.buf.align::<u64>()?;
let key = K::load_struct(&mut self.buf)?;
let value = self.buf.read_variant_as::<T>()?;
Ok(Some((key, value)))
}
}