use crate::{constants::*, schema, traits::*, types::*};
#[cfg(not(feature = "std"))]
use alloc::{boxed::Box, collections, string::String, vec::Vec};
use collections::{BTreeMap, BTreeSet};
use convert::TryFrom;
#[cfg(not(feature = "std"))]
use core::{
    convert, hash, marker,
    mem::{transmute, MaybeUninit},
    slice,
};
use hash::Hash;
#[cfg(feature = "std")]
use std::{
    collections, convert, hash, marker,
    mem::{transmute, MaybeUninit},
    slice,
};
impl Serial for () {
    #[inline(always)]
    fn serial<W: Write>(&self, _out: &mut W) -> Result<(), W::Err> { Ok(()) }
}
impl Deserial for () {
    #[inline(always)]
    fn deserial<R: Read>(_source: &mut R) -> ParseResult<Self> { Ok(()) }
}
impl<A: Serial, B: Serial> Serial for (A, B) {
    fn serial<W: Write>(&self, out: &mut W) -> Result<(), W::Err> {
        self.0.serial(out)?;
        self.1.serial(out)
    }
}
impl<A: Deserial, B: Deserial> Deserial for (A, B) {
    fn deserial<R: Read>(source: &mut R) -> ParseResult<Self> {
        let a = source.get()?;
        let b = source.get()?;
        Ok((a, b))
    }
}
impl<X: Deserial, Y: Deserial, Z: Deserial> Deserial for (X, Y, Z) {
    fn deserial<R: Read>(source: &mut R) -> ParseResult<Self> {
        let a = source.get()?;
        let b = source.get()?;
        let c = source.get()?;
        Ok((a, b, c))
    }
}
impl<A: Serial, B: Serial, C: Serial> Serial for (A, B, C) {
    fn serial<W: Write>(&self, out: &mut W) -> Result<(), W::Err> {
        self.0.serial(out)?;
        self.1.serial(out)?;
        self.2.serial(out)?;
        Ok(())
    }
}
impl<A: Deserial, B: Deserial, C: Deserial, D: Deserial> Deserial for (A, B, C, D) {
    fn deserial<R: Read>(source: &mut R) -> ParseResult<Self> {
        let a = source.get()?;
        let b = source.get()?;
        let c = source.get()?;
        let d = source.get()?;
        Ok((a, b, c, d))
    }
}
impl<A: Serial, B: Serial, C: Serial, D: Serial> Serial for (A, B, C, D) {
    fn serial<W: Write>(&self, out: &mut W) -> Result<(), W::Err> {
        self.0.serial(out)?;
        self.1.serial(out)?;
        self.2.serial(out)?;
        self.3.serial(out)?;
        Ok(())
    }
}
impl<A: Deserial, B: Deserial, C: Deserial, D: Deserial, E: Deserial> Deserial for (A, B, C, D, E) {
    #[allow(clippy::many_single_char_names)]
    fn deserial<R: Read>(source: &mut R) -> ParseResult<Self> {
        let a = source.get()?;
        let b = source.get()?;
        let c = source.get()?;
        let d = source.get()?;
        let e = source.get()?;
        Ok((a, b, c, d, e))
    }
}
impl<A: Serial, B: Serial, C: Serial, D: Serial, E: Serial> Serial for (A, B, C, D, E) {
    fn serial<W: Write>(&self, out: &mut W) -> Result<(), W::Err> {
        self.0.serial(out)?;
        self.1.serial(out)?;
        self.2.serial(out)?;
        self.3.serial(out)?;
        self.4.serial(out)?;
        Ok(())
    }
}
impl<A: Deserial, B: Deserial, C: Deserial, D: Deserial, E: Deserial, F: Deserial> Deserial
    for (A, B, C, D, E, F)
{
    #[allow(clippy::many_single_char_names)]
    fn deserial<R: Read>(source: &mut R) -> ParseResult<Self> {
        let a = source.get()?;
        let b = source.get()?;
        let c = source.get()?;
        let d = source.get()?;
        let e = source.get()?;
        let f = source.get()?;
        Ok((a, b, c, d, e, f))
    }
}
impl<A: Serial, B: Serial, C: Serial, D: Serial, E: Serial, F: Serial> Serial
    for (A, B, C, D, E, F)
{
    fn serial<W: Write>(&self, out: &mut W) -> Result<(), W::Err> {
        self.0.serial(out)?;
        self.1.serial(out)?;
        self.2.serial(out)?;
        self.3.serial(out)?;
        self.4.serial(out)?;
        self.5.serial(out)?;
        Ok(())
    }
}
impl Serial for u8 {
    fn serial<W: Write>(&self, out: &mut W) -> Result<(), W::Err> { out.write_u8(*self) }
}
impl Deserial for u8 {
    fn deserial<R: Read>(source: &mut R) -> ParseResult<Self> { source.read_u8() }
}
impl Serial for u16 {
    fn serial<W: Write>(&self, out: &mut W) -> Result<(), W::Err> { out.write_u16(*self) }
}
impl Deserial for u16 {
    fn deserial<R: Read>(source: &mut R) -> ParseResult<Self> { source.read_u16() }
}
impl Serial for u32 {
    fn serial<W: Write>(&self, out: &mut W) -> Result<(), W::Err> { out.write_u32(*self) }
}
impl Deserial for u32 {
    fn deserial<R: Read>(source: &mut R) -> ParseResult<Self> { source.read_u32() }
}
impl Serial for u64 {
    fn serial<W: Write>(&self, out: &mut W) -> Result<(), W::Err> { out.write_u64(*self) }
}
impl Serial for u128 {
    fn serial<W: Write>(&self, out: &mut W) -> Result<(), W::Err> {
        out.write_all(&self.to_le_bytes())
    }
}
impl Deserial for u64 {
    fn deserial<R: Read>(source: &mut R) -> ParseResult<Self> { source.read_u64() }
}
impl Deserial for u128 {
    fn deserial<R: Read>(source: &mut R) -> ParseResult<Self> {
        let bytes = read_n_bytes!(16, source);
        Ok(u128::from_le_bytes(bytes))
    }
}
impl Serial for i8 {
    fn serial<W: Write>(&self, out: &mut W) -> Result<(), W::Err> { out.write_i8(*self) }
}
impl Deserial for i8 {
    fn deserial<R: Read>(source: &mut R) -> ParseResult<Self> { source.read_i8() }
}
impl Serial for i16 {
    fn serial<W: Write>(&self, out: &mut W) -> Result<(), W::Err> { out.write_i16(*self) }
}
impl Deserial for i16 {
    fn deserial<R: Read>(source: &mut R) -> ParseResult<Self> { source.read_i16() }
}
impl Serial for i32 {
    fn serial<W: Write>(&self, out: &mut W) -> Result<(), W::Err> { out.write_i32(*self) }
}
impl Deserial for i32 {
    fn deserial<R: Read>(source: &mut R) -> ParseResult<Self> { source.read_i32() }
}
impl Serial for i64 {
    fn serial<W: Write>(&self, out: &mut W) -> Result<(), W::Err> { out.write_i64(*self) }
}
impl Deserial for i64 {
    fn deserial<R: Read>(source: &mut R) -> ParseResult<Self> { source.read_i64() }
}
impl Serial for i128 {
    fn serial<W: Write>(&self, out: &mut W) -> Result<(), W::Err> {
        out.write_all(&self.to_le_bytes())
    }
}
impl Deserial for i128 {
    fn deserial<R: Read>(source: &mut R) -> ParseResult<Self> {
        let bytes = read_n_bytes!(16, source);
        Ok(i128::from_le_bytes(bytes))
    }
}
impl Serial for bool {
    fn serial<W: Write>(&self, out: &mut W) -> Result<(), W::Err> {
        if *self {
            out.write_u8(1)?;
        } else {
            out.write_u8(0)?;
        }
        Ok(())
    }
}
impl Deserial for bool {
    fn deserial<R: Read>(source: &mut R) -> ParseResult<Self> {
        let b = source.read_u8()?;
        match b {
            0 => Ok(false),
            1 => Ok(true),
            _ => Err(ParseError::default()),
        }
    }
}
impl Serial for Amount {
    fn serial<W: Write>(&self, out: &mut W) -> Result<(), W::Err> { out.write_u64(self.micro_ccd) }
}
impl Deserial for Amount {
    fn deserial<R: Read>(source: &mut R) -> ParseResult<Self> {
        source.read_u64().map(Amount::from_micro_ccd)
    }
}
impl Serial for AccountBalance {
    fn serial<W: Write>(&self, out: &mut W) -> Result<(), W::Err> {
        self.total.serial(out)?;
        self.staked.serial(out)?;
        self.locked.serial(out)?;
        Ok(())
    }
}
impl Deserial for AccountBalance {
    fn deserial<R: Read>(source: &mut R) -> ParseResult<Self> {
        let bytes: [u8; 24] = source.read_array()?;
        let chunks = unsafe { transmute::<[u8; 24], [[u8; 8]; 3]>(bytes) };
        let total = Amount::from_micro_ccd(u64::from_le_bytes(chunks[0]));
        let staked = Amount::from_micro_ccd(u64::from_le_bytes(chunks[1]));
        let locked = Amount::from_micro_ccd(u64::from_le_bytes(chunks[2]));
        Self::new(total, staked, locked).ok_or_else(ParseError::default)
    }
}
impl Serial for ExchangeRate {
    fn serial<W: Write>(&self, out: &mut W) -> Result<(), W::Err> {
        out.write_u64(self.numerator())?;
        out.write_u64(self.denominator())
    }
}
impl Deserial for ExchangeRate {
    fn deserial<R: Read>(source: &mut R) -> ParseResult<Self> {
        let numerator = source.read_u64()?;
        let denominator = source.read_u64()?;
        if numerator == 0 || denominator == 0 {
            Err(ParseError::default())
        } else {
            Ok(ExchangeRate::new_unchecked(numerator, denominator))
        }
    }
}
impl Serial for ExchangeRates {
    fn serial<W: Write>(&self, out: &mut W) -> Result<(), W::Err> {
        self.euro_per_energy.serial(out)?;
        self.micro_ccd_per_euro.serial(out)?;
        Ok(())
    }
}
impl Deserial for ExchangeRates {
    fn deserial<R: Read>(source: &mut R) -> ParseResult<Self> {
        let bytes: [u8; 32] = source.read_array()?;
        let chunks = unsafe { transmute::<[u8; 32], [[u8; 8]; 4]>(bytes) };
        let euro_per_energy_numerator = u64::from_le_bytes(chunks[0]);
        let euro_per_energy_denominator = u64::from_le_bytes(chunks[1]);
        let micro_ccd_per_euro_numerator = u64::from_le_bytes(chunks[2]);
        let micro_ccd_per_euro_denominator = u64::from_le_bytes(chunks[3]);
        if euro_per_energy_numerator == 0
            || euro_per_energy_denominator == 0
            || micro_ccd_per_euro_numerator == 0
            || micro_ccd_per_euro_denominator == 0
        {
            return Err(ParseError::default());
        }
        let euro_per_energy =
            ExchangeRate::new_unchecked(euro_per_energy_numerator, euro_per_energy_denominator);
        let micro_ccd_per_euro = ExchangeRate::new_unchecked(
            micro_ccd_per_euro_numerator,
            micro_ccd_per_euro_denominator,
        );
        Ok(Self {
            euro_per_energy,
            micro_ccd_per_euro,
        })
    }
}
impl Serial for Timestamp {
    fn serial<W: Write>(&self, out: &mut W) -> Result<(), W::Err> {
        self.timestamp_millis().serial(out)
    }
}
impl Deserial for Timestamp {
    fn deserial<R: Read>(source: &mut R) -> ParseResult<Self> {
        u64::deserial(source).map(Timestamp::from_timestamp_millis)
    }
}
impl Serial for Duration {
    fn serial<W: Write>(&self, out: &mut W) -> Result<(), W::Err> { self.millis().serial(out) }
}
impl Deserial for Duration {
    fn deserial<R: Read>(source: &mut R) -> ParseResult<Self> {
        u64::deserial(source).map(Duration::from_millis)
    }
}
impl Serial for &str {
    fn serial<W: Write>(&self, out: &mut W) -> Result<(), W::Err> {
        let bytes = self.as_bytes();
        let len = bytes.len() as u32;
        len.serial(out)?;
        out.write_all(bytes)
    }
}
impl<A: Serial> Serial for &A {
    fn serial<W: Write>(&self, out: &mut W) -> Result<(), W::Err> { (*self).serial(out) }
}
impl Serial for String {
    fn serial<W: Write>(&self, out: &mut W) -> Result<(), W::Err> { self.as_str().serial(out) }
}
impl Deserial for String {
    fn deserial<R: Read>(source: &mut R) -> ParseResult<Self> {
        let bytes = Vec::deserial(source)?;
        let res = String::from_utf8(bytes).map_err(|_| ParseError::default())?;
        Ok(res)
    }
}
impl<T: Serial> Serial for Box<T> {
    fn serial<W: Write>(&self, out: &mut W) -> Result<(), W::Err> { self.as_ref().serial(out) }
}
impl<T: Deserial> Deserial for Box<T> {
    #[inline]
    fn deserial<R: Read>(source: &mut R) -> ParseResult<Self> {
        let t = T::deserial(source)?;
        Ok(Box::new(t))
    }
}
impl<C: ?Sized> Serial for marker::PhantomData<C> {
    #[inline(always)]
    fn serial<W: Write>(&self, _out: &mut W) -> Result<(), W::Err> { Ok(()) }
}
impl<C: ?Sized> Deserial for marker::PhantomData<C> {
    #[inline(always)]
    fn deserial<R: Read>(_source: &mut R) -> ParseResult<Self> {
        Ok(marker::PhantomData::default())
    }
}
impl<T: Serial> Serial for Option<T> {
    fn serial<W: Write>(&self, out: &mut W) -> Result<(), W::Err> {
        match self {
            None => out.write_u8(0),
            Some(t) => {
                out.write_u8(1)?;
                t.serial(out)
            }
        }
    }
}
impl<T: Deserial> Deserial for Option<T> {
    fn deserial<R: Read>(source: &mut R) -> ParseResult<Self> {
        let idx: u8 = source.get()?;
        match idx {
            0 => Ok(None),
            1 => {
                let t = T::deserial(source)?;
                Ok(Some(t))
            }
            _ => Err(ParseError::default()),
        }
    }
}
impl Serial for AccountAddress {
    fn serial<W: Write>(&self, out: &mut W) -> Result<(), W::Err> { out.write_all(&self.0) }
}
impl Deserial for AccountAddress {
    fn deserial<R: Read>(source: &mut R) -> ParseResult<Self> {
        let bytes = {
            let mut bytes: MaybeUninit<[u8; 32]> = MaybeUninit::uninit();
            let write_bytes =
                unsafe { slice::from_raw_parts_mut(bytes.as_mut_ptr() as *mut u8, 32) };
            source.read_exact(write_bytes)?;
            unsafe { bytes.assume_init() }
        };
        Ok(AccountAddress(bytes))
    }
}
impl Serial for ContractAddress {
    fn serial<W: Write>(&self, out: &mut W) -> Result<(), W::Err> {
        out.write_u64(self.index)?;
        out.write_u64(self.subindex)
    }
}
impl Deserial for ContractAddress {
    #[inline]
    fn deserial<R: Read>(source: &mut R) -> ParseResult<Self> {
        let index = source.get()?;
        let subindex = source.get()?;
        Ok(ContractAddress {
            index,
            subindex,
        })
    }
}
impl Serial for Address {
    fn serial<W: Write>(&self, out: &mut W) -> Result<(), W::Err> {
        match self {
            Address::Account(ref acc) => {
                out.write_u8(0)?;
                acc.serial(out)
            }
            Address::Contract(ref cnt) => {
                out.write_u8(1)?;
                cnt.serial(out)
            }
        }
    }
}
impl Deserial for Address {
    fn deserial<R: Read>(source: &mut R) -> ParseResult<Self> {
        let tag = u8::deserial(source)?;
        match tag {
            0 => Ok(Address::Account(source.get()?)),
            1 => Ok(Address::Contract(source.get()?)),
            _ => Err(ParseError::default()),
        }
    }
}
impl<'a> Serial for ContractName<'a> {
    fn serial<W: Write>(&self, out: &mut W) -> Result<(), W::Err> {
        let name = self.get_chain_name();
        let len = name.len() as u16;
        len.serial(out)?;
        serial_vector_no_length(name.as_bytes(), out)
    }
}
impl Serial for OwnedContractName {
    fn serial<W: Write>(&self, out: &mut W) -> Result<(), W::Err> {
        self.as_contract_name().serial(out)
    }
}
impl Deserial for OwnedContractName {
    fn deserial<R: Read>(source: &mut R) -> ParseResult<Self> {
        let len: u16 = source.get()?;
        let bytes = deserial_vector_no_length(source, len as usize)?;
        let name = String::from_utf8(bytes).map_err(|_| ParseError::default())?;
        let owned_contract_name =
            OwnedContractName::new(name).map_err(|_| ParseError::default())?;
        Ok(owned_contract_name)
    }
}
impl<'a> Serial for ReceiveName<'a> {
    fn serial<W: Write>(&self, out: &mut W) -> Result<(), W::Err> {
        let name = self.get_chain_name();
        let len = name.len() as u16;
        len.serial(out)?;
        serial_vector_no_length(name.as_bytes(), out)
    }
}
impl Serial for OwnedReceiveName {
    fn serial<W: Write>(&self, out: &mut W) -> Result<(), W::Err> {
        self.as_receive_name().serial(out)
    }
}
impl Deserial for OwnedReceiveName {
    fn deserial<R: Read>(source: &mut R) -> ParseResult<Self> {
        let len: u16 = source.get()?;
        let bytes = deserial_vector_no_length(source, len as usize)?;
        let name = String::from_utf8(bytes).map_err(|_| ParseError::default())?;
        let owned_receive_name = OwnedReceiveName::new(name).map_err(|_| ParseError::default())?;
        Ok(owned_receive_name)
    }
}
impl<'a> Serial for EntrypointName<'a> {
    fn serial<W: Write>(&self, out: &mut W) -> Result<(), W::Err> {
        let len = self.0.len() as u16;
        len.serial(out)?;
        serial_vector_no_length(self.0.as_bytes(), out)
    }
}
impl Serial for OwnedEntrypointName {
    fn serial<W: Write>(&self, out: &mut W) -> Result<(), W::Err> {
        self.as_entrypoint_name().serial(out)
    }
}
impl Deserial for OwnedEntrypointName {
    fn deserial<R: Read>(source: &mut R) -> ParseResult<Self> {
        let len: u16 = source.get()?;
        let bytes = deserial_vector_no_length(source, len as usize)?;
        let name = String::from_utf8(bytes).map_err(|_| ParseError::default())?;
        let owned_entrypoint_name = Self::new(name).map_err(|_| ParseError::default())?;
        Ok(owned_entrypoint_name)
    }
}
impl<'a> Serial for Parameter<'a> {
    fn serial<W: Write>(&self, out: &mut W) -> Result<(), W::Err> {
        let len = self.0.len() as u16;
        len.serial(out)?;
        out.write_all(self.0)
    }
}
impl Serial for OwnedParameter {
    fn serial<W: Write>(&self, out: &mut W) -> Result<(), W::Err> {
        self.as_parameter().serial(out)
    }
}
impl Deserial for OwnedParameter {
    fn deserial<R: Read>(source: &mut R) -> ParseResult<Self> {
        let len: u16 = source.get()?;
        let bytes = deserial_vector_no_length(source, len as usize)?;
        Ok(Self(bytes))
    }
}
impl Serial for ChainMetadata {
    fn serial<W: Write>(&self, out: &mut W) -> Result<(), W::Err> { self.slot_time.serial(out) }
}
impl Deserial for ChainMetadata {
    fn deserial<R: Read>(source: &mut R) -> ParseResult<Self> {
        let slot_time = source.get()?;
        Ok(Self {
            slot_time,
        })
    }
}
impl<K: Serial + Ord> SerialCtx for BTreeSet<K> {
    fn serial_ctx<W: Write>(
        &self,
        size_len: schema::SizeLength,
        out: &mut W,
    ) -> Result<(), W::Err> {
        schema::serial_length(self.len(), size_len, out)?;
        serial_set_no_length(self, out)
    }
}
impl<K: Deserial + Ord> DeserialCtx for BTreeSet<K> {
    fn deserial_ctx<R: Read>(
        size_len: schema::SizeLength,
        ensure_ordered: bool,
        source: &mut R,
    ) -> ParseResult<Self> {
        let len = schema::deserial_length(source, size_len)?;
        if ensure_ordered {
            deserial_set_no_length(source, len)
        } else {
            deserial_set_no_length_no_order_check(source, len)
        }
    }
}
impl<K: Serial + Ord, V: Serial> SerialCtx for BTreeMap<K, V> {
    fn serial_ctx<W: Write>(
        &self,
        size_len: schema::SizeLength,
        out: &mut W,
    ) -> Result<(), W::Err> {
        schema::serial_length(self.len(), size_len, out)?;
        serial_map_no_length(self, out)
    }
}
impl<K: Deserial + Ord, V: Deserial> DeserialCtx for BTreeMap<K, V> {
    fn deserial_ctx<R: Read>(
        size_len: schema::SizeLength,
        ensure_ordered: bool,
        source: &mut R,
    ) -> ParseResult<Self> {
        let len = schema::deserial_length(source, size_len)?;
        if ensure_ordered {
            deserial_map_no_length(source, len)
        } else {
            deserial_map_no_length_no_order_check(source, len)
        }
    }
}
impl<K: Serial> SerialCtx for HashSet<K> {
    fn serial_ctx<W: Write>(
        &self,
        size_len: schema::SizeLength,
        out: &mut W,
    ) -> Result<(), W::Err> {
        schema::serial_length(self.len(), size_len, out)?;
        serial_hashset_no_length(self, out)
    }
}
impl<K: Deserial + Eq + Hash> DeserialCtx for HashSet<K> {
    fn deserial_ctx<R: Read>(
        size_len: schema::SizeLength,
        _ensure_ordered: bool,
        source: &mut R,
    ) -> ParseResult<Self> {
        let len = schema::deserial_length(source, size_len)?;
        deserial_hashset_no_length(source, len)
    }
}
impl<K: Serial, V: Serial> SerialCtx for HashMap<K, V> {
    fn serial_ctx<W: Write>(
        &self,
        size_len: schema::SizeLength,
        out: &mut W,
    ) -> Result<(), W::Err> {
        schema::serial_length(self.len(), size_len, out)?;
        serial_hashmap_no_length(self, out)
    }
}
impl<K: Deserial + Eq + Hash, V: Deserial> DeserialCtx for HashMap<K, V> {
    fn deserial_ctx<R: Read>(
        size_len: schema::SizeLength,
        _ensure_ordered: bool,
        source: &mut R,
    ) -> ParseResult<Self> {
        let len = schema::deserial_length(source, size_len)?;
        deserial_hashmap_no_length(source, len)
    }
}
impl<T: Serial> SerialCtx for &[T] {
    fn serial_ctx<W: Write>(
        &self,
        size_len: schema::SizeLength,
        out: &mut W,
    ) -> Result<(), W::Err> {
        schema::serial_length(self.len(), size_len, out)?;
        serial_vector_no_length(self, out)
    }
}
impl<T: Serial> SerialCtx for Vec<T> {
    fn serial_ctx<W: Write>(
        &self,
        size_len: schema::SizeLength,
        out: &mut W,
    ) -> Result<(), W::Err> {
        self.as_slice().serial_ctx(size_len, out)
    }
}
impl<T: Deserial> DeserialCtx for Vec<T> {
    fn deserial_ctx<R: Read>(
        size_len: schema::SizeLength,
        _ensure_ordered: bool,
        source: &mut R,
    ) -> ParseResult<Self> {
        let len = schema::deserial_length(source, size_len)?;
        deserial_vector_no_length(source, len)
    }
}
impl SerialCtx for &str {
    fn serial_ctx<W: Write>(
        &self,
        size_len: schema::SizeLength,
        out: &mut W,
    ) -> Result<(), W::Err> {
        schema::serial_length(self.len(), size_len, out)?;
        serial_vector_no_length(self.as_bytes(), out)
    }
}
impl SerialCtx for String {
    fn serial_ctx<W: Write>(
        &self,
        size_len: schema::SizeLength,
        out: &mut W,
    ) -> Result<(), W::Err> {
        self.as_str().serial_ctx(size_len, out)
    }
}
impl DeserialCtx for String {
    fn deserial_ctx<R: Read>(
        size_len: schema::SizeLength,
        _ensure_ordered: bool,
        source: &mut R,
    ) -> ParseResult<Self> {
        let len = schema::deserial_length(source, size_len)?;
        let bytes = deserial_vector_no_length(source, len)?;
        let res = String::from_utf8(bytes).map_err(|_| ParseError::default())?;
        Ok(res)
    }
}
pub fn serial_vector_no_length<W: Write, T: Serial>(xs: &[T], out: &mut W) -> Result<(), W::Err> {
    for x in xs {
        x.serial(out)?;
    }
    Ok(())
}
pub fn deserial_vector_no_length<R: Read, T: Deserial>(
    reader: &mut R,
    len: usize,
) -> ParseResult<Vec<T>> {
    let mut vec = Vec::with_capacity(core::cmp::min(len, MAX_PREALLOCATED_CAPACITY));
    for _ in 0..len {
        vec.push(T::deserial(reader)?);
    }
    Ok(vec)
}
pub fn serial_map_no_length<W: Write, K: Serial, V: Serial>(
    map: &BTreeMap<K, V>,
    out: &mut W,
) -> Result<(), W::Err> {
    for (k, v) in map.iter() {
        k.serial(out)?;
        v.serial(out)?;
    }
    Ok(())
}
pub fn deserial_map_no_length<R: Read, K: Deserial + Ord, V: Deserial>(
    source: &mut R,
    len: usize,
) -> ParseResult<BTreeMap<K, V>> {
    let mut out = BTreeMap::new();
    let mut x = None;
    for _ in 0..len {
        let k = source.get()?;
        let v = source.get()?;
        if let Some((old_k, old_v)) = x.take() {
            if k > old_k {
                out.insert(old_k, old_v);
            } else {
                return Err(ParseError::default());
            }
        }
        x = Some((k, v));
    }
    if let Some((k, v)) = x {
        out.insert(k, v);
    }
    Ok(out)
}
pub fn deserial_map_no_length_no_order_check<R: Read, K: Deserial + Ord, V: Deserial>(
    source: &mut R,
    len: usize,
) -> ParseResult<BTreeMap<K, V>> {
    let mut out = BTreeMap::new();
    for _ in 0..len {
        let k = source.get()?;
        let v = source.get()?;
        if out.insert(k, v).is_some() {
            return Err(ParseError::default());
        }
    }
    Ok(out)
}
pub fn serial_hashmap_no_length<W: Write, K: Serial, V: Serial>(
    map: &HashMap<K, V>,
    out: &mut W,
) -> Result<(), W::Err> {
    for (k, v) in map.iter() {
        k.serial(out)?;
        v.serial(out)?;
    }
    Ok(())
}
pub fn deserial_hashmap_no_length<R: Read, K: Deserial + Eq + Hash, V: Deserial>(
    source: &mut R,
    len: usize,
) -> ParseResult<HashMap<K, V>> {
    let mut out = HashMap::default();
    for _ in 0..len {
        let k = source.get()?;
        let v = source.get()?;
        if out.insert(k, v).is_some() {
            return Err(ParseError::default());
        }
    }
    Ok(out)
}
pub fn serial_set_no_length<W: Write, K: Serial>(
    map: &BTreeSet<K>,
    out: &mut W,
) -> Result<(), W::Err> {
    for k in map.iter() {
        k.serial(out)?;
    }
    Ok(())
}
pub fn deserial_set_no_length<R: Read, K: Deserial + Ord>(
    source: &mut R,
    len: usize,
) -> ParseResult<BTreeSet<K>> {
    let mut out = BTreeSet::new();
    let mut prev = None;
    for _ in 0..len {
        let key = source.get()?;
        if let Some(old_key) = prev.take() {
            if key > old_key {
                out.insert(old_key);
            } else {
                return Err(ParseError::default());
            }
        }
        prev = Some(key);
    }
    if let Some(key) = prev {
        out.insert(key);
    }
    Ok(out)
}
pub fn serial_hashset_no_length<W: Write, K: Serial>(
    map: &HashSet<K>,
    out: &mut W,
) -> Result<(), W::Err> {
    for k in map.iter() {
        k.serial(out)?;
    }
    Ok(())
}
pub fn deserial_hashset_no_length<R: Read, K: Deserial + Eq + Hash>(
    source: &mut R,
    len: usize,
) -> ParseResult<HashSet<K>> {
    let mut out = HashSet::default();
    for _ in 0..len {
        let key = source.get()?;
        if !out.insert(key) {
            return Err(ParseError::default());
        }
    }
    Ok(out)
}
pub fn deserial_set_no_length_no_order_check<R: Read, K: Deserial + Ord>(
    source: &mut R,
    len: usize,
) -> ParseResult<BTreeSet<K>> {
    let mut out = BTreeSet::new();
    for _ in 0..len {
        let key = source.get()?;
        if !out.insert(key) {
            return Err(ParseError::default());
        }
    }
    Ok(out)
}
impl<T: Serial> Serial for Vec<T> {
    fn serial<W: Write>(&self, out: &mut W) -> Result<(), W::Err> {
        let len = self.len() as u32;
        len.serial(out)?;
        serial_vector_no_length(self, out)
    }
}
impl<T: Deserial> Deserial for Vec<T> {
    fn deserial<R: Read>(source: &mut R) -> ParseResult<Self> {
        let len: u32 = source.get()?;
        deserial_vector_no_length(source, len as usize)
    }
}
impl<K: Serial + Ord, V: Serial> Serial for BTreeMap<K, V> {
    fn serial<W: Write>(&self, out: &mut W) -> Result<(), W::Err> {
        let len = self.len() as u32;
        len.serial(out)?;
        serial_map_no_length(self, out)
    }
}
impl<K: Deserial + Ord, V: Deserial> Deserial for BTreeMap<K, V> {
    fn deserial<R: Read>(source: &mut R) -> ParseResult<Self> {
        let len: u32 = source.get()?;
        deserial_map_no_length_no_order_check(source, len as usize)
    }
}
impl<K: Serial, V: Serial> Serial for HashMap<K, V> {
    fn serial<W: Write>(&self, out: &mut W) -> Result<(), W::Err> {
        let len = self.len() as u32;
        len.serial(out)?;
        serial_hashmap_no_length(self, out)
    }
}
impl<K: Deserial + Hash + Eq, V: Deserial> Deserial for HashMap<K, V> {
    fn deserial<R: Read>(source: &mut R) -> ParseResult<Self> {
        let len: u32 = source.get()?;
        deserial_hashmap_no_length(source, len as usize)
    }
}
impl<K: Serial + Ord> Serial for BTreeSet<K> {
    fn serial<W: Write>(&self, out: &mut W) -> Result<(), W::Err> {
        let len = self.len() as u32;
        len.serial(out)?;
        serial_set_no_length(self, out)
    }
}
impl<K: Deserial + Ord> Deserial for BTreeSet<K> {
    fn deserial<R: Read>(source: &mut R) -> ParseResult<Self> {
        let len: u32 = source.get()?;
        deserial_set_no_length_no_order_check(source, len as usize)
    }
}
impl<K: Serial> Serial for HashSet<K> {
    fn serial<W: Write>(&self, out: &mut W) -> Result<(), W::Err> {
        let len = self.len() as u32;
        len.serial(out)?;
        serial_hashset_no_length(self, out)
    }
}
impl<K: Deserial + Hash + Eq> Deserial for HashSet<K> {
    fn deserial<R: Read>(source: &mut R) -> ParseResult<Self> {
        let len: u32 = source.get()?;
        deserial_hashset_no_length(source, len as usize)
    }
}
impl<T: Serial, const N: usize> Serial for [T; N] {
    fn serial<W: Write>(&self, out: &mut W) -> Result<(), W::Err> {
        for elem in self.iter() {
            elem.serial(out)?;
        }
        Ok(())
    }
}
impl<T: Deserial, const N: usize> Deserial for [T; N] {
    fn deserial<R: Read>(source: &mut R) -> ParseResult<Self> {
        let mut data: [MaybeUninit<T>; N] = unsafe { MaybeUninit::uninit().assume_init() };
        for item in data.iter_mut() {
            *item = MaybeUninit::new(T::deserial(source)?);
        }
        Ok(unsafe { data.as_ptr().cast::<[T; N]>().read() })
    }
}
impl Address {
    pub fn matches_account(&self, acc: &AccountAddress) -> bool {
        if let Address::Account(ref my_acc) = self {
            my_acc == acc
        } else {
            false
        }
    }
    pub fn matches_contract(&self, cnt: &ContractAddress) -> bool {
        if let Address::Contract(ref my_cnt) = self {
            my_cnt == cnt
        } else {
            false
        }
    }
    pub fn is_account(&self) -> bool { matches!(self, Address::Account(_)) }
    pub fn is_contract(&self) -> bool { matches!(self, Address::Contract(_)) }
}
impl Serial for AttributeTag {
    fn serial<W: Write>(&self, out: &mut W) -> Result<(), W::Err> { self.0.serial(out) }
}
impl Deserial for AttributeTag {
    fn deserial<R: Read>(source: &mut R) -> ParseResult<Self> { Ok(AttributeTag(source.get()?)) }
}
impl Serial for AttributeValue {
    fn serial<W: Write>(&self, out: &mut W) -> Result<(), W::Err> {
        out.write_all(&self.inner[..=self.len()]) }
}
impl Deserial for AttributeValue {
    fn deserial<R: Read>(source: &mut R) -> ParseResult<Self> {
        let mut buf = [0u8; 32];
        let len: u8 = source.get()?;
        buf[0] = len;
        if len > 31 {
            return Err(ParseError::default());
        }
        source.read_exact(&mut buf[1..=len as usize])?;
        Ok(unsafe { AttributeValue::new_unchecked(buf) })
    }
}
impl Serial for OwnedPolicy {
    fn serial<W: Write>(&self, out: &mut W) -> Result<(), W::Err> {
        self.identity_provider.serial(out)?;
        self.created_at.serial(out)?;
        self.valid_to.serial(out)?;
        (self.items.len() as u16).serial(out)?;
        for item in self.items.iter() {
            item.0.serial(out)?;
            item.1.serial(out)?;
        }
        Ok(())
    }
}
impl Deserial for OwnedPolicy {
    fn deserial<R: Read>(source: &mut R) -> ParseResult<Self> {
        let identity_provider = source.get()?;
        let created_at = source.get()?;
        let valid_to = source.get()?;
        let len: u16 = source.get()?;
        let mut items = Vec::with_capacity(len as usize);
        for _ in 0..len {
            let tag = AttributeTag::deserial(source)?;
            let value = AttributeValue::deserial(source)?;
            items.push((tag, value))
        }
        Ok(Self {
            identity_provider,
            created_at,
            valid_to,
            items,
        })
    }
}
impl<T> Cursor<T> {
    pub fn new(data: T) -> Self {
        Cursor {
            offset: 0,
            data,
        }
    }
}
impl<T: AsRef<[u8]>> Read for Cursor<T> {
    fn read(&mut self, buf: &mut [u8]) -> ParseResult<usize> {
        let mut len = self.data.as_ref().len() - self.offset;
        if len > buf.len() {
            len = buf.len();
        }
        if len > 0 {
            buf[0..len].copy_from_slice(&self.data.as_ref()[self.offset..self.offset + len]);
            self.offset += len;
            Ok(len)
        } else {
            Ok(0)
        }
    }
}
impl<T: AsRef<[u8]>> HasSize for T {
    fn size(&self) -> u32 { self.as_ref().len() as u32 }
}
impl<T: AsRef<[u8]>> AsRef<[u8]> for Cursor<T> {
    fn as_ref(&self) -> &[u8] { self.data.as_ref() }
}
impl<T: HasSize> Seek for Cursor<T> {
    type Err = ();
    fn seek(&mut self, pos: SeekFrom) -> Result<u32, Self::Err> {
        use SeekFrom::*;
        let end = self.data.size();
        match pos {
            Start(offset) => {
                if offset <= end {
                    self.offset = offset as usize;
                    Ok(offset)
                } else {
                    Err(())
                }
            }
            End(delta) => {
                if delta > 0 {
                    Err(()) } else {
                    let new_offset = end.wrapping_add(delta as u32);
                    if new_offset <= end {
                        self.offset = new_offset as usize;
                        Ok(new_offset)
                    } else {
                        Err(())
                    }
                }
            }
            Current(delta) => {
                let current_offset = u32::try_from(self.offset).map_err(|_| ())?;
                let new_offset: u32 = current_offset.wrapping_add(delta as u32);
                if new_offset <= end {
                    self.offset = new_offset as usize;
                    Ok(new_offset)
                } else {
                    Err(())
                }
            }
        }
    }
    #[inline(always)]
    fn cursor_position(&self) -> u32 { self.offset as u32 }
}
impl Write for Cursor<&mut Vec<u8>> {
    type Err = ();
    fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Err> {
        if buf.is_empty() {
            Ok(0)
        } else {
            let remaining_len = self.data.len() - self.offset;
            let (to_write, to_extend): (_, &[u8]) = {
                if remaining_len >= buf.len() {
                    (buf, &[])
                } else {
                    (&buf[..remaining_len], &buf[remaining_len..])
                }
            };
            self.data[self.offset..self.offset + to_write.len()].copy_from_slice(to_write);
            self.data.extend_from_slice(to_extend);
            self.offset += buf.len();
            Ok(buf.len())
        }
    }
}
pub fn to_bytes<S: Serial>(x: &S) -> Vec<u8> {
    let mut out = Vec::new();
    let mut cursor = Cursor::new(&mut out);
    x.serial(&mut cursor).expect("Writing to a vector should succeed.");
    out
}
#[inline]
pub fn from_bytes<S: Deserial>(source: &[u8]) -> ParseResult<S> {
    let mut cursor = Cursor::new(source);
    cursor.get()
}
#[cfg(test)]
mod test {
    use super::*;
    #[test]
    fn test_u64_array_deserial_serial_is_id() {
        let xs: [u64; 1] = [123];
        let bytes = to_bytes(&xs);
        let xs2: ParseResult<[u64; 1]> = from_bytes(&bytes);
        assert_eq!(
            xs,
            xs2.unwrap(),
            "Serializing and then deserializing should return original value."
        );
    }
    #[test]
    fn test_string_array_deserial_serial_is_id() {
        let xs: [String; 1] = ["hello".to_string()];
        let bytes = to_bytes(&xs);
        let xs2: ParseResult<[String; 1]> = from_bytes(&bytes);
        assert_eq!(
            xs,
            xs2.unwrap(),
            "Serializing and then deserializing should return original value."
        );
    }
    #[test]
    fn test_cursor_seek_start() {
        let bytes = [0u8; 10];
        let mut cursor = Cursor::new(&bytes);
        let result = cursor.seek(SeekFrom::Start(8));
        let position = result.expect("Seek should succeed");
        assert_eq!(position, 8, "Seek moved to the wrong position");
    }
    #[test]
    fn test_cursor_seek_start_at_the_end() {
        let bytes = [0u8; 10];
        let mut cursor = Cursor::new(&bytes);
        let result = cursor.seek(SeekFrom::Start(10));
        let position = result.expect("Seek should succeed");
        assert_eq!(position, 10, "Seek moved to the wrong position");
    }
    #[test]
    fn test_cursor_seek_start_fails_beyond_end() {
        let bytes = [0u8; 10];
        let mut cursor = Cursor::new(&bytes);
        let result = cursor.seek(SeekFrom::Start(11));
        result.expect_err("Should have failed to seek beyond end of data");
    }
    #[test]
    fn test_cursor_seek_end() {
        let bytes = [0u8; 10];
        let mut cursor = Cursor::new(&bytes);
        let result = cursor.seek(SeekFrom::End(-8));
        let position = result.expect("Seek should succeed");
        assert_eq!(position, 2, "Seek moved to the wrong position");
    }
    #[test]
    fn test_cursor_seek_end_at_the_start() {
        let bytes = [0u8; 10];
        let mut cursor = Cursor::new(&bytes);
        let result = cursor.seek(SeekFrom::End(-10));
        let position = result.expect("Seek should succeed");
        assert_eq!(position, 0, "Seek moved to the wrong position");
    }
    #[test]
    fn test_cursor_seek_end_at_the_end() {
        let bytes = [0u8; 10];
        let mut cursor = Cursor::new(&bytes);
        let result = cursor.seek(SeekFrom::End(0));
        let position = result.expect("Seek should succeed");
        assert_eq!(position, 10, "Seek moved to the wrong position");
    }
    #[test]
    fn test_cursor_seek_end_fails_before_start() {
        let bytes = [0u8; 10];
        let mut cursor = Cursor::new(&bytes);
        let result = cursor.seek(SeekFrom::End(-11));
        result.expect_err("Should have failed to seek before start of data");
    }
    #[test]
    fn test_cursor_seek_end_fails_beyond_end() {
        let bytes = [0u8; 10];
        let mut cursor = Cursor::new(&bytes);
        let result = cursor.seek(SeekFrom::End(1));
        result.expect_err("Should have failed to seek beyond end of data");
    }
    #[test]
    fn test_cursor_seek_current_forward_twice() {
        let bytes = [0u8; 10];
        let mut cursor = Cursor::new(&bytes);
        let result = cursor.seek(SeekFrom::Current(4));
        let position = result.expect("Seek should succeed");
        assert_eq!(position, 4, "Seek moved to the wrong position");
        let result = cursor.seek(SeekFrom::Current(2));
        let position = result.expect("Seek should succeed");
        assert_eq!(position, 6, "Seek moved to the wrong position");
    }
    #[test]
    fn test_cursor_seek_current_forward_backward() {
        let bytes = [0u8; 10];
        let mut cursor = Cursor::new(&bytes);
        cursor.seek(SeekFrom::Current(4)).expect("Seek should succeed");
        let result = cursor.seek(SeekFrom::Current(-2));
        let position = result.expect("Seek should succeed");
        assert_eq!(position, 2, "Seek moved to the wrong position");
    }
    #[test]
    fn test_cursor_seek_current_forward_backward_fail_before_start() {
        let bytes = [0u8; 10];
        let mut cursor = Cursor::new(&bytes);
        cursor.seek(SeekFrom::Current(4)).expect("Seek should succeed");
        let result = cursor.seek(SeekFrom::Current(-5));
        result.expect_err("Should have failed to seek before start of data");
    }
    #[test]
    fn test_cursor_seek_current_forward_twice_fail_beyond_end() {
        let bytes = [0u8; 10];
        let mut cursor = Cursor::new(&bytes);
        cursor.seek(SeekFrom::Current(4)).expect("Seek should succeed");
        let result = cursor.seek(SeekFrom::Current(7));
        result.expect_err("Should have failed to seek beyond end of data");
    }
    #[test]
    fn test_owned_policy_serial_deserial_is_identity() {
        let op = OwnedPolicy {
            identity_provider: 1234,
            created_at:        Timestamp::from_timestamp_millis(11),
            valid_to:          Timestamp::from_timestamp_millis(999999),
            items:             vec![
                (attributes::COUNTRY_OF_RESIDENCE, b"DK".into()),
                (attributes::ID_DOC_TYPE, b"A document type with 31 chars..".into()),
            ],
        };
        let mut buf = Vec::new();
        op.serial(&mut buf).unwrap();
        let res = OwnedPolicy::deserial(&mut Cursor::new(buf)).unwrap();
        assert_eq!(op.identity_provider, res.identity_provider, "identity provider didn't match");
        assert_eq!(op.created_at, res.created_at, "created_at didn't match");
        assert_eq!(op.valid_to, res.valid_to, "valid_to didn't match");
        assert_eq!(op.items, res.items, "items didn't match");
    }
}