use failure::prelude::*;
use std::collections::BTreeMap;
pub trait CanonicalSerialize {
fn serialize(&self, serializer: &mut impl CanonicalSerializer) -> Result<()>;
}
pub trait CanonicalSerializer {
fn encode_bool(&mut self, v: bool) -> Result<&mut Self>;
fn encode_bytes(&mut self, v: &[u8]) -> Result<&mut Self>;
fn encode_i8(&mut self, v: i8) -> Result<&mut Self>;
fn encode_i16(&mut self, v: i16) -> Result<&mut Self>;
fn encode_i32(&mut self, v: i32) -> Result<&mut Self>;
fn encode_i64(&mut self, v: i64) -> Result<&mut Self>;
fn encode_string(&mut self, v: &str) -> Result<&mut Self>;
fn encode_u8(&mut self, v: u8) -> Result<&mut Self>;
fn encode_u16(&mut self, v: u16) -> Result<&mut Self>;
fn encode_u32(&mut self, v: u32) -> Result<&mut Self>;
fn encode_u64(&mut self, v: u64) -> Result<&mut Self>;
fn encode_tuple2<T0, T1>(&mut self, v: &(T0, T1)) -> Result<&mut Self>
where
Self: Sized,
T0: CanonicalSerialize,
T1: CanonicalSerialize,
{
v.0.serialize(self)?;
v.1.serialize(self)?;
Ok(self)
}
fn encode_tuple3<T0, T1, T2>(&mut self, v: &(T0, T1, T2)) -> Result<&mut Self>
where
Self: Sized,
T0: CanonicalSerialize,
T1: CanonicalSerialize,
T2: CanonicalSerialize,
{
v.0.serialize(self)?;
v.1.serialize(self)?;
v.2.serialize(self)?;
Ok(self)
}
fn encode_btreemap<K: CanonicalSerialize, V: CanonicalSerialize>(
&mut self,
v: &BTreeMap<K, V>,
) -> Result<&mut Self> {
self.encode_tuple_iterator(v.iter())
}
fn encode_tuple_iterator<K: CanonicalSerialize, V: CanonicalSerialize, I>(
&mut self,
iter: I,
) -> Result<&mut Self>
where
I: Iterator<Item = (K, V)>;
fn encode_optional<T: CanonicalSerialize>(&mut self, v: &Option<T>) -> Result<&mut Self>;
fn encode_struct(&mut self, structure: &impl CanonicalSerialize) -> Result<&mut Self>
where
Self: std::marker::Sized,
{
structure.serialize(self)?;
Ok(self)
}
fn encode_vec<T: CanonicalSerialize>(&mut self, v: &[T]) -> Result<&mut Self>;
}
macro_rules! impl_canonical_serialize_for_complex {
($function:ident, $type:ty) => {
impl CanonicalSerialize for $type {
fn serialize(&self, serializer: &mut impl CanonicalSerializer) -> Result<()> {
serializer.$function(self)?;
Ok(())
}
}
};
}
macro_rules! impl_canonical_serialize_for_primitive {
($function:ident, $type:ty) => {
impl CanonicalSerialize for $type {
fn serialize(&self, serializer: &mut impl CanonicalSerializer) -> Result<()> {
serializer.$function(*self)?;
Ok(())
}
}
};
}
macro_rules! impl_canonical_serialize_for_tuple {
($function:ident,$($type:ident)+) => (
impl<$($type), +> CanonicalSerialize for ($($type),+)
where
$($type: CanonicalSerialize,) +
{
fn serialize(&self, serializer: &mut impl CanonicalSerializer) -> Result<()> {
serializer.$function(self)?;
Ok(())
}
}
);
}
impl_canonical_serialize_for_primitive!(encode_bool, bool);
impl_canonical_serialize_for_complex!(encode_btreemap, BTreeMap<Vec<u8>, Vec<u8>>);
impl_canonical_serialize_for_primitive!(encode_i8, i8);
impl_canonical_serialize_for_primitive!(encode_i16, i16);
impl_canonical_serialize_for_primitive!(encode_i32, i32);
impl_canonical_serialize_for_primitive!(encode_i64, i64);
impl_canonical_serialize_for_complex!(encode_string, &str);
impl_canonical_serialize_for_tuple!(encode_tuple2, T0 T1);
impl_canonical_serialize_for_tuple!(encode_tuple3, T0 T1 T2);
impl_canonical_serialize_for_primitive!(encode_u8, u8);
impl_canonical_serialize_for_primitive!(encode_u16, u16);
impl_canonical_serialize_for_primitive!(encode_u32, u32);
impl_canonical_serialize_for_primitive!(encode_u64, u64);
impl<T> CanonicalSerialize for &T
where
T: CanonicalSerialize,
{
fn serialize(&self, serializer: &mut impl CanonicalSerializer) -> Result<()> {
serializer.encode_struct(*self)?;
Ok(())
}
}
impl<T> CanonicalSerialize for Option<T>
where
T: CanonicalSerialize,
{
fn serialize(&self, serializer: &mut impl CanonicalSerializer) -> Result<()> {
serializer.encode_optional(self)?;
Ok(())
}
}
impl CanonicalSerialize for String {
fn serialize(&self, serializer: &mut impl CanonicalSerializer) -> Result<()> {
serializer.encode_string(self.as_str())?;
Ok(())
}
}
impl CanonicalSerialize for usize {
fn serialize(&self, serializer: &mut impl CanonicalSerializer) -> Result<()> {
ensure!(
*self <= u64::max_value() as usize,
"usize bigger than max allowed. Expected <= {}, found: {}",
u64::max_value(),
*self,
);
serializer.encode_u64(*self as u64)?;
Ok(())
}
}
impl<T> CanonicalSerialize for Vec<T>
where
T: CanonicalSerialize,
{
fn serialize(&self, serializer: &mut impl CanonicalSerializer) -> Result<()> {
serializer.encode_vec(self.as_ref())?;
Ok(())
}
}