use super::{CountedList, CountedListWriter, Deserialize, Error, InitExpr, Serialize, VarUint32};
use crate::io;
use alloc::vec::Vec;
#[cfg(feature = "bulk")]
const FLAG_MEMZERO: u32 = 0;
#[cfg(feature = "bulk")]
const FLAG_PASSIVE: u32 = 1;
#[cfg(feature = "bulk")]
const FLAG_MEM_NONZERO: u32 = 2;
#[cfg(feature = "reduced-stack-buffer")]
const VALUES_BUFFER_LENGTH: usize = 256;
#[cfg(not(feature = "reduced-stack-buffer"))]
const VALUES_BUFFER_LENGTH: usize = 16384;
#[derive(Debug, Clone, PartialEq)]
pub struct ElementSegment {
index: u32,
offset: Option<InitExpr>,
members: Vec<u32>,
#[cfg(feature = "bulk")]
passive: bool,
}
impl ElementSegment {
pub fn new(index: u32, offset: Option<InitExpr>, members: Vec<u32>) -> Self {
ElementSegment {
index,
offset,
members,
#[cfg(feature = "bulk")]
passive: false,
}
}
pub fn members(&self) -> &[u32] {
&self.members
}
pub fn members_mut(&mut self) -> &mut Vec<u32> {
&mut self.members
}
pub fn index(&self) -> u32 {
self.index
}
pub fn offset(&self) -> &Option<InitExpr> {
&self.offset
}
pub fn offset_mut(&mut self) -> &mut Option<InitExpr> {
&mut self.offset
}
}
#[cfg(feature = "bulk")]
impl ElementSegment {
pub fn passive(&self) -> bool {
self.passive
}
pub fn passive_mut(&mut self) -> &mut bool {
&mut self.passive
}
pub fn set_passive(&mut self, passive: bool) {
self.passive = passive;
}
}
impl Deserialize for ElementSegment {
type Error = Error;
#[cfg(not(feature = "bulk"))]
fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
let index: u32 = VarUint32::deserialize(reader)?.into();
let offset = InitExpr::deserialize(reader)?;
let members: Vec<u32> = CountedList::<VarUint32>::deserialize(reader)?
.into_inner()
.into_iter()
.map(Into::into)
.collect();
Ok(ElementSegment { index, offset: Some(offset), members })
}
#[cfg(feature = "bulk")]
fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
let flags: u32 = VarUint32::deserialize(reader)?.into();
let index = if flags == FLAG_MEMZERO || flags == FLAG_PASSIVE {
0u32
} else if flags == FLAG_MEM_NONZERO {
VarUint32::deserialize(reader)?.into()
} else {
return Err(Error::InvalidSegmentFlags(flags))
};
let offset =
if flags == FLAG_PASSIVE { None } else { Some(InitExpr::deserialize(reader)?) };
let members: Vec<u32> = CountedList::<VarUint32>::deserialize(reader)?
.into_inner()
.into_iter()
.map(Into::into)
.collect();
Ok(ElementSegment { index, offset, members, passive: flags == FLAG_PASSIVE })
}
}
impl Serialize for ElementSegment {
type Error = Error;
fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
#[cfg(feature = "bulk")]
{
if self.passive {
VarUint32::from(FLAG_PASSIVE).serialize(writer)?;
} else if self.index != 0 {
VarUint32::from(FLAG_MEM_NONZERO).serialize(writer)?;
VarUint32::from(self.index).serialize(writer)?;
} else {
VarUint32::from(FLAG_MEMZERO).serialize(writer)?;
}
}
#[cfg(not(feature = "bulk"))]
VarUint32::from(self.index).serialize(writer)?;
if let Some(offset) = self.offset {
offset.serialize(writer)?;
}
let data = self.members;
let counted_list =
CountedListWriter::<VarUint32, _>(data.len(), data.into_iter().map(Into::into));
counted_list.serialize(writer)?;
Ok(())
}
}
#[derive(Clone, Debug, PartialEq)]
pub struct DataSegment {
index: u32,
offset: Option<InitExpr>,
value: Vec<u8>,
#[cfg(feature = "bulk")]
passive: bool,
}
impl DataSegment {
pub fn new(index: u32, offset: Option<InitExpr>, value: Vec<u8>) -> Self {
DataSegment {
index,
offset,
value,
#[cfg(feature = "bulk")]
passive: false,
}
}
pub fn index(&self) -> u32 {
self.index
}
pub fn offset(&self) -> &Option<InitExpr> {
&self.offset
}
pub fn offset_mut(&mut self) -> &mut Option<InitExpr> {
&mut self.offset
}
pub fn value(&self) -> &[u8] {
&self.value
}
pub fn value_mut(&mut self) -> &mut Vec<u8> {
&mut self.value
}
}
#[cfg(feature = "bulk")]
impl DataSegment {
pub fn passive(&self) -> bool {
self.passive
}
pub fn passive_mut(&mut self) -> &mut bool {
&mut self.passive
}
pub fn set_passive(&mut self, passive: bool) {
self.passive = passive;
}
}
impl Deserialize for DataSegment {
type Error = Error;
#[cfg(not(feature = "bulk"))]
fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
let index = VarUint32::deserialize(reader)?;
let offset = InitExpr::deserialize(reader)?;
let value_len = u32::from(VarUint32::deserialize(reader)?) as usize;
let value = buffered_read!(VALUES_BUFFER_LENGTH, value_len, reader);
Ok(DataSegment { index: index.into(), offset: Some(offset), value })
}
#[cfg(feature = "bulk")]
fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
let flags: u32 = VarUint32::deserialize(reader)?.into();
let index = if flags == FLAG_MEMZERO || flags == FLAG_PASSIVE {
0u32
} else if flags == FLAG_MEM_NONZERO {
VarUint32::deserialize(reader)?.into()
} else {
return Err(Error::InvalidSegmentFlags(flags))
};
let offset =
if flags == FLAG_PASSIVE { None } else { Some(InitExpr::deserialize(reader)?) };
let value_len = u32::from(VarUint32::deserialize(reader)?) as usize;
let value = buffered_read!(VALUES_BUFFER_LENGTH, value_len, reader);
Ok(DataSegment { index, offset, value, passive: flags == FLAG_PASSIVE })
}
}
impl Serialize for DataSegment {
type Error = Error;
fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error> {
#[cfg(feature = "bulk")]
{
if self.passive {
VarUint32::from(FLAG_PASSIVE).serialize(writer)?;
} else if self.index != 0 {
VarUint32::from(FLAG_MEM_NONZERO).serialize(writer)?;
VarUint32::from(self.index).serialize(writer)?;
} else {
VarUint32::from(FLAG_MEMZERO).serialize(writer)?;
}
}
#[cfg(not(feature = "bulk"))]
VarUint32::from(self.index).serialize(writer)?;
if let Some(offset) = self.offset {
offset.serialize(writer)?;
}
let value = self.value;
VarUint32::from(value.len()).serialize(writer)?;
writer.write(&value[..])?;
Ok(())
}
}