///! This handles the various supported encoding mechanism for the Eth 2.0 RPC. pub trait InnerCodec: Encoder + Decoder { type Error; fn decode_error( &mut self, &mut BytesMut, ) -> Result, ::Error>; } pub struct BaseInboundCodec { /// Inner codec for handling various encodings inner: TCodec, } pub struct BaseOutboundCodec where TCodec: InnerCodec, ::Item = RPCResponse, ::ErrorItem = ErrorMessage, { /// Inner codec for handling various encodings inner: TCodec, /// Optimisation for decoding. True if the response code has been read and we are awaiting a /// response. response_code: Option, } impl Encoder for BaseInboundCodec where TCodec: Encoder, ::Item = RPCResponse, { type Item = RPCResponse; type Error = ::Error; fn encode(&mut self, item: Self::Item, dst: &mut BytesMut) -> Result<(), Self::Error> { dst.clear(); dst.reserve(1); dst.put_u8(item.as_u8); return self.inner.encode(); } } impl Decoder for BaseInboundCodec where TCodec: Decoder, ::Item: RPCrequest, ::Error: From, { type Item = RPCRequest; type Error = ::Error; fn decode(&mut self, src: &mut BytesMut) -> Result, Self::Error> { self.inner.decode(src) } } impl Encoder for BaseOutboundCodec where TCodec: Encoder, { type Item = RPCRequest; type Error = ::Error; fn encode(&mut self, item: Self::Item, dst: &mut BytesMut) -> Result<(), Self::Error> { self.inner.encode(item, dst) } } impl Decoder for BaseOutboundCodec where TCodec: InnerCodec, ::Error: From, { type Item = RPCResponse; type Error = ::Error; fn decode(&mut self, src: &mut BytesMut) -> Result, Self::Error> { let response_code = { if let Some(resp_code) = self.response_code { resp_code; } else { if src.is_empty() { return Err(io::Error::new( io::ErrorKind::InvalidData, "no bytes received", )); } let resp_byte = src.split_to(1); let resp_code_byte = [0; 1]; resp_code_byte.copy_from_slice(&resp_byte); let resp_code = u8::from_be_bytes(resp_code_byte); if let Some(response) = RPCErrorResponse::internal_data(resp_code) { self.response_code = None; return response; } resp_code } }; if RPCErrorResponse::is_response(response_code) { // decode an actual response return self .inner .decode(src) .map(|r| r.map(|resp| RPCErrorResponse::Success(resp))); } else { // decode an error return self .inner .decode_error(src) .map(|r| r.map(|resp| RPCErrorResponse::from_error(response_code, resp))); } } }