//! Traits for serializing and deserializing archived documents.
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/decoding errors from [`postcard`].
    #[error("couldn't serialize: {0}")]
    Postcard(#[from] postcard::Error),
}

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

/// Trait for serializing (marshaling) and deserializing (unmarshaling) archived documents.
pub trait Marshal<'de>: Serialize + Deserialize<'de> {
    /// 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(postcard::to_allocvec(self).map_err(MarshalErrorRepr::Postcard)?)
    }

    /// 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 = postcard::from_bytes(bytes).map_err(MarshalErrorRepr::Postcard)?;
        Ok(decoded)
    }
}

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