use crate::rpc::methods::*;
use crate::rpc::{
codec::base::OutboundCodec,
protocol::{ProtocolId, RPCError},
};
use crate::rpc::{ErrorMessage, RPCErrorResponse, RPCRequest, RPCResponse};
use bytes::{Bytes, BytesMut};
use ssz::{Decode, Encode};
use tokio::codec::{Decoder, Encoder};
use unsigned_varint::codec::UviBytes;
/* Inbound Codec */
pub struct SSZInboundCodec {
inner: UviBytes,
protocol: ProtocolId,
}
impl SSZInboundCodec {
pub fn new(protocol: ProtocolId, max_packet_size: usize) -> Self {
let mut uvi_codec = UviBytes::default();
uvi_codec.set_max_len(max_packet_size);
// this encoding only applies to ssz.
debug_assert!(protocol.encoding.as_str() == "ssz");
SSZInboundCodec {
inner: uvi_codec,
protocol,
}
}
}
// Encoder for inbound
impl Encoder for SSZInboundCodec {
type Item = RPCErrorResponse;
type Error = RPCError;
fn encode(&mut self, item: Self::Item, dst: &mut BytesMut) -> Result<(), Self::Error> {
let bytes = match item {
RPCErrorResponse::Success(resp) => {
match resp {
RPCResponse::Hello(res) => res.as_ssz_bytes(),
RPCResponse::BeaconBlocks(res) => res, // already raw bytes
RPCResponse::RecentBeaconBlocks(res) => res, // already raw bytes
}
}
RPCErrorResponse::InvalidRequest(err) => err.as_ssz_bytes(),
RPCErrorResponse::ServerError(err) => err.as_ssz_bytes(),
RPCErrorResponse::Unknown(err) => err.as_ssz_bytes(),
};
if !bytes.is_empty() {
// length-prefix and return
return self
.inner
.encode(Bytes::from(bytes), dst)
.map_err(RPCError::from);
}
Ok(())
}
}
// Decoder for inbound
impl Decoder for SSZInboundCodec {
type Item = RPCRequest;
type Error = RPCError;
fn decode(&mut self, src: &mut BytesMut) -> Result