more on encoding

This commit is contained in:
mbecker20
2025-10-11 14:11:07 -07:00
parent 1dc861f538
commit 80fb1e6889
10 changed files with 418 additions and 287 deletions

View File

@@ -135,7 +135,7 @@ impl PeripheryClient {
.await?;
// Still in progress, sent to avoid timeout.
let Some(message) = message.decode()? else {
let Some(message) = message.decode()?.into_std() else {
continue;
};

View File

@@ -29,7 +29,7 @@ impl CastBytes for EncodedLoginMessage {
impl Encode<EncodedLoginMessage> for anyhow::Result<LoginMessage> {
fn encode(self) -> EncodedLoginMessage {
EncodedLoginMessage(self.map(LoginMessage::encode).encode())
EncodedLoginMessage(encoding::Result::from(self).map_encode())
}
}
@@ -124,7 +124,7 @@ impl Decode<LoginMessage> for InnerEncodedLoginMessage {
let mut bytes = self.0;
let variant_byte = bytes
.pop()
.context("Failed to parse login message | bytes are empty")?;
.context("Failed to parse login message | Bytes are empty")?;
let variant = LoginMessageVariant::from_byte(variant_byte)?;
use LoginMessageVariant::*;
match variant {

View File

@@ -21,6 +21,159 @@ impl CastBytes for EncodedTransportMessage {
}
}
// ===================
// TRANSPORT MESSAGE
// ===================
/// When an EncodedTransportMessage is received,
/// it is decoded into this type.
///
/// Note that inner bytes for top level message variants are left as is,
/// as their decoding is left to specific handler.
/// The main receiving hot loop should do minimal parsing.
#[derive(Debug, EnumVariants)]
#[variant_derive(Debug, Clone, Copy)]
pub enum TransportMessage {
Login(EncodedLoginMessage),
Request(EncodedRequestMessage),
Response(EncodedResponseMessage),
Terminal(EncodedTerminalMessage),
}
impl Encode<EncodedTransportMessage> for TransportMessage {
fn encode(self) -> EncodedTransportMessage {
let variant_byte = self.extract_variant().as_byte();
let mut bytes = match self {
TransportMessage::Login(data) => data.into_vec(),
TransportMessage::Request(data) => data.0.into_vec(),
TransportMessage::Response(data) => data.0.into_vec(),
TransportMessage::Terminal(data) => data.0.into_vec(),
};
bytes.push(variant_byte);
EncodedTransportMessage(bytes)
}
}
impl Decode<TransportMessage> for EncodedTransportMessage {
fn decode(self) -> anyhow::Result<TransportMessage> {
let mut bytes = self.0;
let variant_byte = bytes
.pop()
.context("Failed to decode message | bytes are empty")?;
use TransportMessageVariant::*;
let message =
match TransportMessageVariant::from_byte(variant_byte)? {
Login => TransportMessage::Login(
EncodedLoginMessage::from_vec(bytes),
),
Request => TransportMessage::Request(EncodedRequestMessage(
EncodedChannel::from_vec(bytes),
)),
Response => TransportMessage::Response(
EncodedResponseMessage(EncodedChannel::from_vec(bytes)),
),
Terminal => TransportMessage::Terminal(
EncodedTerminalMessage(EncodedChannel::from_vec(bytes)),
),
};
Ok(message.into())
}
}
impl TransportMessageVariant {
pub fn from_byte(byte: u8) -> anyhow::Result<Self> {
use TransportMessageVariant::*;
let variant = match byte {
0 => Login,
1 => Request,
2 => Response,
3 => Terminal,
other => {
return Err(anyhow!(
"Got unrecognized MessageVariant byte: {other}"
));
}
};
Ok(variant)
}
pub fn as_byte(self) -> u8 {
use TransportMessageVariant::*;
match self {
Login => 0,
Request => 1,
Response => 2,
Terminal => 3,
}
}
}
// ===================
// DECODED TRANSPORT
// ===================
pub enum DecodedTransportMessage {
Login(anyhow::Result<LoginMessage>),
Request(WithChannel<EncodedJsonMessage>),
Response(
WithChannel<Option<anyhow::Result<EncodedJsonMessage>>>, // EncodedChannel<EncodedOption<EncodedResult<EncodedJsonMessage>>>,
),
Terminal(WithChannel<Vec<u8>>),
}
impl Encode<TransportMessage> for DecodedTransportMessage {
fn encode(self) -> TransportMessage {
use DecodedTransportMessage::*;
match self {
Login(res) => TransportMessage::Login(res.encode()),
Request(data) => TransportMessage::Request(
EncodedRequestMessage(data.encode()),
),
Response(data) => {
TransportMessage::Response(EncodedResponseMessage(
data
.map(|data| encoding::Option::from(data).map_encode())
.encode(),
))
}
Terminal(data) => TransportMessage::Terminal(
EncodedTerminalMessage(data.encode()),
),
}
}
}
impl Encode<EncodedTransportMessage> for DecodedTransportMessage {
fn encode(self) -> EncodedTransportMessage {
let res: TransportMessage = self.encode();
res.encode()
}
}
impl<T: From<DecodedTransportMessage>> Decode<T>
for TransportMessage
{
fn decode(self) -> anyhow::Result<T> {
let message = match self {
TransportMessage::Login(encoded_result) => {
DecodedTransportMessage::Login(encoded_result.decode())
}
TransportMessage::Request(encoded_channel) => {
DecodedTransportMessage::Request(encoded_channel.0.decode()?)
}
TransportMessage::Response(encoded_channel) => {
DecodedTransportMessage::Response(
encoded_channel.0.decode()?.map(|data| data.decode_map()),
)
}
TransportMessage::Terminal(encoded_channel) => {
DecodedTransportMessage::Terminal(encoded_channel.0.decode()?)
}
};
Ok(message.into())
}
}
// =================
// REQUEST MESSAGE
// =================
@@ -74,13 +227,14 @@ impl CastBytes for EncodedResponseMessage {
}
impl Encode<EncodedResponseMessage>
for WithChannel<Option<anyhow::Result<EncodedJsonMessage>>>
for WithChannel<
encoding::Option<encoding::Result<EncodedJsonMessage>>,
>
{
fn encode(self) -> EncodedResponseMessage {
let data = self
.map(|data| data.map(|data| data.encode()).encode())
.encode();
EncodedResponseMessage(data)
EncodedResponseMessage(
self.map(|data| data.map_encode()).encode(),
)
}
}
@@ -88,8 +242,7 @@ impl Encode<EncodedResponseMessage>
for WithChannel<EncodedResult<EncodedJsonMessage>>
{
fn encode(self) -> EncodedResponseMessage {
let data = self.map(|data| Some(data).encode()).encode();
EncodedResponseMessage(data)
EncodedResponseMessage(self.map(Some).map_encode())
}
}
@@ -101,10 +254,20 @@ impl<T: DeserializeOwned>
self,
) -> anyhow::Result<WithChannel<Option<anyhow::Result<T>>>> {
let WithChannel { channel, data } = self.0.decode()?;
let data = data
.decode()?
.map(|data| data.decode().and_then(|data| data.decode()));
Ok(WithChannel { channel, data })
let data = data.decode()?.into_std();
// Does it this way to make sure the inner result is preserved
// for later handling.
let Some(data) = data else {
return Ok(WithChannel {
channel,
data: None,
});
};
let data = data.decode().and_then(|data| data.decode());
Ok(WithChannel {
channel,
data: Some(data),
})
}
}
@@ -146,161 +309,6 @@ impl Encode<EncodedTerminalMessage> for WithChannel<Vec<u8>> {
impl Decode<WithChannel<Vec<u8>>> for EncodedTerminalMessage {
fn decode(self) -> anyhow::Result<WithChannel<Vec<u8>>> {
let WithChannel { channel, data } = self.0.decode()?;
let data = data.decode()?;
Ok(WithChannel { channel, data })
}
}
// ===================
// TRANSPORT MESSAGE
// ===================
#[derive(Debug, EnumVariants)]
#[variant_derive(Debug, Clone, Copy)]
pub enum TransportMessage {
Login(EncodedLoginMessage),
Request(EncodedRequestMessage),
Response(EncodedResponseMessage),
Terminal(EncodedTerminalMessage),
}
impl Encode<EncodedTransportMessage> for TransportMessage {
fn encode(self) -> EncodedTransportMessage {
let variant_byte = self.extract_variant().as_byte();
let mut bytes = match self {
TransportMessage::Login(data) => data.into_vec(),
TransportMessage::Request(data) => data.0.into_vec(),
TransportMessage::Response(data) => data.0.into_vec(),
TransportMessage::Terminal(data) => data.0.into_vec(),
};
bytes.push(variant_byte);
EncodedTransportMessage(bytes)
}
}
impl<T: From<TransportMessage>> Decode<T>
for EncodedTransportMessage
{
fn decode(self) -> anyhow::Result<T> {
let mut bytes = self.0;
let variant_byte = bytes
.pop()
.context("Failed to decode message | bytes are empty")?;
use TransportMessageVariant::*;
let message =
match TransportMessageVariant::from_byte(variant_byte)? {
Login => TransportMessage::Login(
EncodedLoginMessage::from_vec(bytes),
),
Request => TransportMessage::Request(EncodedRequestMessage(
EncodedChannel::from_vec(bytes),
)),
Response => TransportMessage::Response(
EncodedResponseMessage(EncodedChannel::from_vec(bytes)),
),
Terminal => TransportMessage::Terminal(
EncodedTerminalMessage(EncodedChannel::from_vec(bytes)),
),
};
Ok(message.into())
}
}
// ===================
// DECODED TRANSPORT
// ===================
pub enum DecodedTransportMessage {
Login(anyhow::Result<LoginMessage>),
Request(WithChannel<EncodedJsonMessage>),
Response(
WithChannel<Option<anyhow::Result<EncodedJsonMessage>>>, // EncodedChannel<EncodedOption<EncodedResult<EncodedJsonMessage>>>,
),
Terminal(WithChannel<Vec<u8>>),
}
impl Encode<TransportMessage> for DecodedTransportMessage {
fn encode(self) -> TransportMessage {
use DecodedTransportMessage::*;
match self {
Login(res) => TransportMessage::Login(res.encode()),
Request(data) => TransportMessage::Request(
EncodedRequestMessage(data.encode()),
),
Response(data) => {
TransportMessage::Response(EncodedResponseMessage(
data
.map(|data| data.map(|data| data.encode()).encode())
.encode(),
))
}
Terminal(data) => TransportMessage::Terminal(
EncodedTerminalMessage(data.encode()),
),
}
}
}
impl Encode<EncodedTransportMessage> for DecodedTransportMessage {
fn encode(self) -> EncodedTransportMessage {
let res: TransportMessage = self.encode();
res.encode()
}
}
impl<T: From<DecodedTransportMessage>> Decode<T>
for TransportMessage
{
fn decode(self) -> anyhow::Result<T> {
let message = match self {
TransportMessage::Login(encoded_result) => {
DecodedTransportMessage::Login(encoded_result.decode())
}
TransportMessage::Request(encoded_channel) => {
DecodedTransportMessage::Request(encoded_channel.0.decode()?)
}
TransportMessage::Response(encoded_channel) => {
let WithChannel { channel, data } =
encoded_channel.0.decode()?;
let data = data.decode()?.map(|data| data.decode());
DecodedTransportMessage::Response(WithChannel {
channel,
data,
})
}
TransportMessage::Terminal(encoded_channel) => {
DecodedTransportMessage::Terminal(encoded_channel.0.decode()?)
}
};
Ok(message.into())
}
}
impl TransportMessageVariant {
pub fn from_byte(byte: u8) -> anyhow::Result<Self> {
use TransportMessageVariant::*;
let variant = match byte {
0 => Login,
1 => Request,
2 => Response,
3 => Terminal,
other => {
return Err(anyhow!(
"Got unrecognized MessageVariant byte: {other}"
));
}
};
Ok(variant)
}
pub fn as_byte(self) -> u8 {
use TransportMessageVariant::*;
match self {
Login => 0,
Request => 1,
Response => 2,
Terminal => 3,
}
self.0.decode_map()
}
}

View File

@@ -2,7 +2,7 @@ use anyhow::anyhow;
use bytes::Bytes;
use uuid::Uuid;
use crate::{CastBytes, Decode, Encode};
use crate::{CastBytes, Decode, Encode, impl_wrapper};
/// Message wrapper to handle Error unwrapping
/// anywhere in the en/decoding chain.
@@ -13,24 +13,16 @@ use crate::{CastBytes, Decode, Encode};
#[derive(Clone, Debug)]
pub struct EncodedChannel<T>(T);
impl<T> From<T> for EncodedChannel<T> {
fn from(value: T) -> Self {
Self(value)
}
}
impl_wrapper!(EncodedChannel);
impl<T: CastBytes> CastBytes for EncodedChannel<T> {
fn from_bytes(bytes: Bytes) -> Self {
Self(T::from_bytes(bytes))
}
fn into_bytes(self) -> Bytes {
self.0.into_bytes()
}
fn from_vec(vec: Vec<u8>) -> Self {
Self(T::from_vec(vec))
}
fn into_vec(self) -> Vec<u8> {
self.0.into_vec()
impl<B: CastBytes> EncodedChannel<B> {
pub fn decode_map<T>(self) -> anyhow::Result<WithChannel<T>>
where
B: Decode<T>,
{
let WithChannel { channel, data } = self.decode()?;
let data = data.decode()?;
Ok(WithChannel { channel, data })
}
}
@@ -46,14 +38,21 @@ impl<T> WithChannel<T> {
data: map(self.data),
}
}
}
impl<T, E: Encode<T>> Encode<WithChannel<T>> for WithChannel<E> {
fn encode(self) -> WithChannel<T> {
WithChannel {
channel: self.channel,
data: self.data.encode(),
}
pub fn map_encode<B: CastBytes + Send>(self) -> EncodedChannel<B>
where
T: Encode<B>,
{
self.map(Encode::encode).encode()
}
pub fn map_decode<D>(self) -> anyhow::Result<WithChannel<D>>
where
T: CastBytes + Send + Decode<D>,
{
let WithChannel { channel, data } = self;
let data = data.decode()?;
Ok(WithChannel { channel, data })
}
}

View File

@@ -1,7 +1,9 @@
use anyhow::Context;
use serde::{Serialize, de::DeserializeOwned};
use crate::{CastBytes, Decode, Encode, EncodedResult};
use crate::{
CastBytes, Decode, Encode, EncodedResult, impl_identity,
};
/// ```markdown
/// | --- u8[] --- |
@@ -10,6 +12,8 @@ use crate::{CastBytes, Decode, Encode, EncodedResult};
#[derive(Clone, Debug)]
pub struct EncodedJsonMessage(Vec<u8>);
impl_identity!(EncodedJsonMessage);
impl CastBytes for EncodedJsonMessage {
fn from_vec(vec: Vec<u8>) -> Self {
Self(vec)
@@ -22,14 +26,15 @@ impl CastBytes for EncodedJsonMessage {
pub struct JsonMessage<'a, T>(pub &'a T);
impl<'a, T: Serialize + Send>
Encode<anyhow::Result<EncodedJsonMessage>> for JsonMessage<'a, T>
Encode<crate::Result<EncodedJsonMessage>> for JsonMessage<'a, T>
where
&'a T: Send,
{
fn encode(self) -> anyhow::Result<EncodedJsonMessage> {
let bytes = serde_json::to_vec(self.0)
.context("Failed to serialize data to bytes")?;
Ok(EncodedJsonMessage(bytes))
fn encode(self) -> crate::Result<EncodedJsonMessage> {
serde_json::to_vec(self.0)
.context("Failed to serialize data to bytes")
.map(EncodedJsonMessage)
.into()
}
}

View File

@@ -22,30 +22,6 @@ pub trait Encode<Target>: Sized + Send {
}
}
impl Encode<Bytes> for Bytes {
fn encode(self) -> Bytes {
self
}
}
impl Encode<Vec<u8>> for Vec<u8> {
fn encode(self) -> Vec<u8> {
self
}
}
impl Encode<Vec<u8>> for Bytes {
fn encode(self) -> Vec<u8> {
self.into()
}
}
impl Encode<Bytes> for Vec<u8> {
fn encode(self) -> Bytes {
self.into()
}
}
pub trait Decode<Target>: Sized {
fn decode(self) -> anyhow::Result<Target>;
fn decode_into<T>(self) -> anyhow::Result<T>
@@ -56,29 +32,11 @@ pub trait Decode<Target>: Sized {
}
}
impl Decode<Bytes> for Bytes {
fn decode(self) -> anyhow::Result<Bytes> {
Ok(self)
}
}
impl_identity!(Bytes);
impl_identity!(Vec<u8>);
impl Decode<Vec<u8>> for Vec<u8> {
fn decode(self) -> anyhow::Result<Vec<u8>> {
Ok(self)
}
}
impl Decode<Vec<u8>> for Bytes {
fn decode(self) -> anyhow::Result<Vec<u8>> {
Ok(self.into())
}
}
impl Decode<Bytes> for Vec<u8> {
fn decode(self) -> anyhow::Result<Bytes> {
Ok(self.into())
}
}
impl_identity_into!(Bytes, Vec<u8>);
impl_identity_into!(Vec<u8>, Bytes);
/// Helps cast between the top level message types.
/// Implement whichever ones are most convenient for the source type.
@@ -114,3 +72,64 @@ impl CastBytes for Vec<u8> {
self
}
}
// Encode is basically 'Into',
// while decode is 'TryInto'.
#[macro_export]
macro_rules! impl_identity {
($typ:ty) => {
impl Encode<$typ> for $typ {
fn encode(self) -> $typ {
self
}
}
impl Decode<$typ> for $typ {
fn decode(self) -> anyhow::Result<$typ> {
Ok(self)
}
}
};
}
/// impl where a: Into<b>
#[macro_export]
macro_rules! impl_identity_into {
($a:ty, $b:ty) => {
impl Encode<$b> for $a {
fn encode(self) -> $b {
self.into()
}
}
impl Decode<$b> for $a {
fn decode(self) -> anyhow::Result<$b> {
Ok(self.into())
}
}
};
}
#[macro_export]
macro_rules! impl_wrapper {
($struct:ident) => {
impl<T> From<T> for $struct<T> {
fn from(value: T) -> Self {
Self(value)
}
}
impl<T: CastBytes> CastBytes for $struct<T> {
fn from_bytes(bytes: Bytes) -> Self {
Self(T::from_bytes(bytes))
}
fn into_bytes(self) -> Bytes {
self.0.into_bytes()
}
fn from_vec(vec: Vec<u8>) -> Self {
Self(T::from_vec(vec))
}
fn into_vec(self) -> Vec<u8> {
self.0.into_vec()
}
}
};
}

View File

@@ -1,7 +1,9 @@
use std::option::Option as StdOption;
use anyhow::Context;
use bytes::Bytes;
use crate::{CastBytes, Decode, Encode};
use crate::{CastBytes, Decode, Encode, impl_wrapper};
/// Message wrapper to handle Option unwrapping
/// anywhere in the en/decoding chain.
@@ -12,29 +14,60 @@ use crate::{CastBytes, Decode, Encode};
#[derive(Clone, Debug)]
pub struct EncodedOption<T>(T);
impl<T> From<T> for EncodedOption<T> {
fn from(value: T) -> Self {
Self(value)
impl_wrapper!(EncodedOption);
impl<B: CastBytes + Send> EncodedOption<B> {
/// Will only produce None if really None, with confirmed None byte.
/// Any error in decoding will lead to Some(Err(e))
pub fn decode_map<T>(self) -> StdOption<anyhow::Result<T>>
where
B: Decode<T>,
{
self.decode().and_then(|data| data.map_decode()).transpose()
}
}
impl<T: CastBytes> CastBytes for EncodedOption<T> {
fn from_bytes(bytes: Bytes) -> Self {
Self(T::from_bytes(bytes))
/// Just std Option,
/// but can implement on it.
pub enum Option<T> {
Some(T),
None,
}
impl<T> Option<T> {
pub fn into_std(self) -> StdOption<T> {
self.into()
}
fn into_bytes(self) -> Bytes {
self.0.into_bytes()
pub fn map<R>(self, map: impl FnOnce(T) -> R) -> Option<R> {
use Option::*;
match self {
Some(t) => Some(map(t)),
None => None,
}
}
fn from_vec(vec: Vec<u8>) -> Self {
Self(T::from_vec(vec))
pub fn map_encode<B: CastBytes + Send>(self) -> EncodedOption<B>
where
T: Encode<B>,
{
self.map(Encode::encode).encode()
}
fn into_vec(self) -> Vec<u8> {
self.0.into_vec()
pub fn map_decode<D>(self) -> anyhow::Result<StdOption<D>>
where
T: CastBytes + Send + Decode<D>,
{
match self.map(Decode::decode) {
Option::Some(res) => res.map(Some),
Option::None => Ok(None),
}
}
}
impl<T: CastBytes + Send> Encode<EncodedOption<T>> for Option<T> {
fn encode(self) -> EncodedOption<T> {
use Option::*;
match self {
Some(data) => {
let mut bytes = data.into_vec();
@@ -46,8 +79,15 @@ impl<T: CastBytes + Send> Encode<EncodedOption<T>> for Option<T> {
}
}
impl<T: CastBytes + Send> Encode<EncodedOption<T>> for StdOption<T> {
fn encode(self) -> EncodedOption<T> {
Option::from(self).encode()
}
}
impl<T: CastBytes> Decode<Option<T>> for EncodedOption<T> {
fn decode(self) -> anyhow::Result<Option<T>> {
use Option::*;
let mut bytes = self.0.into_vec();
let option_byte =
bytes.pop().context("OptionWrapper bytes cannot be empty")?;
@@ -58,3 +98,21 @@ impl<T: CastBytes> Decode<Option<T>> for EncodedOption<T> {
}
}
}
impl<T> From<StdOption<T>> for Option<T> {
fn from(value: StdOption<T>) -> Self {
match value {
Some(t) => Self::Some(t),
None => Self::None,
}
}
}
impl<T> From<Option<T>> for StdOption<T> {
fn from(value: Option<T>) -> Self {
match value {
Option::Some(t) => Some(t),
Option::None => None,
}
}
}

View File

@@ -1,8 +1,8 @@
use anyhow::Context;
use anyhow::{Context, Result as AnyhowResult};
use bytes::Bytes;
use serror::{deserialize_error_bytes, serialize_error_bytes};
use crate::{CastBytes, Decode, Encode};
use crate::{CastBytes, Decode, Encode, impl_wrapper};
/// Message wrapper to handle Error unwrapping
/// anywhere in the en/decoding chain.
@@ -13,31 +13,49 @@ use crate::{CastBytes, Decode, Encode};
#[derive(Clone, Debug)]
pub struct EncodedResult<T>(T);
impl<T> From<T> for EncodedResult<T> {
fn from(value: T) -> Self {
Self(value)
impl_wrapper!(EncodedResult);
/// Just anyhow's Result,
/// but can implement on it.
pub enum Result<T> {
Ok(T),
Err(anyhow::Error),
}
impl<T> Result<T> {
pub fn into_anyhow(self) -> AnyhowResult<T> {
self.into()
}
pub fn map<R>(self, map: impl FnOnce(T) -> R) -> Result<R> {
use Result::*;
match self {
Ok(t) => Ok(map(t)),
Err(e) => Err(e),
}
}
pub fn map_encode<B: CastBytes + Send>(self) -> EncodedResult<B>
where
T: Encode<B>,
{
self.map(Encode::encode).encode()
}
pub fn map_decode<D>(self) -> anyhow::Result<D>
where
T: CastBytes + Send + Decode<D>,
{
match self.map(Decode::decode) {
Result::Ok(res) => res,
Result::Err(e) => Err(e),
}
}
}
impl<T: CastBytes> CastBytes for EncodedResult<T> {
fn from_bytes(bytes: Bytes) -> Self {
Self(T::from_bytes(bytes))
}
fn into_bytes(self) -> Bytes {
self.0.into_bytes()
}
fn from_vec(vec: Vec<u8>) -> Self {
Self(T::from_vec(vec))
}
fn into_vec(self) -> Vec<u8> {
self.0.into_vec()
}
}
impl<T: CastBytes + Send> Encode<EncodedResult<T>>
for anyhow::Result<T>
{
impl<T: CastBytes + Send> Encode<EncodedResult<T>> for Result<T> {
fn encode(self) -> EncodedResult<T> {
use Result::*;
let bytes = match self {
Ok(data) => {
let mut bytes = data.into_vec();
@@ -55,8 +73,14 @@ impl<T: CastBytes + Send> Encode<EncodedResult<T>>
}
impl<T: CastBytes + Send> Encode<EncodedResult<T>>
for &anyhow::Error
for AnyhowResult<T>
{
fn encode(self) -> EncodedResult<T> {
Result::from(self).encode()
}
}
impl<T: CastBytes> Encode<EncodedResult<T>> for &anyhow::Error {
fn encode(self) -> EncodedResult<T> {
let mut bytes = serialize_error_bytes(self);
bytes.push(1);
@@ -65,7 +89,7 @@ impl<T: CastBytes + Send> Encode<EncodedResult<T>>
}
impl<T: CastBytes> Decode<T> for EncodedResult<T> {
fn decode(self) -> anyhow::Result<T> {
fn decode(self) -> AnyhowResult<T> {
let mut bytes = self.0.into_vec();
let result_byte =
bytes.pop().context("ResultWrapper bytes cannot be empty")?;
@@ -76,3 +100,21 @@ impl<T: CastBytes> Decode<T> for EncodedResult<T> {
}
}
}
impl<T> From<AnyhowResult<T>> for Result<T> {
fn from(value: AnyhowResult<T>) -> Self {
match value {
Ok(t) => Self::Ok(t),
Err(e) => Self::Err(e),
}
}
}
impl<T> From<Result<T>> for AnyhowResult<T> {
fn from(value: Result<T>) -> Self {
match value {
Result::Ok(t) => Ok(t),
Result::Err(e) => Err(e),
}
}
}

View File

@@ -86,7 +86,7 @@ impl Sender<EncodedTransportMessage> {
where
&'a T: Send,
{
let data = JsonMessage(request).encode()?;
let data = JsonMessage(request).encode().into_anyhow()?;
let message =
DecodedTransportMessage::Request(WithChannel { channel, data });
self.send_message(message).await

View File

@@ -119,7 +119,7 @@ pub trait WebsocketSenderExt: WebsocketSender + Send {
&'a T: Send,
{
async move {
let data = JsonMessage(request).encode()?;
let data = JsonMessage(request).encode().into_anyhow()?;
let message = DecodedTransportMessage::Request(WithChannel {
channel,
data,