mirror of
https://github.com/moghtech/komodo.git
synced 2026-04-28 11:49:39 -05:00
more on encoding
This commit is contained in:
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 })
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user