use std::io;
use crate::id::CommitmentId;
use crate::Conceal;
pub trait CommitEncode {
fn commit_encode(&self, e: &mut impl io::Write);
}
#[macro_export]
macro_rules! commit_encode_list {
( $encoder:ident; $($item:expr),+ ) => {
{
let mut len = 0usize;
$(
len += $item.commit_encode(&mut $encoder);
)+CommitId
len
}
}
}
pub trait CommitStrategy {
type Strategy;
}
pub mod strategies {
use amplify::confinement::Confined;
use amplify::num::apfloat::ieee;
use amplify::num::{i1024, i256, i512, u1024, u24, u256, u512};
use amplify::{Bytes32, Holder, Wrapper};
use strict_encoding::{StrictEncode, StrictWriter};
use super::*;
use crate::merkle::{MerkleLeaves, MerkleNode};
#[doc(hidden)]
pub enum AsRef {}
pub enum IntoU8 {}
pub enum IntoInner {}
pub enum Strict {}
pub enum ConcealStrict {}
pub enum Id {}
pub enum Merklize<const MERKLE_ROOT_TAG: u128> {}
impl<'a, T> CommitEncode for Holder<&'a T, IntoU8>
where T: Copy + Into<u8>
{
fn commit_encode(&self, e: &mut impl io::Write) {
let raw = **self.as_type();
e.write_all(&[raw.into()]).ok();
}
}
impl<'a, T> CommitEncode for Holder<&'a T, AsRef>
where T: CommitEncode
{
fn commit_encode(&self, e: &mut impl io::Write) { self.as_type().commit_encode(e); }
}
impl<'a, T> CommitEncode for Holder<&'a T, IntoInner>
where
T: Wrapper,
T::Inner: CommitEncode,
{
fn commit_encode(&self, e: &mut impl io::Write) {
self.as_type().as_inner().commit_encode(e);
}
}
impl<'a, T> CommitEncode for Holder<&'a T, Strict>
where T: StrictEncode
{
fn commit_encode(&self, e: &mut impl io::Write) {
let w = StrictWriter::with(u32::MAX as usize, e);
self.as_type().strict_encode(w).ok();
}
}
impl<'a, T> CommitEncode for Holder<&'a T, ConcealStrict>
where
T: Conceal,
T::Concealed: StrictEncode,
{
fn commit_encode(&self, e: &mut impl io::Write) {
let w = StrictWriter::with(u32::MAX as usize, e);
self.as_type().conceal().strict_encode(w).ok();
}
}
impl<'a, T> CommitEncode for Holder<&'a T, Id>
where
T: CommitmentId,
T::Id: Into<[u8; 32]>,
{
fn commit_encode(&self, e: &mut impl io::Write) {
e.write_all(&self.as_type().commitment_id().into()).ok();
}
}
impl<'a, T, const MERKLE_ROOT_TAG: u128> CommitEncode for Holder<&'a T, Merklize<MERKLE_ROOT_TAG>>
where T: MerkleLeaves
{
fn commit_encode(&self, e: &mut impl io::Write) {
MerkleNode::merklize(MERKLE_ROOT_TAG.to_be_bytes(), *self.as_type()).commit_encode(e);
}
}
impl<T> CommitEncode for T
where
T: CommitStrategy,
for<'a> Holder<&'a T, T::Strategy>: CommitEncode,
{
fn commit_encode(&self, e: &mut impl io::Write) { Holder::new(self).commit_encode(e) }
}
impl CommitStrategy for u8 {
type Strategy = Strict;
}
impl CommitStrategy for u16 {
type Strategy = Strict;
}
impl CommitStrategy for u24 {
type Strategy = Strict;
}
impl CommitStrategy for u32 {
type Strategy = Strict;
}
impl CommitStrategy for u64 {
type Strategy = Strict;
}
impl CommitStrategy for u128 {
type Strategy = Strict;
}
impl CommitStrategy for u256 {
type Strategy = Strict;
}
impl CommitStrategy for u512 {
type Strategy = Strict;
}
impl CommitStrategy for u1024 {
type Strategy = Strict;
}
impl CommitStrategy for i8 {
type Strategy = Strict;
}
impl CommitStrategy for i16 {
type Strategy = Strict;
}
impl CommitStrategy for i32 {
type Strategy = Strict;
}
impl CommitStrategy for i64 {
type Strategy = Strict;
}
impl CommitStrategy for i128 {
type Strategy = Strict;
}
impl CommitStrategy for i256 {
type Strategy = Strict;
}
impl CommitStrategy for i512 {
type Strategy = Strict;
}
impl CommitStrategy for i1024 {
type Strategy = Strict;
}
impl CommitStrategy for ieee::Half {
type Strategy = Strict;
}
impl CommitStrategy for ieee::Single {
type Strategy = Strict;
}
impl CommitStrategy for ieee::Double {
type Strategy = Strict;
}
impl CommitStrategy for ieee::X87DoubleExtended {
type Strategy = Strict;
}
impl CommitStrategy for ieee::Quad {
type Strategy = Strict;
}
impl CommitStrategy for ieee::Oct {
type Strategy = Strict;
}
impl CommitStrategy for Bytes32 {
type Strategy = IntoInner;
}
impl<T> CommitStrategy for Box<T>
where T: CommitStrategy
{
type Strategy = T::Strategy;
}
impl<T> CommitStrategy for Option<T>
where T: CommitStrategy
{
type Strategy = T::Strategy;
}
impl<const MIN: usize, const MAX: usize> CommitStrategy for Confined<Vec<u8>, MIN, MAX> {
type Strategy = Strict;
}
impl<T> CommitStrategy for &T
where T: CommitEncode
{
type Strategy = AsRef;
}
}
impl CommitEncode for [u8; 32] {
fn commit_encode(&self, e: &mut impl io::Write) { e.write_all(self).ok(); }
}