use super::protocol::*;
use pallas_codec::minicbor::{decode, encode, Decode, Encode, Encoder};
impl Encode<()> for Message {
fn encode<W: encode::Write>(
&self,
e: &mut Encoder<W>,
_ctx: &mut (),
) -> Result<(), encode::Error<W::Error>> {
match self {
Message::Done => {
e.array(1)?.u16(0)?;
}
Message::Acquire => {
e.array(1)?.u16(1)?;
}
Message::Acquired(slot) => {
e.array(2)?.u16(2)?;
e.encode(slot)?;
}
Message::Release => {
e.array(1)?.u16(3)?;
}
// TODO: confirm if this is valid, I'm just assuming that label 4 is AwaitAcquire, can't
// find the specs
Message::AwaitAcquire => {
e.array(1)?.u16(4)?;
}
Message::RequestNextTx => {
e.array(1)?.u16(5)?;
}
Message::ResponseNextTx(None) => {
e.array(1)?.u16(6)?;
}
Message::ResponseNextTx(Some(tx)) => {
e.array(2)?.u16(6)?;
e.encode(tx)?;
}
Message::RequestHasTx(tx) => {
e.array(2)?.u16(7)?;
e.encode(tx)?;
}
Message::ResponseHasTx(tx) => {
e.array(2)?.u16(8)?;
e.encode(tx)?;
}
Message::RequestSizeAndCapacity => {
e.array(1)?.u16(9)?;
}
Message::ResponseSizeAndCapacity(sz) => {
e.array(2)?.u16(10)?;
e.array(3)?;
e.encode(sz.capacity_in_bytes)?;
e.encode(sz.size_in_bytes)?;
e.encode(sz.number_of_txs)?;
}
}
Ok(())
}
}
impl<'b> Decode<'b, ()> for Message {
fn decode(
d: &mut pallas_codec::minicbor::Decoder<'b>,
_ctx: &mut (),
) -> Result<Self, decode::Error> {
d.array()?;
let label = d.u16()?;
match label {
0 => Ok(Message::Done),
1 => Ok(Message::Acquire),
2 => {
let slot = d.decode()?;
Ok(Message::Acquired(slot))
}
3 => Ok(Message::Release),
// TODO: confirm if this is valid, I'm just assuming that label 4 is AwaitAcquire, can't
// find the specs
4 => Ok(Message::AwaitAcquire),
5 => Ok(Message::RequestNextTx),
6 => match d.datatype() {
Ok(datatype) => match datatype {
pallas_codec::minicbor::data::Type::Array
| pallas_codec::minicbor::data::Type::ArrayIndef => {
let tx = d.decode()?;
Ok(Message::ResponseNextTx(Some(tx)))
}
_ => Ok(Message::ResponseNextTx(None)),
},
Err(_) => Ok(Message::ResponseNextTx(None)),
},
7 => {
let id = d.decode()?;
Ok(Message::RequestHasTx(id))
}
8 => {
let has = d.decode()?;
Ok(Message::ResponseHasTx(has))
}
9 => Ok(Message::RequestSizeAndCapacity),
10 => {
d.array()?;
let capacity_in_bytes = d.decode()?;
let size_in_bytes = d.decode()?;
let number_of_txs = d.decode()?;
Ok(Message::ResponseSizeAndCapacity(MempoolSizeAndCapacity {
capacity_in_bytes,
size_in_bytes,
number_of_txs,
}))
}
_ => Err(decode::Error::message("can't decode Message")),
}
}
}
#[cfg(test)]
pub mod tests {
const EXAMPLE_RESPONSE_NEXT_TX_WITH_DATA: &str = "82068205d81859013184a5008282582003e4aea27ebacf5f50b10ac60cc84deba96569ce8a47fdf9199998d1fd16ec0601825820eebf8249544b7eefa7839510dfd58a7ed420f2254bd3bf632baea8cd0928b00102018182583901b98f57f569aba4cffc4d9c791f099374e9403ed5e2cb614eab25b78278b1312c2c271d260db425b8b9847ab142b395b4598d3c0b383aa696821a00924172a1581c09f2d4e4a5c3662f4c1e6a7d9600e9605279dbdcedb22d4507cb6e75a1435350461a0422bb35021a00029f3d031a063ec6470800a100818258208293ac2260e28a07657f77087d1d7ff5e3ced29ff4385abf60a9546e2bcbc04a5840d69ce3a8f9713513a9baf473c1be08fd17d1a85df2881dc107fb1f68ce02c8e7adcf1c91bce7fb58868908f7ac47310a8e97d95780beadcfd8493bebbb914d0df5f6";
#[test]
fn test_next_tx_response() {
let bytes = hex::decode(EXAMPLE_RESPONSE_NEXT_TX_WITH_DATA).unwrap();
let msg: super::Message = pallas_codec::minicbor::decode(&bytes).unwrap();
if let super::Message::ResponseNextTx(Some((era, body))) = msg {
assert_eq!(era, 5);
assert_eq!(body.len(), 305);
} else {
unreachable!();
}
}
#[test]
fn test_empty_next_tx_response() {
let bytes = vec![129, 6];
let msg: super::Message = pallas_codec::minicbor::decode(&bytes).unwrap();
if let super::Message::ResponseNextTx(None) = msg {
assert_eq!(0u64, 0u64);
} else {
unreachable!();
}
}
}