omry-archiving 0.12.0

Archiving abstractions for the Omry project.
Documentation
//! Traits for serializing and deserializing archived documents.
use bincode::config::Configuration;
use bincode::serde::{borrow_decode_from_slice, encode_to_vec};
use serde::{Deserialize, Serialize};
use thiserror::Error;

/// Errors that can occur during serialization or deserialization.
#[derive(Debug, Error)]
#[error(transparent)]
pub struct MarshalError(#[from] MarshalErrorRepr);

/// Internal error variants for (de)serialization failures.
#[derive(Debug, Error)]
enum MarshalErrorRepr {
    /// Variant for encoding error from [`bincode`].
    #[error("couldn't serialize with bincode: {0}")]
    Serialize(#[from] bincode::error::EncodeError),

    /// Variant for decoding error from [`bincode`].
    #[error("couldn't deserialize with bincode: {0}")]
    Deserialize(#[from] bincode::error::DecodeError),
}

type MarshalResult<T> = Result<T, MarshalError>;

/// Trait for serializing (marshaling) and deserializing (unmarshaling) archived documents.
pub trait Marshal<'de>: Serialize + Deserialize<'de> {
    /// Bincode configuration that preserves compatibility with bincode 1.3.x
    /// (used by tokio-serde, in turn used by current version of tarpc).
    /// see <https://docs.rs/bincode/latest/bincode/migration_guide/index.html#from-options-to-configuration>
    const BINCODE_CONFIG: Configuration = bincode::config::legacy().with_variable_int_encoding();

    /// Attempts to serialize (marshal) to a byte vec.
    ///
    /// ## Errors
    /// Returns [`MarshalError`] if we couldn't serialize the value.
    fn to_byte_vec(&self) -> MarshalResult<Vec<u8>> {
        Ok(encode_to_vec(self, Self::BINCODE_CONFIG).map_err(MarshalErrorRepr::Serialize)?)
    }

    /// Attempts to deserialize (unmarshal) from a byte slice.
    ///
    /// ## Errors
    /// Returns [`MarshalError`] if we couldn't deserialize the value from the given slice.
    fn from_bytes(bytes: &'de [u8]) -> MarshalResult<Self> {
        let (decoded, _bytes_read) = borrow_decode_from_slice(bytes, Self::BINCODE_CONFIG)
            .map_err(MarshalErrorRepr::Deserialize)?;
        Ok(decoded)
    }
}

impl<'de, T> Marshal<'de> for T where T: Serialize + Deserialize<'de> {}