use std::io;
use strict_encoding::{self, StrictDecode, StrictEncode};
use crate::{BigSize, Error, LightningDecode, LightningEncode};
pub struct AsStrict;
pub struct AsBigSize;
pub struct AsBitcoinHash;
pub struct AsWrapped;
pub trait Strategy {
type Strategy;
}
impl<T> LightningEncode for T
where
T: Strategy + Clone,
amplify::Holder<T, <T as Strategy>::Strategy>: LightningEncode,
{
#[inline]
fn lightning_encode<E: io::Write>(&self, e: E) -> Result<usize, Error> {
amplify::Holder::new(self.clone()).lightning_encode(e)
}
}
impl<T> LightningDecode for T
where
T: Strategy,
amplify::Holder<T, <T as Strategy>::Strategy>: LightningDecode,
{
#[inline]
fn lightning_decode<D: io::Read>(d: D) -> Result<Self, Error> {
Ok(amplify::Holder::lightning_decode(d)?.into_inner())
}
}
impl<T> LightningEncode for amplify::Holder<T, AsStrict>
where
T: StrictEncode,
{
#[inline]
fn lightning_encode<E: io::Write>(&self, e: E) -> Result<usize, Error> {
self.as_inner().strict_encode(e).map_err(Error::from)
}
}
impl<T> LightningDecode for amplify::Holder<T, AsStrict>
where
T: StrictDecode,
{
#[inline]
fn lightning_decode<D: io::Read>(d: D) -> Result<Self, Error> {
Ok(Self::new(T::strict_decode(d)?))
}
}
impl<T> LightningEncode for amplify::Holder<T, AsBitcoinHash>
where
T: bitcoin::hashes::Hash + strict_encoding::StrictEncode,
{
#[inline]
fn lightning_encode<E: io::Write>(&self, e: E) -> Result<usize, Error> {
self.as_inner().strict_encode(e).map_err(Error::from)
}
}
impl<T> LightningDecode for amplify::Holder<T, AsBitcoinHash>
where
T: bitcoin::hashes::Hash + strict_encoding::StrictDecode,
{
#[inline]
fn lightning_decode<D: io::Read>(d: D) -> Result<Self, Error> {
Ok(Self::new(T::strict_decode(d).map_err(|err| {
Error::DataIntegrityError(err.to_string())
})?))
}
}
impl<T> LightningEncode for amplify::Holder<T, AsWrapped>
where
T: amplify::Wrapper,
T::Inner: LightningEncode,
{
#[inline]
fn lightning_encode<E: io::Write>(&self, e: E) -> Result<usize, Error> {
self.as_inner().as_inner().lightning_encode(e)
}
}
impl<T> LightningDecode for amplify::Holder<T, AsWrapped>
where
T: amplify::Wrapper,
T::Inner: LightningDecode,
{
#[inline]
fn lightning_decode<D: io::Read>(d: D) -> Result<Self, Error> {
Ok(Self::new(T::from_inner(T::Inner::lightning_decode(d)?)))
}
}
impl<T> LightningDecode for amplify::Holder<T, AsBigSize>
where
T: From<BigSize>,
{
#[inline]
fn lightning_decode<D: io::Read>(d: D) -> Result<Self, Error> {
Ok(Self::new(T::from(BigSize::lightning_decode(d)?)))
}
}
impl<T> LightningEncode for amplify::Holder<T, AsBigSize>
where
T: Into<BigSize>,
T: Copy,
{
#[inline]
fn lightning_encode<E: io::Write>(&self, e: E) -> Result<usize, Error> {
(*self.as_inner()).into().lightning_encode(e)
}
}
impl From<strict_encoding::Error> for Error {
#[inline]
fn from(err: strict_encoding::Error) -> Self {
match err {
strict_encoding::Error::Io(io_err) => Error::Io(io_err),
strict_encoding::Error::DataNotEntirelyConsumed => {
Error::DataNotEntirelyConsumed
}
strict_encoding::Error::DataIntegrityError(msg) => {
Error::DataIntegrityError(msg)
}
strict_encoding::Error::EnumValueNotKnown(s, v) => {
Error::EnumValueNotKnown(s, v)
}
other => Error::DataIntegrityError(other.to_string()),
}
}
}