use core::{fmt::Display, marker::PhantomData};
use crate::{
Cell, Error,
r#as::Ref,
bits::{
bitvec::{mem::bits_of, view::AsBits},
de::{BitReaderExt, BitUnpackAs},
ser::{BitPackAs, BitWriter},
},
de::{CellDeserializeAs, CellParser, CellParserError},
ser::{CellBuilder, CellBuilderError, CellSerializeAs},
};
use super::Same;
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Data<As: ?Sized = Same>(PhantomData<As>);
impl<T, As> CellSerializeAs<T> for Data<As>
where
As: BitPackAs<T> + ?Sized,
T: ?Sized,
{
type Args = As::Args;
#[inline]
fn store_as(
source: &T,
builder: &mut CellBuilder,
args: Self::Args,
) -> Result<(), CellBuilderError> {
As::pack_as(source, builder, args)
}
}
impl<'de, T, As> CellDeserializeAs<'de, T> for Data<As>
where
As: BitUnpackAs<'de, T> + ?Sized,
{
type Args = As::Args;
#[inline]
fn parse_as(parser: &mut CellParser<'de>, args: Self::Args) -> Result<T, CellParserError<'de>> {
As::unpack_as(parser, args)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct SnakeData;
impl<T> CellSerializeAs<T> for SnakeData
where
T: AsRef<[u8]>,
{
type Args = ();
fn store_as(
source: &T,
builder: &mut CellBuilder,
_: Self::Args,
) -> Result<(), CellBuilderError> {
fn pack_max<'a>(
mut s: &'a [u8],
b: &mut CellBuilder,
) -> Result<&'a [u8], CellBuilderError> {
let cur: &[u8];
(cur, s) = s.split_at(s.len().min(b.capacity_left() / bits_of::<u8>()));
b.write_bitslice(cur.as_bits())?;
Ok(s)
}
let mut s = source.as_ref();
s = pack_max(s, builder)?;
let mut stack: Vec<CellBuilder> = Vec::new();
while !s.is_empty() {
let mut b = Cell::builder();
s = pack_max(s, &mut b)?;
stack.push(b);
}
if let Some(last) = stack.pop() {
let child = stack.into_iter().try_rfold(last, |child, mut parent| {
parent.store_as::<_, Ref>(child, ())?;
Ok(parent)
})?;
builder.store_as::<_, Ref>(child, ())?;
}
Ok(())
}
}
impl<'de, T> CellDeserializeAs<'de, T> for SnakeData
where
T: TryFrom<Vec<u8>>,
<T as TryFrom<Vec<u8>>>::Error: Display,
{
type Args = ();
fn parse_as(parser: &mut CellParser<'de>, _: Self::Args) -> Result<T, CellParserError<'de>> {
let mut parser: CellParser = parser.parse(())?;
let mut data = Vec::new();
while !parser.no_bits_left() {
let cur_len = data.len();
let more = parser.bits_left() / bits_of::<u8>();
data.resize(cur_len + more, 0);
let n = parser.read_bytes_into(&mut data[cur_len..])?;
if n != more * bits_of::<u8>() {
return Err(Error::custom("EOF"));
}
if parser.no_references_left() {
break;
}
parser = parser.parse_as::<CellParser, Ref>(())?;
}
data.try_into().map_err(Error::custom)
}
}
pub type Text = SnakeData;
#[cfg(test)]
mod tests {
use crate::tests::assert_store_parse_as_eq;
use super::*;
#[test]
fn serde() {
assert_store_parse_as_eq::<_, SnakeData>(
"Hello, TON!"
.repeat(100),
(),
);
}
}