Skip to main content

titan_api_codec/dec/
common.rs

1//! Common traits and implementations for decoding of messages from binary representations.
2
3// TODO: Look into how to allow for no-copy deserialization to work with tranforms.
4// Would likely need for decode to return some intermediate object that contains both the
5// deserialized value as well as a Bytes with the underlying data, whether that be the original
6// data or the transformed data.
7
8use bytes::Bytes;
9use serde::de::DeserializeOwned;
10use thiserror::Error;
11
12use crate::transform::BinaryTransform;
13
14/// Possible errors that can occur while decoding messages.
15#[derive(Error, Debug)]
16pub enum DecodeError {
17    /// Serialization to the data format failed.
18    #[error("Failed to deserialize message from binary data")]
19    DeserializationFailed(#[from] Box<dyn std::error::Error + Send + Sync>),
20    /// Transformation of the serialized data failed (ex. compression).
21    #[error("Failed to apply transform to serialized data")]
22    TransformFailed(#[from] std::io::Error),
23}
24
25/// A decoder that can transform binary data into a serde-deserializable object.
26pub trait Decoder {
27    /// Attempt to decode the given binary data.
28    fn decode<T>(&self, data: Bytes) -> Result<T, DecodeError>
29    where
30        T: DeserializeOwned;
31
32    /// Attempt to decode the given binary data, possibly mutating the state of the decoder.
33    fn decode_mut<T>(&mut self, data: Bytes) -> Result<T, DecodeError>
34    where
35        T: DeserializeOwned,
36    {
37        self.decode(data)
38    }
39
40    /// Wraps this decoder, first applying `transformer` to any data before passing it to the
41    /// decoder.
42    fn transformed<BT>(self, transformer: BT) -> TransformedDecoder<Self, BT>
43    where
44        Self: Sized,
45        BT: BinaryTransform,
46    {
47        TransformedDecoder::new(self, transformer)
48    }
49}
50
51/// A decoder that wraps another [`Decoder`], first applying a [`BinaryTransform`] to the data.
52pub struct TransformedDecoder<D: Decoder, BT: BinaryTransform> {
53    decoder: D,
54    transformer: BT,
55}
56
57impl<D: Decoder, BT: BinaryTransform> TransformedDecoder<D, BT> {
58    // Wraps `decoder`, applying `transformer` to any data before passing the result for decoding.
59    fn new(decoder: D, transformer: BT) -> Self {
60        Self {
61            decoder,
62            transformer,
63        }
64    }
65}
66
67impl<D: Decoder, BT: BinaryTransform> Decoder for TransformedDecoder<D, BT> {
68    fn decode<T>(&self, data: Bytes) -> Result<T, DecodeError>
69    where
70        T: DeserializeOwned,
71    {
72        self.decoder.decode(
73            self.transformer
74                .transform(data)
75                .map_err(DecodeError::TransformFailed)?,
76        )
77    }
78
79    fn decode_mut<T>(&mut self, data: Bytes) -> Result<T, DecodeError>
80    where
81        T: DeserializeOwned,
82    {
83        self.decoder.decode_mut(
84            self.transformer
85                .transform_mut(data)
86                .map_err(DecodeError::TransformFailed)?,
87        )
88    }
89}