1use std::io;
3
4use bdk::bitcoin::{
5 secp256k1::ecdsa::{RecoverableSignature, RecoveryId},
6 Amount, Script,
7};
8use thiserror::Error;
9
10use crate::StacksResult;
11
12#[derive(Error, Debug)]
13pub enum CodecError {
15 #[error("Could not serialize or deserialize: {0}")]
16 IoError(#[from] io::Error),
18}
19
20pub type CodecResult<T> = Result<T, CodecError>;
22
23pub trait Codec {
25 fn codec_serialize<W: io::Write>(&self, dest: &mut W) -> io::Result<()>;
27 fn codec_deserialize<R: io::Read>(data: &mut R) -> io::Result<Self>
29 where
30 Self: Sized;
31
32 fn serialize<W: io::Write>(&self, dest: &mut W) -> StacksResult<()> {
34 self.codec_serialize(dest)
35 .map_err(|err| CodecError::IoError(err).into())
36 }
37
38 fn deserialize<R: io::Read>(data: &mut R) -> StacksResult<Self>
40 where
41 Self: Sized,
42 {
43 Self::codec_deserialize(data)
44 .map_err(|err| CodecError::IoError(err).into())
45 }
46
47 fn serialize_to_vec(&self) -> Vec<u8> {
49 let mut buffer = vec![];
50
51 self.serialize(&mut buffer).unwrap();
52
53 buffer
54 }
55}
56
57impl Codec for Amount {
58 fn codec_serialize<W: io::Write>(&self, dest: &mut W) -> io::Result<()> {
59 dest.write_all(&self.to_sat().to_be_bytes())
60 }
61
62 fn codec_deserialize<R: io::Read>(data: &mut R) -> io::Result<Self>
63 where
64 Self: Sized,
65 {
66 let mut buffer = [0; 8];
67 data.read_exact(&mut buffer)?;
68
69 Ok(Self::from_sat(u64::from_be_bytes(buffer)))
70 }
71}
72
73impl Codec for RecoverableSignature {
74 fn codec_serialize<W: io::Write>(&self, dest: &mut W) -> io::Result<()> {
75 let (id, signature) = self.serialize_compact();
76
77 let id: u8 = id.to_i32().try_into().unwrap();
78
79 dest.write_all(&[id])?;
80 dest.write_all(&signature)
81 }
82
83 fn codec_deserialize<R: io::Read>(data: &mut R) -> io::Result<Self>
84 where
85 Self: Sized,
86 {
87 let mut id_buffer = [0; 1];
88 data.read_exact(&mut id_buffer)?;
89
90 let id = RecoveryId::from_i32(id_buffer[0] as i32)
91 .map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))?;
92
93 let mut signature_buffer = [0; 64];
94 data.read_exact(&mut signature_buffer)?;
95
96 Self::from_compact(&signature_buffer, id)
97 .map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))
98 }
99}
100
101impl Codec for u64 {
102 fn codec_serialize<W: io::Write>(&self, dest: &mut W) -> io::Result<()> {
103 dest.write_all(&self.to_be_bytes())
104 }
105
106 fn codec_deserialize<R: io::Read>(data: &mut R) -> io::Result<Self>
107 where
108 Self: Sized,
109 {
110 let mut bytes = [0; 8];
111 data.read_exact(&mut bytes)?;
112
113 Ok(Self::from_be_bytes(bytes))
114 }
115}
116
117impl Codec for Script {
118 fn codec_serialize<W: io::Write>(&self, dest: &mut W) -> io::Result<()> {
119 dest.write_all(self.as_bytes())
120 }
121
122 fn codec_deserialize<R: io::Read>(data: &mut R) -> io::Result<Self>
123 where
124 Self: Sized,
125 {
126 let mut buffer = vec![];
127 data.read_to_end(&mut buffer)?;
128
129 Ok(Self::from(buffer))
130 }
131}