titan-api-codec 1.2.9

Helpers for encoding and decoding Titan API messages
Documentation
//! Common traits and implementations for binary encoding of messages.

use bytes::Bytes;
use serde::ser::Serialize;
use thiserror::Error;

use crate::transform::BinaryTransform;

/// Possible errors that can occur while encoding messages.
#[derive(Error, Debug)]
pub enum EncodeError {
    /// Serialization to the data format failed.
    #[error("Failed to serialize message to data format")]
    SerializationFailed(#[from] Box<dyn std::error::Error + Send + Sync>),
    /// Transformation of the serialized data failed (ex. compression).
    #[error("Failed to apply transform to serialized data")]
    TransformFailed(#[from] std::io::Error),
}

/// An encoder that can transform a serde-serializable object into binary data.
pub trait Encoder {
    /// Encode the specified object and return the bytes representing the encoded value.
    fn encode<T>(&self, value: &T) -> Result<Bytes, EncodeError>
    where
        T: Serialize;

    /// Encode the specified object and return the bytes representing the encoded value, possibly
    /// mutating the state of the encoder.
    fn encode_mut<T>(&mut self, value: &T) -> Result<Bytes, EncodeError>
    where
        T: Serialize,
    {
        self.encode(value)
    }

    /// Takes the encoder and applies the given transform to data produced by it.
    fn transform<BT>(self, transformer: BT) -> TransformedEncoder<Self, BT>
    where
        Self: Sized,
        BT: BinaryTransform,
    {
        TransformedEncoder::new(self, transformer)
    }
}

/// An encoder that applies a transform to data encoded by another encoder.
pub struct TransformedEncoder<E: Encoder, BT: BinaryTransform> {
    encoder: E,
    transformer: BT,
}

impl<E: Encoder, BT: BinaryTransform> TransformedEncoder<E, BT> {
    // Wraps `encoder`, applying `transformer` to any encoded data.
    fn new(encoder: E, transformer: BT) -> Self {
        Self {
            encoder,
            transformer,
        }
    }
}

impl<E: Encoder, BT: BinaryTransform> Encoder for TransformedEncoder<E, BT> {
    fn encode<T>(&self, value: &T) -> Result<Bytes, EncodeError>
    where
        T: Serialize,
    {
        self.transformer
            .transform(self.encoder.encode(value)?)
            .map_err(EncodeError::TransformFailed)
    }

    fn encode_mut<T>(&mut self, value: &T) -> Result<Bytes, EncodeError>
    where
        T: Serialize,
    {
        self.transformer
            .transform_mut(self.encoder.encode_mut(value)?)
            .map_err(EncodeError::TransformFailed)
    }
}