use impl_tools::autoimpl;
use tlb::{
Cell, ParseFully, Ref, Same,
bits::{
NBits,
de::{BitReader, BitReaderExt, BitUnpack},
ser::{BitPack, BitWriter, BitWriterExt},
},
de::{CellDeserialize, CellParser, CellParserError},
hashmap::HashmapE,
ser::{CellBuilder, CellBuilderError, CellSerialize, CellSerializeExt},
};
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, Clone, PartialEq, Eq)]
#[autoimpl(Default)]
pub struct StateInit<C = Cell, D = Cell> {
pub split_depth: Option<u8>,
pub special: Option<TickTock>,
pub code: Option<C>,
pub data: Option<D>,
#[cfg_attr(feature = "arbitrary", arbitrary(default))] pub library: HashmapE<SimpleLib>,
}
impl<IC, ID> StateInit<IC, ID>
where
IC: CellSerialize<Args = ()>,
ID: CellSerialize<Args = ()>,
{
#[inline]
pub fn normalize(&self) -> Result<StateInit, CellBuilderError> {
Ok(StateInit {
split_depth: self.split_depth,
special: self.special,
code: self.code.as_ref().map(|c| c.to_cell(())).transpose()?,
data: self.data.as_ref().map(|d| d.to_cell(())).transpose()?,
library: self.library.clone(),
})
}
}
impl<C, D> CellSerialize for StateInit<C, D>
where
C: CellSerialize<Args = ()>,
D: CellSerialize<Args = ()>,
{
type Args = ();
#[inline]
fn store(&self, builder: &mut CellBuilder, _: Self::Args) -> Result<(), CellBuilderError> {
builder
.pack_as::<_, Option<NBits<5>>>(self.split_depth, ())?
.pack(self.special, ())?
.store_as::<_, Option<Ref>>(self.code.as_ref(), ())?
.store_as::<_, Option<Ref>>(self.data.as_ref(), ())?
.store_as::<_, &HashmapE<Same, Same>>(&self.library, (256, (), ()))?;
Ok(())
}
}
impl<'de, C, D> CellDeserialize<'de> for StateInit<C, D>
where
C: CellDeserialize<'de, Args = ()>,
D: CellDeserialize<'de, Args = ()>,
{
type Args = ();
#[inline]
fn parse(parser: &mut CellParser<'de>, _: Self::Args) -> Result<Self, CellParserError<'de>> {
Ok(Self {
split_depth: parser.unpack_as::<_, Option<NBits<5>>>(())?,
special: parser.unpack(())?,
code: parser.parse_as::<_, Option<Ref<ParseFully>>>(())?,
data: parser.parse_as::<_, Option<Ref<ParseFully>>>(())?,
library: parser.parse_as::<_, HashmapE<Same, Same>>((256, (), ()))?,
})
}
}
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct TickTock {
pub tick: bool,
pub tock: bool,
}
impl BitPack for TickTock {
type Args = ();
#[inline]
fn pack<W>(&self, writer: &mut W, _: Self::Args) -> Result<(), W::Error>
where
W: BitWriter + ?Sized,
{
writer.pack(self.tick, ())?.pack(self.tock, ())?;
Ok(())
}
}
impl<'de> BitUnpack<'de> for TickTock {
type Args = ();
#[inline]
fn unpack<R>(reader: &mut R, _: Self::Args) -> Result<Self, R::Error>
where
R: BitReader<'de> + ?Sized,
{
Ok(Self {
tick: reader.unpack(())?,
tock: reader.unpack(())?,
})
}
}
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct SimpleLib {
pub public: bool,
pub root: Cell,
}
impl CellSerialize for SimpleLib {
type Args = ();
#[inline]
fn store(&self, builder: &mut CellBuilder, _: Self::Args) -> Result<(), CellBuilderError> {
builder
.pack(self.public, ())?
.store_as::<_, Ref>(&self.root, ())?;
Ok(())
}
}
impl<'de> CellDeserialize<'de> for SimpleLib {
type Args = ();
#[inline]
fn parse(parser: &mut CellParser<'de>, _: Self::Args) -> Result<Self, CellParserError<'de>> {
Ok(SimpleLib {
public: parser.unpack(())?,
root: parser.parse_as::<_, Ref>(())?,
})
}
}
#[cfg(test)]
mod tests {
use tlb::ser::CellSerializeExt;
use super::*;
#[test]
fn state_init_serde() {
let s = StateInit::<(), ()>::default();
let cell = s.to_cell(()).unwrap();
let got: StateInit<(), ()> = cell.parse_fully(()).unwrap();
assert_eq!(got, s);
}
}