pro_serde_versioned/
lib.rs

1// ┌───────────────────────────────────────────────────────────────────────────┐
2// │                                                                           │
3// │  ██████╗ ██████╗  ██████╗   Copyright (C) The Prospective Company         │
4// │  ██╔══██╗██╔══██╗██╔═══██╗  All Rights Reserved - April 2022              │
5// │  ██████╔╝██████╔╝██║   ██║                                                │
6// │  ██╔═══╝ ██╔══██╗██║   ██║  Proprietary and confidential. Unauthorized    │
7// │  ██║     ██║  ██║╚██████╔╝  copying of this file, via any medium is       │
8// │  ╚═╝     ╚═╝  ╚═╝ ╚═════╝   strictly prohibited.                          │
9// │                                                                           │
10// └───────────────────────────────────────────────────────────────────────────┘
11
12#![doc = include_str!("../README.md")]
13
14mod formats;
15
16#[cfg(feature = "derive")]
17pub use pro_serde_versioned_derive::{VersionedDeserialize, VersionedSerialize, VersionedUpgrade};
18use serde::{Deserialize, Serialize};
19
20pub use crate::formats::*;
21
22/// Derivable trait used to chain upgrade a versioned wrapper to the latest
23/// version of a structure (e.g. v1 -> v2 -> ... -> latest)
24pub trait VersionedUpgrade {
25    type Latest;
26    fn upgrade_to_latest(self) -> Self::Latest;
27}
28
29/// Defines the next version of a given upgradable type (e.g. mystructv1 ->
30/// mystructv1)
31pub trait Upgrade<To> {
32    fn upgrade(self) -> To;
33}
34
35/// Allows for serializing to any supported format.
36pub trait VersionedSerialize {
37    type VersionedEnvelope<F: Serialize>: Serialize;
38
39    fn to_envelope<F>(&self) -> Result<Self::VersionedEnvelope<F>, F::Error>
40    where
41        F: SerializeFormat;
42
43    fn versioned_serialize<F>(&self) -> Result<F, F::Error>
44    where
45        F: SerializeFormat,
46    {
47        Ok(F::serialize_format(self.to_envelope::<F>()?)?)
48    }
49}
50
51/// Allows for serializing from any supported format.
52pub trait VersionedDeserialize: Sized + Clone {
53    type VersionedEnvelope<'a, F: Deserialize<'a>>: Deserialize<'a>;
54
55    fn from_envelope<'a, F>(data: &Self::VersionedEnvelope<'a, F>) -> Result<Self, F::Error>
56    where
57        F: DeserializeFormat + Deserialize<'a>;
58
59    fn versioned_deserialize<'a, F>(data: &'a F) -> Result<Self, F::Error>
60    where
61        F: DeserializeFormat + Deserialize<'a>,
62    {
63        let envelope: Self::VersionedEnvelope<'a, F> = F::deserialize_format(data)?;
64        Self::from_envelope(&envelope)
65    }
66}
67
68/// Serialize to the underlying format of a given serialization standard. (e.g.
69/// [serde_json::Value] for JSON, [std::borrow::Cow] of bytes for MsgPack, etc.)
70pub trait SerializeFormat: Sized + Serialize {
71    type Error: serde::ser::Error;
72    fn serialize_format<T>(data: T) -> Result<Self, Self::Error>
73    where
74        T: Serialize;
75}
76
77/// Deserialize from the underlying format of a given serialization standard.
78/// (e.g. [serde_json::Value] for JSON, [std::borrow::Cow] of bytes for MsgPack,
79/// etc.)
80pub trait DeserializeFormat: Sized {
81    type Error: serde::de::Error;
82    fn deserialize_format<'a, T>(&'a self) -> Result<T, Self::Error>
83    where
84        T: Deserialize<'a>;
85}
86
87/// Versioned wrapper for the underlying data format.
88/// Allows for partial deserialization of the data, and for
89/// the version number to be used to determine which
90/// deserialization method to use.
91#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)]
92pub struct VersionedEnvelope<T> {
93    pub version_number: usize,
94    pub data: T,
95}