titan-api-codec 1.2.9

Helpers for encoding and decoding Titan API messages
Documentation
//! Defines codecs for encoding and decoding messages for versions of the Titan API with optional
//! compression and possibly other options.

use std::marker::PhantomData;

use crate::{
    dec::{DecodeError, Decoder},
    enc::{EncodeError, Encoder},
};

use bytes::Bytes;
use serde::de::DeserializeOwned;
use serde::Serialize;
use thiserror::Error;

pub mod ws;

/// Errors that can occur while attempting to load a codec.
#[derive(Debug, Error, PartialEq, Eq)]
pub enum CodecLoadError {
    /// Protocol is unsupported.
    ///
    /// Normally wil be caused by the client requesting a different version than the server
    /// supports.
    #[error("Unsupported protocol {0}")]
    UnsupportedProtocol(String),
    /// Requested protocol and encoding is valid, but the encoding method is disabled.
    #[error("Requested encoding method enabled")]
    DisabledEncoding(&'static str),
}

/// An encoder that encodes a specific type of message.
pub trait TypedEncoder<T> {
    /// Type of error returned by this encoder if encoding fails.
    type Error;

    /// Encode the given value to binary.
    fn encode(&self, value: &T) -> Result<Bytes, Self::Error>;
    /// Encode the given value to binary, mutating the encoder if doing so provides a benefit.
    fn encode_mut(&mut self, value: &T) -> Result<Bytes, Self::Error>;
}

/// A decoder that decodes a specific type of message.
pub trait TypedDecoder {
    /// The type of messages this Decoder decodes.
    type Item;
    /// Type of error returned by this decoder if decoding fails.
    type Error;

    /// Attempt to decode the given data into a value.
    fn decode(&self, data: Bytes) -> Result<Self::Item, Self::Error>;
    /// Attempt to decode the given data into a value, mutating the decoder's state if doing so
    /// provides a benefit.
    fn decode_mut(&mut self, data: Bytes) -> Result<Self::Item, Self::Error>;
}

/// Represents a specific encoding and decoding scheme for one side of a connection.
///
/// The codec defines what messages the user is spected to send to the other side, as well as the
/// messages that are expected to be received from the other side.
///
/// The encoders and decoders generated by the Codec handle any optional transformations, such as
/// compression, as configured during protocol negotiation.
pub trait Codec {
    /// The type of message that is sent to the other side.
    type SendItem;
    /// The type of error that is returned if encoding fails.
    type SendError;
    /// The type of message that is expected to be received from the other side.
    type RecvItem;
    /// The type of error that is returned if decoding fails.
    type RecvError;

    /// Generates a new encoder for encoding messages to be sent to the other side of the
    /// connection.
    fn encoder(
        &self,
    ) -> Box<dyn TypedEncoder<Self::SendItem, Error = Self::SendError> + Send + Sync>;
    /// Generates a new decoder for encoding messages to be sent to the other side of the
    /// connection.
    fn decoder(
        &self,
    ) -> Box<dyn TypedDecoder<Item = Self::RecvItem, Error = Self::RecvError> + Send + Sync>;
}

/// Wraps an [`Encoder`], restricting thet type of message that can be encoded.
pub struct WrappedEncoder<T, E> {
    encoder: E,
    _tag: PhantomData<T>,
}

impl<T, E> WrappedEncoder<T, E>
where
    T: Serialize,
    E: Encoder,
{
    /// Creates a new [`WrappedEncoder`] using the given [`Encoder`].
    ///
    /// The new encoder is a [`TypedEncoder`] that only encodes values of type `T`.
    pub fn new(encoder: E) -> Self {
        Self {
            encoder,
            _tag: PhantomData,
        }
    }
}

impl<T, E> TypedEncoder<T> for WrappedEncoder<T, E>
where
    T: Serialize,
    E: Encoder,
{
    type Error = EncodeError;

    #[inline]
    fn encode(&self, value: &T) -> Result<Bytes, Self::Error> {
        self.encoder.encode(value)
    }

    #[inline]
    fn encode_mut(&mut self, value: &T) -> Result<Bytes, Self::Error> {
        self.encoder.encode_mut(value)
    }
}

/// Wraps a [`Decoder`], attempting to decode a specific message type from provided data.
pub struct WrappedDecoder<T, D> {
    decoder: D,
    _tag: PhantomData<T>,
}

impl<T, E> WrappedDecoder<T, E>
where
    T: Serialize,
    E: Decoder,
{
    /// Creates a new [`WrappedDecoder`] using the given [`Decoder`].
    ///
    /// The new decoder is a [`TypedDecoder`] that attempts to decode values of type `T` from
    /// provided data.
    pub fn new(decoder: E) -> Self {
        Self {
            decoder,
            _tag: PhantomData,
        }
    }
}

impl<T, D> TypedDecoder for WrappedDecoder<T, D>
where
    T: DeserializeOwned,
    D: Decoder,
{
    type Item = T;
    type Error = DecodeError;

    #[inline]
    fn decode(&self, data: Bytes) -> Result<Self::Item, Self::Error> {
        self.decoder.decode(data)
    }

    #[inline]
    fn decode_mut(&mut self, data: Bytes) -> Result<Self::Item, Self::Error> {
        self.decoder.decode_mut(data)
    }
}