provenance-mark 0.23.1

A cryptographically-secured system for establishing and verifying the authenticity of works
Documentation
use base64::Engine as _;
use bc_ur::UR;
use dcbor::prelude::*;
use serde::{
    Deserialize,
    de::{Deserializer, Error as DeError},
    ser::Serializer,
};
use serde_json::json;

use crate::{PROVENANCE_SEED_LENGTH, ProvenanceSeed};

pub fn serialize_base64<S>(
    bytes: &[u8],
    serializer: S,
) -> Result<S::Ok, S::Error>
where
    S: Serializer,
{
    let encoded = base64::engine::general_purpose::STANDARD.encode(bytes);
    serializer.serialize_str(&encoded)
}

pub fn deserialize_base64<'de, D>(deserializer: D) -> Result<Vec<u8>, D::Error>
where
    D: Deserializer<'de>,
{
    let s = String::deserialize(deserializer)?;
    base64::engine::general_purpose::STANDARD
        .decode(s)
        .map_err(DeError::custom)
}

pub fn parse_seed(s: &str) -> Result<ProvenanceSeed, String> {
    let seed: ProvenanceSeed =
        serde_json::from_value(json!(s)).map_err(|e| e.to_string())?;
    Ok(seed)
}

pub fn parse_date(s: &str) -> Result<Date, String> {
    Date::from_string(s).map_err(|e| e.to_string())
}

pub fn serialize_cbor<S>(bytes: &[u8], serializer: S) -> Result<S::Ok, S::Error>
where
    S: Serializer,
{
    serialize_base64(bytes, serializer)
}

pub fn deserialize_cbor<'de, D>(deserializer: D) -> Result<Vec<u8>, D::Error>
where
    D: Deserializer<'de>,
{
    let data = deserialize_base64(deserializer)?;
    CBOR::try_from_data(&data).map_err(DeError::custom)?;
    Ok(data)
}

pub fn serialize_block<S>(
    seed: &[u8; PROVENANCE_SEED_LENGTH],
    serializer: S,
) -> Result<S::Ok, S::Error>
where
    S: serde::Serializer,
{
    serialize_base64(seed, serializer)
}

pub fn deserialize_block<'de, D>(
    deserializer: D,
) -> Result<[u8; PROVENANCE_SEED_LENGTH], D::Error>
where
    D: serde::Deserializer<'de>,
{
    let seed = deserialize_base64(deserializer)?;
    if seed.len() != PROVENANCE_SEED_LENGTH {
        return Err(serde::de::Error::custom(format!(
            "seed length is {}, expected {}",
            seed.len(),
            PROVENANCE_SEED_LENGTH
        )));
    }
    let mut result = [0; PROVENANCE_SEED_LENGTH];
    result.copy_from_slice(&seed);
    Ok(result)
}

pub fn serialize_iso8601<S>(
    date: &Date,
    serializer: S,
) -> Result<S::Ok, S::Error>
where
    S: serde::Serializer,
{
    serializer.serialize_str(&date.to_string())
}

pub fn deserialize_iso8601<'de, D>(deserializer: D) -> Result<Date, D::Error>
where
    D: serde::Deserializer<'de>,
{
    let s = String::deserialize(deserializer)?;
    Date::from_string(s).map_err(serde::de::Error::custom)
}

pub fn serialize_ur<S>(ur: &UR, serializer: S) -> Result<S::Ok, S::Error>
where
    S: serde::Serializer,
{
    serializer.serialize_str(&ur.to_string())
}

pub fn deserialize_ur<'de, D>(deserializer: D) -> Result<UR, D::Error>
where
    D: serde::Deserializer<'de>,
{
    let s = String::deserialize(deserializer)?;
    UR::from_ur_string(s).map_err(serde::de::Error::custom)
}