use super::op_code::OpCode;
use super::sigma_byte_writer::SigmaByteWrite;
use super::SigmaSerializationError;
use crate::serialization::SigmaSerializeResult;
use crate::serialization::{
sigma_byte_reader::SigmaByteRead, SigmaParsingError, SigmaSerializable,
};
use crate::types::stuple;
use crate::types::stype::SType;
use crate::types::stype_param;
use num_derive::FromPrimitive;
use num_traits::FromPrimitive;
use std::convert::TryInto;
#[allow(non_camel_case_types)]
#[allow(clippy::upper_case_acronyms)] #[derive(Copy, Clone, Debug, PartialEq, Eq, FromPrimitive)]
#[repr(u8)]
pub enum TypeCode {
SBOOLEAN = 1,
SBYTE = 2,
SSHORT = 3,
SINT = 4,
SLONG = 5,
SBIGINT = 6,
SGROUP_ELEMENT = 7,
SSIGMAPROP = 8,
COLL = (TypeCode::MAX_PRIM_TYPECODE + 1) * TypeCode::COLLECTION_CONSTR_ID, COLL_BOOL = TypeCode::COLL as u8 + TypeCode::SBOOLEAN as u8, COLL_BYTE = TypeCode::COLL as u8 + TypeCode::SBYTE as u8, COLL_SHORT = TypeCode::COLL as u8 + TypeCode::SSHORT as u8, COLL_INT = TypeCode::COLL as u8 + TypeCode::SINT as u8, COLL_LONG = TypeCode::COLL as u8 + TypeCode::SLONG as u8, COLL_BIGINT = TypeCode::COLL as u8 + TypeCode::SBIGINT as u8, COLL_GROUP_ELEMENT = TypeCode::COLL as u8 + TypeCode::SGROUP_ELEMENT as u8, COLL_SIGMAPROP = TypeCode::COLL as u8 + TypeCode::SSIGMAPROP as u8,
NESTED_COLL_BOOL = TypeCode::NESTED_COLL as u8 + TypeCode::SBOOLEAN as u8, NESTED_COLL_BYTE = TypeCode::NESTED_COLL as u8 + TypeCode::SBYTE as u8, NESTED_COLL_SHORT = TypeCode::NESTED_COLL as u8 + TypeCode::SSHORT as u8, NESTED_COLL_INT = TypeCode::NESTED_COLL as u8 + TypeCode::SINT as u8, NESTED_COLL_LONG = TypeCode::NESTED_COLL as u8 + TypeCode::SLONG as u8, NESTED_COLL_BIGINT = TypeCode::NESTED_COLL as u8 + TypeCode::SBIGINT as u8, NESTED_COLL_GROUP_ELEMENT = TypeCode::NESTED_COLL as u8 + TypeCode::SGROUP_ELEMENT as u8, NESTED_COLL_SIGMAPROP = TypeCode::NESTED_COLL as u8 + TypeCode::SSIGMAPROP as u8,
OPTION = (TypeCode::MAX_PRIM_TYPECODE + 1) * TypeCode::OPTION_CONSTR_ID, OPTION_BOOL = TypeCode::OPTION as u8 + TypeCode::SBOOLEAN as u8, OPTION_BYTE = TypeCode::OPTION as u8 + TypeCode::SBYTE as u8, OPTION_SHORT = TypeCode::OPTION as u8 + TypeCode::SSHORT as u8, OPTION_INT = TypeCode::OPTION as u8 + TypeCode::SINT as u8, OPTION_LONG = TypeCode::OPTION as u8 + TypeCode::SLONG as u8, OPTION_BIGINT = TypeCode::OPTION as u8 + TypeCode::SBIGINT as u8, OPTION_GROUP_ELEMENT = TypeCode::OPTION as u8 + TypeCode::SGROUP_ELEMENT as u8, OPTION_SIGMAPROP = TypeCode::OPTION as u8 + TypeCode::SSIGMAPROP as u8,
OPTION_COLL_BOOL = TypeCode::OPTION_COLLECTION as u8 + TypeCode::SBOOLEAN as u8, OPTION_COLL_BYTE = TypeCode::OPTION_COLLECTION as u8 + TypeCode::SBYTE as u8, OPTION_COLL_SHORT = TypeCode::OPTION_COLLECTION as u8 + TypeCode::SSHORT as u8, OPTION_COLL_INT = TypeCode::OPTION_COLLECTION as u8 + TypeCode::SINT as u8, OPTION_COLL_LONG = TypeCode::OPTION_COLLECTION as u8 + TypeCode::SLONG as u8, OPTION_COLL_BIGINT = TypeCode::OPTION_COLLECTION as u8 + TypeCode::SBIGINT as u8, OPTION_COLL_GROUP_ELEMENT = TypeCode::OPTION_COLLECTION as u8 + TypeCode::SGROUP_ELEMENT as u8, OPTION_COLL_SIGMAPROP = TypeCode::OPTION_COLLECTION as u8 + TypeCode::SSIGMAPROP as u8,
TUPLE_PAIR1 = (TypeCode::MAX_PRIM_TYPECODE + 1) * TypeCode::TUPLE_PAIR1_CONSTR_ID, TUPLE_PAIR1_BOOL = TypeCode::TUPLE_PAIR1 as u8 + TypeCode::SBOOLEAN as u8, TUPLE_PAIR1_BYTE = TypeCode::TUPLE_PAIR1 as u8 + TypeCode::SBYTE as u8, TUPLE_PAIR1_SHORT = TypeCode::TUPLE_PAIR1 as u8 + TypeCode::SSHORT as u8, TUPLE_PAIR1_INT = TypeCode::TUPLE_PAIR1 as u8 + TypeCode::SINT as u8, TUPLE_PAIR1_LONG = TypeCode::TUPLE_PAIR1 as u8 + TypeCode::SLONG as u8, TUPLE_PAIR1_BIGINT = TypeCode::TUPLE_PAIR1 as u8 + TypeCode::SBIGINT as u8, TUPLE_PAIR1_GROUP_ELEMENT = TypeCode::TUPLE_PAIR1 as u8 + TypeCode::SGROUP_ELEMENT as u8, TUPLE_PAIR1_SIGMAPROP = TypeCode::TUPLE_PAIR1 as u8 + TypeCode::SSIGMAPROP as u8,
TUPLE_TRIPLE = Self::TUPLE_PAIR2,
TUPLE_PAIR2_BOOL = TypeCode::TUPLE_PAIR2 as u8 + TypeCode::SBOOLEAN as u8, TUPLE_PAIR2_BYTE = TypeCode::TUPLE_PAIR2 as u8 + TypeCode::SBYTE as u8, TUPLE_PAIR2_SHORT = TypeCode::TUPLE_PAIR2 as u8 + TypeCode::SSHORT as u8, TUPLE_PAIR2_INT = TypeCode::TUPLE_PAIR2 as u8 + TypeCode::SINT as u8, TUPLE_PAIR2_LONG = TypeCode::TUPLE_PAIR2 as u8 + TypeCode::SLONG as u8, TUPLE_PAIR2_BIGINT = TypeCode::TUPLE_PAIR2 as u8 + TypeCode::SBIGINT as u8, TUPLE_PAIR2_GROUP_ELEMENT = TypeCode::TUPLE_PAIR2 as u8 + TypeCode::SGROUP_ELEMENT as u8, TUPLE_PAIR2_SIGMAPROP = TypeCode::TUPLE_PAIR2 as u8 + TypeCode::SSIGMAPROP as u8,
TUPLE_QUADRUPLE = Self::TUPLE_PAIR_SYMMETRIC,
TUPLE_PAIR_SYMMETRIC_BOOL = TypeCode::TUPLE_PAIR_SYMMETRIC as u8 + TypeCode::SBOOLEAN as u8, TUPLE_PAIR_SYMMETRIC_BYTE = TypeCode::TUPLE_PAIR_SYMMETRIC as u8 + TypeCode::SBYTE as u8, TUPLE_PAIR_SYMMETRIC_SHORT = TypeCode::TUPLE_PAIR_SYMMETRIC as u8 + TypeCode::SSHORT as u8, TUPLE_PAIR_SYMMETRIC_INT = TypeCode::TUPLE_PAIR_SYMMETRIC as u8 + TypeCode::SINT as u8, TUPLE_PAIR_SYMMETRIC_LONG = TypeCode::TUPLE_PAIR_SYMMETRIC as u8 + TypeCode::SLONG as u8, TUPLE_PAIR_SYMMETRIC_BIGINT = TypeCode::TUPLE_PAIR_SYMMETRIC as u8 + TypeCode::SBIGINT as u8, TUPLE_PAIR_SYMMETRIC_GROUP_ELEMENT =
TypeCode::TUPLE_PAIR_SYMMETRIC as u8 + TypeCode::SGROUP_ELEMENT as u8, TUPLE_PAIR_SYMMETRIC_SIGMAPROP =
TypeCode::TUPLE_PAIR_SYMMETRIC as u8 + TypeCode::SSIGMAPROP as u8,
TUPLE = (TypeCode::MAX_PRIM_TYPECODE + 1) * 8,
SANY = 97,
SUNIT = 98,
SBOX = 99,
SAVL_TREE = 100,
SCONTEXT = 101,
STYPE_VAR = 103,
SHEADER = 104,
SPRE_HEADER = 105,
SGLOBAL = 106,
}
impl TypeCode {
#[allow(dead_code)]
const FIRST_FUNC_TYPE: u8 = OpCode::LAST_DATA_TYPE.value();
#[allow(dead_code)]
const LAST_FUNC_TYPE: u8 = 255;
#[allow(dead_code)]
const LAST_PRIM_TYPECODE: u8 = 8;
const MAX_PRIM_TYPECODE: u8 = 11;
const COLLECTION_CONSTR_ID: u8 = 1;
const NESTED_COLLECTION_CONSTS_ID: u8 = 2;
const NESTED_COLL: u8 =
(TypeCode::MAX_PRIM_TYPECODE + 1) * TypeCode::NESTED_COLLECTION_CONSTS_ID;
const OPTION_CONSTR_ID: u8 = 3;
const OPTION_COLLECTION_TYPE_CONSTR_ID: u8 = 4;
const OPTION_COLLECTION: u8 =
(TypeCode::MAX_PRIM_TYPECODE + 1) * TypeCode::OPTION_COLLECTION_TYPE_CONSTR_ID;
const TUPLE_PAIR1_CONSTR_ID: u8 = 5;
const TUPLE_PAIR2_CONSTR_ID: u8 = 6;
const TUPLE_PAIR2: u8 = (TypeCode::MAX_PRIM_TYPECODE + 1) * TypeCode::TUPLE_PAIR2_CONSTR_ID;
const TUPLE_PAIR_SYMMETRIC_TYPE_CONSTR_ID: u8 = 7;
const TUPLE_PAIR_SYMMETRIC: u8 =
(TypeCode::MAX_PRIM_TYPECODE + 1) * TypeCode::TUPLE_PAIR_SYMMETRIC_TYPE_CONSTR_ID;
pub(crate) fn parse(b: u8) -> Result<Self, SigmaParsingError> {
match FromPrimitive::from_u8(b) {
Some(t) => Ok(t),
None => Err(SigmaParsingError::InvalidTypeCode(b)),
}
}
pub(crate) const fn value(&self) -> u8 {
*self as u8
}
}
impl SigmaSerializable for TypeCode {
fn sigma_serialize<W: SigmaByteWrite>(&self, w: &mut W) -> SigmaSerializeResult {
w.put_u8(self.value())?;
Ok(())
}
fn sigma_parse<R: SigmaByteRead>(r: &mut R) -> Result<Self, SigmaParsingError> {
let b = r.get_u8()?;
Self::parse(b)
}
}
impl SType {
pub(crate) fn parse_with_type_code<R: SigmaByteRead>(
r: &mut R,
c: TypeCode,
) -> Result<Self, SigmaParsingError> {
use SType::*;
Ok(match c {
TypeCode::SBOOLEAN => SBoolean,
TypeCode::SBYTE => SByte,
TypeCode::SSHORT => SShort,
TypeCode::SINT => SInt,
TypeCode::SLONG => SLong,
TypeCode::SBIGINT => SBigInt,
TypeCode::SGROUP_ELEMENT => SGroupElement,
TypeCode::SSIGMAPROP => SSigmaProp,
TypeCode::COLL => SColl(SType::sigma_parse(r)?.into()),
TypeCode::COLL_BOOL => SColl(SBoolean.into()),
TypeCode::COLL_BYTE => SColl(SByte.into()),
TypeCode::COLL_SHORT => SColl(SShort.into()),
TypeCode::COLL_INT => SColl(SInt.into()),
TypeCode::COLL_LONG => SColl(SLong.into()),
TypeCode::COLL_BIGINT => SColl(SBigInt.into()),
TypeCode::COLL_GROUP_ELEMENT => SColl(SGroupElement.into()),
TypeCode::COLL_SIGMAPROP => SColl(SSigmaProp.into()),
TypeCode::NESTED_COLL_BOOL => SColl(SColl(SBoolean.into()).into()),
TypeCode::NESTED_COLL_BYTE => SColl(SColl(SByte.into()).into()),
TypeCode::NESTED_COLL_SHORT => SColl(SColl(SShort.into()).into()),
TypeCode::NESTED_COLL_INT => SColl(SColl(SInt.into()).into()),
TypeCode::NESTED_COLL_LONG => SColl(SColl(SLong.into()).into()),
TypeCode::NESTED_COLL_BIGINT => SColl(SColl(SBigInt.into()).into()),
TypeCode::NESTED_COLL_GROUP_ELEMENT => SColl(SColl(SGroupElement.into()).into()),
TypeCode::NESTED_COLL_SIGMAPROP => SColl(SColl(SSigmaProp.into()).into()),
TypeCode::OPTION => SOption(SType::sigma_parse(r)?.into()),
TypeCode::OPTION_BOOL => SOption(SBoolean.into()),
TypeCode::OPTION_BYTE => SOption(SByte.into()),
TypeCode::OPTION_SHORT => SOption(SShort.into()),
TypeCode::OPTION_INT => SOption(SInt.into()),
TypeCode::OPTION_LONG => SOption(SLong.into()),
TypeCode::OPTION_BIGINT => SOption(SBigInt.into()),
TypeCode::OPTION_GROUP_ELEMENT => SOption(SGroupElement.into()),
TypeCode::OPTION_SIGMAPROP => SOption(SSigmaProp.into()),
TypeCode::OPTION_COLL_BOOL => SOption(SColl(SBoolean.into()).into()),
TypeCode::OPTION_COLL_BYTE => SOption(SColl(SByte.into()).into()),
TypeCode::OPTION_COLL_SHORT => SOption(SColl(SShort.into()).into()),
TypeCode::OPTION_COLL_INT => SOption(SColl(SInt.into()).into()),
TypeCode::OPTION_COLL_LONG => SOption(SColl(SLong.into()).into()),
TypeCode::OPTION_COLL_BIGINT => SOption(SColl(SBigInt.into()).into()),
TypeCode::OPTION_COLL_GROUP_ELEMENT => SOption(SColl(SGroupElement.into()).into()),
TypeCode::OPTION_COLL_SIGMAPROP => SOption(SColl(SSigmaProp.into()).into()),
TypeCode::TUPLE_PAIR1 => STuple(stuple::STuple::pair(
SType::sigma_parse(r)?,
SType::sigma_parse(r)?,
)),
TypeCode::TUPLE_PAIR1_BOOL => {
STuple(stuple::STuple::pair(SBoolean, SType::sigma_parse(r)?))
}
TypeCode::TUPLE_PAIR1_BYTE => {
STuple(stuple::STuple::pair(SByte, SType::sigma_parse(r)?))
}
TypeCode::TUPLE_PAIR1_SHORT => {
STuple(stuple::STuple::pair(SShort, SType::sigma_parse(r)?))
}
TypeCode::TUPLE_PAIR1_INT => STuple(stuple::STuple::pair(SInt, SType::sigma_parse(r)?)),
TypeCode::TUPLE_PAIR1_LONG => {
STuple(stuple::STuple::pair(SLong, SType::sigma_parse(r)?))
}
TypeCode::TUPLE_PAIR1_BIGINT => {
STuple(stuple::STuple::pair(SBigInt, SType::sigma_parse(r)?))
}
TypeCode::TUPLE_PAIR1_GROUP_ELEMENT => {
STuple(stuple::STuple::pair(SGroupElement, SType::sigma_parse(r)?))
}
TypeCode::TUPLE_PAIR1_SIGMAPROP => {
STuple(stuple::STuple::pair(SSigmaProp, SType::sigma_parse(r)?))
}
TypeCode::TUPLE_TRIPLE => STuple(stuple::STuple::triple(
SType::sigma_parse(r)?,
SType::sigma_parse(r)?,
SType::sigma_parse(r)?,
)),
TypeCode::TUPLE_PAIR2_BOOL => {
STuple(stuple::STuple::pair(SType::sigma_parse(r)?, SBoolean))
}
TypeCode::TUPLE_PAIR2_BYTE => {
STuple(stuple::STuple::pair(SType::sigma_parse(r)?, SByte))
}
TypeCode::TUPLE_PAIR2_SHORT => {
STuple(stuple::STuple::pair(SType::sigma_parse(r)?, SShort))
}
TypeCode::TUPLE_PAIR2_INT => STuple(stuple::STuple::pair(SType::sigma_parse(r)?, SInt)),
TypeCode::TUPLE_PAIR2_LONG => {
STuple(stuple::STuple::pair(SType::sigma_parse(r)?, SLong))
}
TypeCode::TUPLE_PAIR2_BIGINT => {
STuple(stuple::STuple::pair(SType::sigma_parse(r)?, SBigInt))
}
TypeCode::TUPLE_PAIR2_GROUP_ELEMENT => {
STuple(stuple::STuple::pair(SType::sigma_parse(r)?, SGroupElement))
}
TypeCode::TUPLE_PAIR2_SIGMAPROP => {
STuple(stuple::STuple::pair(SType::sigma_parse(r)?, SSigmaProp))
}
TypeCode::TUPLE_QUADRUPLE => STuple(stuple::STuple::quadruple(
SType::sigma_parse(r)?,
SType::sigma_parse(r)?,
SType::sigma_parse(r)?,
SType::sigma_parse(r)?,
)),
TypeCode::TUPLE_PAIR_SYMMETRIC_BOOL => STuple(stuple::STuple::pair(SBoolean, SBoolean)),
TypeCode::TUPLE_PAIR_SYMMETRIC_BYTE => STuple(stuple::STuple::pair(SByte, SByte)),
TypeCode::TUPLE_PAIR_SYMMETRIC_SHORT => STuple(stuple::STuple::pair(SShort, SShort)),
TypeCode::TUPLE_PAIR_SYMMETRIC_INT => STuple(stuple::STuple::pair(SInt, SInt)),
TypeCode::TUPLE_PAIR_SYMMETRIC_LONG => STuple(stuple::STuple::pair(SLong, SLong)),
TypeCode::TUPLE_PAIR_SYMMETRIC_BIGINT => STuple(stuple::STuple::pair(SBigInt, SBigInt)),
TypeCode::TUPLE_PAIR_SYMMETRIC_GROUP_ELEMENT => {
STuple(stuple::STuple::pair(SGroupElement, SGroupElement))
}
TypeCode::TUPLE_PAIR_SYMMETRIC_SIGMAPROP => {
STuple(stuple::STuple::pair(SSigmaProp, SSigmaProp))
}
TypeCode::TUPLE => {
let len = r.get_u8()?;
let mut items = Vec::with_capacity(len as usize);
for _ in 0..len {
items.push(SType::sigma_parse(r)?);
}
SType::STuple(
items
.try_into()
.map_err(|_| SigmaParsingError::TupleItemsOutOfBounds(len as usize))?,
)
}
TypeCode::SANY => SAny,
TypeCode::SUNIT => SUnit,
TypeCode::SBOX => SBox,
TypeCode::SAVL_TREE => SAvlTree,
TypeCode::SCONTEXT => SContext,
TypeCode::STYPE_VAR => STypeVar(stype_param::STypeVar::sigma_parse(r)?),
TypeCode::SHEADER => SHeader,
TypeCode::SPRE_HEADER => SPreHeader,
TypeCode::SGLOBAL => SGlobal,
})
}
}
impl SigmaSerializable for SType {
fn sigma_serialize<W: SigmaByteWrite>(&self, w: &mut W) -> SigmaSerializeResult {
use SType::*;
match self {
SType::SFunc(_) => Err(SigmaSerializationError::NotSupported("SFunc")),
SType::SAny => TypeCode::SANY.sigma_serialize(w),
SType::SUnit => TypeCode::SUNIT.sigma_serialize(w),
SType::SBoolean => TypeCode::SBOOLEAN.sigma_serialize(w),
SType::SByte => TypeCode::SBYTE.sigma_serialize(w),
SType::SShort => TypeCode::SSHORT.sigma_serialize(w),
SType::SInt => TypeCode::SINT.sigma_serialize(w),
SType::SLong => TypeCode::SLONG.sigma_serialize(w),
SType::SBigInt => TypeCode::SBIGINT.sigma_serialize(w),
SType::SGroupElement => TypeCode::SGROUP_ELEMENT.sigma_serialize(w),
SType::SSigmaProp => TypeCode::SSIGMAPROP.sigma_serialize(w),
SType::SBox => TypeCode::SBOX.sigma_serialize(w),
SType::SAvlTree => TypeCode::SAVL_TREE.sigma_serialize(w),
SType::SContext => TypeCode::SCONTEXT.sigma_serialize(w),
SType::SHeader => TypeCode::SHEADER.sigma_serialize(w),
SType::SPreHeader => TypeCode::SPRE_HEADER.sigma_serialize(w),
SType::SGlobal => TypeCode::SGLOBAL.sigma_serialize(w),
SOption(elem_type) => match &**elem_type {
SBoolean => TypeCode::OPTION_BOOL.sigma_serialize(w),
SByte => TypeCode::OPTION_BYTE.sigma_serialize(w),
SShort => TypeCode::OPTION_SHORT.sigma_serialize(w),
SInt => TypeCode::OPTION_INT.sigma_serialize(w),
SLong => TypeCode::OPTION_LONG.sigma_serialize(w),
SBigInt => TypeCode::OPTION_BIGINT.sigma_serialize(w),
SGroupElement => TypeCode::OPTION_GROUP_ELEMENT.sigma_serialize(w),
SSigmaProp => TypeCode::OPTION_SIGMAPROP.sigma_serialize(w),
SColl(inner_elem_type) => match &**inner_elem_type {
SBoolean => TypeCode::OPTION_COLL_BOOL.sigma_serialize(w),
SByte => TypeCode::OPTION_COLL_BYTE.sigma_serialize(w),
SShort => TypeCode::OPTION_COLL_SHORT.sigma_serialize(w),
SInt => TypeCode::OPTION_COLL_INT.sigma_serialize(w),
SLong => TypeCode::OPTION_COLL_LONG.sigma_serialize(w),
SBigInt => TypeCode::OPTION_COLL_BIGINT.sigma_serialize(w),
SGroupElement => TypeCode::OPTION_COLL_GROUP_ELEMENT.sigma_serialize(w),
SSigmaProp => TypeCode::OPTION_COLL_SIGMAPROP.sigma_serialize(w),
STypeVar(_) | SAny | SUnit | SBox | SAvlTree | SOption(_) | SColl(_)
| STuple(_) | SFunc(_) | SContext | SHeader | SPreHeader | SGlobal => {
TypeCode::OPTION.sigma_serialize(w)?;
elem_type.sigma_serialize(w)
}
},
STypeVar(_) | SAny | SUnit | SBox | SAvlTree | SOption(_) | STuple(_)
| SFunc(_) | SContext | SHeader | SPreHeader | SGlobal => {
TypeCode::OPTION.sigma_serialize(w)?;
elem_type.sigma_serialize(w)
}
},
SType::SColl(elem_type) => match &**elem_type {
SBoolean => TypeCode::COLL_BOOL.sigma_serialize(w),
SByte => TypeCode::COLL_BYTE.sigma_serialize(w),
SShort => TypeCode::COLL_SHORT.sigma_serialize(w),
SInt => TypeCode::COLL_INT.sigma_serialize(w),
SLong => TypeCode::COLL_LONG.sigma_serialize(w),
SBigInt => TypeCode::COLL_BIGINT.sigma_serialize(w),
SGroupElement => TypeCode::COLL_GROUP_ELEMENT.sigma_serialize(w),
SSigmaProp => TypeCode::COLL_SIGMAPROP.sigma_serialize(w),
SColl(inner_elem_type) => match &**inner_elem_type {
SBoolean => TypeCode::NESTED_COLL_BOOL.sigma_serialize(w),
SByte => TypeCode::NESTED_COLL_BYTE.sigma_serialize(w),
SShort => TypeCode::NESTED_COLL_SHORT.sigma_serialize(w),
SInt => TypeCode::NESTED_COLL_INT.sigma_serialize(w),
SLong => TypeCode::NESTED_COLL_LONG.sigma_serialize(w),
SBigInt => TypeCode::NESTED_COLL_BIGINT.sigma_serialize(w),
SGroupElement => TypeCode::NESTED_COLL_GROUP_ELEMENT.sigma_serialize(w),
SSigmaProp => TypeCode::NESTED_COLL_SIGMAPROP.sigma_serialize(w),
STypeVar(_) | SAny | SUnit | SBox | SAvlTree | SOption(_) | SColl(_)
| STuple(_) | SFunc(_) | SContext | SHeader | SPreHeader | SGlobal => {
TypeCode::COLL.sigma_serialize(w)?;
elem_type.sigma_serialize(w)
}
},
STypeVar(_) | SAny | SUnit | SBox | SAvlTree | SOption(_) | STuple(_)
| SFunc(_) | SContext | SHeader | SPreHeader | SGlobal => {
TypeCode::COLL.sigma_serialize(w)?;
elem_type.sigma_serialize(w)
}
},
SType::STuple(stuple::STuple { items }) => match items.clone().as_slice() {
[t1, t2] => match (t1, t2) {
(SBoolean, SBoolean) => TypeCode::TUPLE_PAIR_SYMMETRIC_BOOL.sigma_serialize(w),
(SByte, SByte) => TypeCode::TUPLE_PAIR_SYMMETRIC_BYTE.sigma_serialize(w),
(SInt, SInt) => TypeCode::TUPLE_PAIR_SYMMETRIC_INT.sigma_serialize(w),
(SLong, SLong) => TypeCode::TUPLE_PAIR_SYMMETRIC_LONG.sigma_serialize(w),
(SBigInt, SBigInt) => TypeCode::TUPLE_PAIR_SYMMETRIC_BIGINT.sigma_serialize(w),
(SGroupElement, SGroupElement) => {
TypeCode::TUPLE_PAIR_SYMMETRIC_GROUP_ELEMENT.sigma_serialize(w)
}
(SSigmaProp, SSigmaProp) => {
TypeCode::TUPLE_PAIR_SYMMETRIC_SIGMAPROP.sigma_serialize(w)
}
(SBoolean, t2) => {
TypeCode::TUPLE_PAIR1_BOOL.sigma_serialize(w)?;
t2.sigma_serialize(w)
}
(SByte, t2) => {
TypeCode::TUPLE_PAIR1_BYTE.sigma_serialize(w)?;
t2.sigma_serialize(w)
}
(SShort, t2) => {
TypeCode::TUPLE_PAIR1_SHORT.sigma_serialize(w)?;
t2.sigma_serialize(w)
}
(SInt, t2) => {
TypeCode::TUPLE_PAIR1_INT.sigma_serialize(w)?;
t2.sigma_serialize(w)
}
(SLong, t2) => {
TypeCode::TUPLE_PAIR1_LONG.sigma_serialize(w)?;
t2.sigma_serialize(w)
}
(SBigInt, t2) => {
TypeCode::TUPLE_PAIR1_BIGINT.sigma_serialize(w)?;
t2.sigma_serialize(w)
}
(SGroupElement, t2) => {
TypeCode::TUPLE_PAIR1_GROUP_ELEMENT.sigma_serialize(w)?;
t2.sigma_serialize(w)
}
(SSigmaProp, t2) => {
TypeCode::TUPLE_PAIR1_SIGMAPROP.sigma_serialize(w)?;
t2.sigma_serialize(w)
}
(t1, SBoolean) => {
TypeCode::TUPLE_PAIR2_BOOL.sigma_serialize(w)?;
t1.sigma_serialize(w)
}
(t1, SByte) => {
TypeCode::TUPLE_PAIR2_BYTE.sigma_serialize(w)?;
t1.sigma_serialize(w)
}
(t1, SShort) => {
TypeCode::TUPLE_PAIR2_SHORT.sigma_serialize(w)?;
t1.sigma_serialize(w)
}
(t1, SInt) => {
TypeCode::TUPLE_PAIR2_INT.sigma_serialize(w)?;
t1.sigma_serialize(w)
}
(t1, SLong) => {
TypeCode::TUPLE_PAIR2_LONG.sigma_serialize(w)?;
t1.sigma_serialize(w)
}
(t1, SBigInt) => {
TypeCode::TUPLE_PAIR2_BIGINT.sigma_serialize(w)?;
t1.sigma_serialize(w)
}
(t1, SGroupElement) => {
TypeCode::TUPLE_PAIR2_GROUP_ELEMENT.sigma_serialize(w)?;
t1.sigma_serialize(w)
}
(t1, SSigmaProp) => {
TypeCode::TUPLE_PAIR2_SIGMAPROP.sigma_serialize(w)?;
t1.sigma_serialize(w)
}
(
STypeVar(_) | SAny | SUnit | SBox | SAvlTree | SOption(_) | SColl(_)
| STuple(_) | SFunc(_) | SContext | SHeader | SPreHeader | SGlobal,
STypeVar(_) | SAny | SUnit | SBox | SAvlTree | SOption(_) | SColl(_)
| STuple(_) | SFunc(_) | SContext | SHeader | SPreHeader | SGlobal,
) => {
TypeCode::TUPLE_PAIR1.sigma_serialize(w)?;
t1.sigma_serialize(w)?;
t2.sigma_serialize(w)
}
},
[t1, t2, t3] => {
TypeCode::TUPLE_TRIPLE.sigma_serialize(w)?;
t1.sigma_serialize(w)?;
t2.sigma_serialize(w)?;
t3.sigma_serialize(w)
}
[t1, t2, t3, t4] => {
TypeCode::TUPLE_QUADRUPLE.sigma_serialize(w)?;
t1.sigma_serialize(w)?;
t2.sigma_serialize(w)?;
t3.sigma_serialize(w)?;
t4.sigma_serialize(w)
}
_ => {
TypeCode::TUPLE.sigma_serialize(w)?;
w.put_u8(items.len() as u8)?;
items.iter().try_for_each(|i| i.sigma_serialize(w))
}
},
SType::STypeVar(tv) => {
TypeCode::STYPE_VAR.sigma_serialize(w)?;
tv.sigma_serialize(w)
}
}
}
fn sigma_parse<R: SigmaByteRead>(r: &mut R) -> Result<Self, SigmaParsingError> {
let c = TypeCode::sigma_parse(r)?;
Self::parse_with_type_code(r, c)
}
}
#[cfg(test)]
#[cfg(feature = "arbitrary")]
#[allow(clippy::panic)]
mod tests {
use super::*;
use crate::serialization::sigma_serialize_roundtrip;
use proptest::prelude::*;
proptest! {
#[test]
fn ser_roundtrip(v in any::<SType>()) {
prop_assert_eq![sigma_serialize_roundtrip(&v), v];
}
}
}