use crate::{
codec::GetSize,
datatypes::{
ShortTxId, Signature, Sv2DataType, U32AsRef, B016M, B0255, B032, B064K, U24, U256,
},
Error,
};
use alloc::vec::Vec;
#[cfg(not(feature = "no_std"))]
use std::io::{Error as E, Write};
pub trait Encodable {
#[allow(clippy::wrong_self_convention)]
fn to_bytes(self, dst: &mut [u8]) -> Result<usize, Error>;
#[cfg(not(feature = "no_std"))]
#[allow(clippy::wrong_self_convention)]
fn to_writer(self, dst: &mut impl Write) -> Result<(), E>;
}
impl<'a, T: Into<EncodableField<'a>>> Encodable for T {
#[allow(clippy::wrong_self_convention)]
fn to_bytes(self, dst: &mut [u8]) -> Result<usize, Error> {
let encoded_field = self.into();
encoded_field.encode(dst, 0)
}
#[cfg(not(feature = "no_std"))]
#[allow(clippy::wrong_self_convention, unconditional_recursion)]
fn to_writer(self, dst: &mut impl Write) -> Result<(), E> {
let encoded_field = self.into();
encoded_field.to_writer(dst)
}
}
#[derive(Debug)]
pub enum EncodablePrimitive<'a> {
U8(u8),
OwnedU8(u8),
U16(u16),
Bool(bool),
U24(U24),
U256(U256<'a>),
ShortTxId(ShortTxId<'a>),
Signature(Signature<'a>),
U32(u32),
U32AsRef(U32AsRef<'a>),
F32(f32),
U64(u64),
B032(B032<'a>),
B0255(B0255<'a>),
B064K(B064K<'a>),
B016M(B016M<'a>),
}
impl<'a> EncodablePrimitive<'a> {
fn encode(&self, dst: &mut [u8]) -> Result<usize, Error> {
match self {
Self::U8(v) => v.to_slice(dst),
Self::OwnedU8(v) => v.to_slice(dst),
Self::U16(v) => v.to_slice(dst),
Self::Bool(v) => v.to_slice(dst),
Self::U24(v) => v.to_slice(dst),
Self::U256(v) => v.to_slice(dst),
Self::ShortTxId(v) => v.to_slice(dst),
Self::Signature(v) => v.to_slice(dst),
Self::U32(v) => v.to_slice(dst),
Self::U32AsRef(v) => v.to_slice(dst),
Self::F32(v) => v.to_slice(dst),
Self::U64(v) => v.to_slice(dst),
Self::B032(v) => v.to_slice(dst),
Self::B0255(v) => v.to_slice(dst),
Self::B064K(v) => v.to_slice(dst),
Self::B016M(v) => v.to_slice(dst),
}
}
#[cfg(not(feature = "no_std"))]
pub fn write(&self, writer: &mut impl Write) -> Result<(), E> {
match self {
Self::U8(v) => v.to_writer_(writer),
Self::OwnedU8(v) => v.to_writer_(writer),
Self::U16(v) => v.to_writer_(writer),
Self::Bool(v) => v.to_writer_(writer),
Self::U24(v) => v.to_writer_(writer),
Self::U256(v) => v.to_writer_(writer),
Self::ShortTxId(v) => v.to_writer_(writer),
Self::Signature(v) => v.to_writer_(writer),
Self::U32(v) => v.to_writer_(writer),
Self::U32AsRef(v) => v.to_writer_(writer),
Self::F32(v) => v.to_writer_(writer),
Self::U64(v) => v.to_writer_(writer),
Self::B032(v) => v.to_writer_(writer),
Self::B0255(v) => v.to_writer_(writer),
Self::B064K(v) => v.to_writer_(writer),
Self::B016M(v) => v.to_writer_(writer),
}
}
}
impl<'a> GetSize for EncodablePrimitive<'a> {
fn get_size(&self) -> usize {
match self {
Self::U8(v) => v.get_size(),
Self::OwnedU8(v) => v.get_size(),
Self::U16(v) => v.get_size(),
Self::Bool(v) => v.get_size(),
Self::U24(v) => v.get_size(),
Self::U256(v) => v.get_size(),
Self::ShortTxId(v) => v.get_size(),
Self::Signature(v) => v.get_size(),
Self::U32(v) => v.get_size(),
Self::U32AsRef(v) => v.get_size(),
Self::F32(v) => v.get_size(),
Self::U64(v) => v.get_size(),
Self::B032(v) => v.get_size(),
Self::B0255(v) => v.get_size(),
Self::B064K(v) => v.get_size(),
Self::B016M(v) => v.get_size(),
}
}
}
#[derive(Debug)]
pub enum EncodableField<'a> {
Primitive(EncodablePrimitive<'a>),
Struct(Vec<EncodableField<'a>>),
}
impl<'a> EncodableField<'a> {
pub fn encode(&self, dst: &mut [u8], mut offset: usize) -> Result<usize, Error> {
match (self, dst.len() >= offset) {
(Self::Primitive(p), true) => p.encode(&mut dst[offset..]),
(Self::Struct(ps), true) => {
let mut result = 0;
for p in ps {
let encoded_bytes = p.encode(dst, offset)?;
offset += encoded_bytes;
result += encoded_bytes;
}
Ok(result)
}
(_, false) => Err(Error::WriteError(offset, dst.len())),
}
}
#[cfg(not(feature = "no_std"))]
pub fn to_writer(&self, writer: &mut impl Write) -> Result<(), E> {
match self {
Self::Primitive(p) => p.write(writer),
Self::Struct(ps) => {
for p in ps {
p.to_writer(writer)?;
}
Ok(())
}
}
}
}
impl<'a> GetSize for EncodableField<'a> {
fn get_size(&self) -> usize {
match self {
Self::Primitive(p) => p.get_size(),
Self::Struct(ps) => {
let mut size = 0;
for p in ps {
size += p.get_size();
}
size
}
}
}
}