pub use self::load_array::LoadArray;
mod load_array;
pub use self::as_body::AsBody;
mod as_body;
use core::fmt;
#[cfg(feature = "alloc")]
use crate::BodyBuf;
use crate::buf::Aligned;
use crate::error::Result;
use crate::ty;
use crate::{Endianness, Frame, Read, Signature};
pub struct Body<'a> {
data: Aligned<'a>,
endianness: Endianness,
signature: &'a Signature,
}
impl<'a> Body<'a> {
pub(crate) const fn empty() -> Self {
Self::from_raw_parts(Aligned::empty(), Endianness::NATIVE, Signature::EMPTY)
}
#[inline]
pub(crate) const fn from_raw_parts(
data: Aligned<'a>,
endianness: Endianness,
signature: &'a Signature,
) -> Self {
Self {
data,
endianness,
signature,
}
}
#[cfg(feature = "alloc")]
#[inline]
pub(crate) const fn into_raw_parts(self) -> (Aligned<'a>, Endianness, &'a Signature) {
(self.data, self.endianness, self.signature)
}
pub fn endianness(&self) -> Endianness {
self.endianness
}
pub fn with_endianness(self, endianness: Endianness) -> Self {
Self { endianness, ..self }
}
pub fn signature(&self) -> &'a Signature {
self.signature
}
#[cfg(feature = "alloc")]
pub(crate) fn with_signature(self, signature: &'a Signature) -> Self {
Self { signature, ..self }
}
pub fn get(&self) -> &'a [u8] {
self.data.get()
}
#[inline]
pub fn is_empty(&self) -> bool {
self.data.is_empty()
}
#[inline]
pub fn len(&self) -> usize {
self.data.len()
}
pub fn read<T>(&mut self) -> Result<&'a T>
where
T: ?Sized + Read,
{
T::read_from(self)
}
pub fn read_until(&mut self, len: usize) -> Body<'a> {
Body::from_raw_parts(self.data.read_until(len), self.endianness, self.signature)
}
pub fn load_array<E>(&mut self) -> Result<LoadArray<'a, E>>
where
E: ty::Marker,
{
LoadArray::from_mut(self)
}
pub fn load_struct<E>(&mut self) -> Result<E::Return<'a>>
where
E: ty::Fields,
{
self.align::<u64>()?;
E::load_struct(self)
}
pub fn load_struct_with<F, O>(&mut self, f: F) -> Result<O>
where
F: FnOnce(&mut Body<'a>) -> Result<O>,
{
self.align::<u64>()?;
f(self)
}
pub fn load<T>(&mut self) -> Result<T>
where
T: Frame,
{
let mut frame = self.data.load::<T>()?;
frame.adjust(self.endianness);
Ok(frame)
}
pub fn load_bool(&mut self) -> Result<bool> {
Ok(self.load::<u32>()? != 0)
}
pub fn read_variant(&mut self) -> Result<crate::Variant<'a>> {
<ty::Variant as ty::Marker>::load_struct(self)
}
pub fn read_variant_as<T>(&mut self) -> Result<T::Return<'a>>
where
T: ty::Marker,
{
let signature = self.read::<Signature>()?;
let mut expected = crate::signature::SignatureBuilder::new();
T::write_signature(&mut expected)?;
if signature != expected.to_signature() {
#[cfg(feature = "alloc")]
return Err(crate::Error::new(
crate::error::ErrorKind::UnsupportedVariant(signature.into()),
));
#[cfg(not(feature = "alloc"))]
return Err(crate::Error::new(
crate::error::ErrorKind::UnsupportedVariantNoAlloc,
));
}
self.align::<T::Alignment>()?;
T::load_struct(self)
}
#[cfg(feature = "alloc")]
pub fn skip_variant(&mut self) -> Result<&'a Signature> {
let signature = self.read::<Signature>()?;
crate::signature::skip(signature, self)?;
Ok(signature)
}
#[cfg(feature = "alloc")]
pub fn align_to(&mut self, alignment: crate::Alignment) -> Result<()> {
self.data.align_to(alignment.in_bytes())
}
#[cfg(feature = "alloc")]
pub fn load_raw_array(&mut self, alignment: crate::Alignment) -> Result<Body<'a>> {
let bytes = self.load::<u32>()?;
if bytes > crate::buf::MAX_ARRAY_LENGTH {
return Err(crate::Error::new(crate::error::ErrorKind::ArrayTooLong(
bytes,
)));
}
self.align_to(alignment)?;
Ok(self.read_until(bytes as usize))
}
#[cfg(feature = "alloc")]
#[inline]
pub(crate) fn advance(&mut self, n: usize) -> Result<()> {
self.data.advance(n)
}
#[inline]
pub(crate) fn align<T>(&mut self) -> Result<()> {
self.data.align::<T>()
}
#[inline]
pub(crate) fn load_slice(&mut self, len: usize) -> Result<&'a [u8]> {
self.data.load_slice(len)
}
#[inline]
pub(crate) fn load_slice_nul(&mut self, len: usize) -> Result<&'a [u8]> {
self.data.load_slice_nul(len)
}
}
unsafe impl Send for Body<'_> {}
unsafe impl Sync for Body<'_> {}
impl Clone for Body<'_> {
#[inline]
fn clone(&self) -> Self {
Self {
data: self.data.clone(),
endianness: self.endianness,
signature: self.signature,
}
}
}
impl fmt::Debug for Body<'_> {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Body")
.field("data", &self.data)
.field("endianness", &self.endianness)
.finish()
}
}
impl<'a> PartialEq<Body<'a>> for Body<'_> {
#[inline]
fn eq(&self, other: &Body<'a>) -> bool {
self.get() == other.get() && self.endianness == other.endianness
}
}
#[cfg(feature = "alloc")]
impl PartialEq<BodyBuf> for Body<'_> {
#[inline]
fn eq(&self, other: &BodyBuf) -> bool {
self.get() == other.get() && self.endianness == other.endianness()
}
}
impl Eq for Body<'_> {}