coven_format/version.rs
1//! Supported object formats, independent of the format selected for new objects.
2
3use crate::Error;
4
5/// The format of an object or a persisted upload attempt (Appendix C.2).
6#[derive(Clone, Copy, Debug, PartialEq, Eq)]
7pub enum FormatVersion {
8 /// format.md's first format.
9 V1,
10}
11
12impl FormatVersion {
13 /// The format selected for a new object. Retries use their recorded value.
14 pub const CURRENT: Self = Self::V1;
15
16 /// The version number written after the object's kind.
17 pub const fn number(self) -> u16 {
18 match self {
19 Self::V1 => 1,
20 }
21 }
22
23 /// The three clear bytes that start every stored object: `kind | version`.
24 pub(crate) const fn prefix(self, kind: u8) -> [u8; 3] {
25 let [high, low] = self.number().to_be_bytes();
26 [kind, high, low]
27 }
28
29 /// Read the format from a clear `kind | version` prefix, before parsing
30 /// version-specific fields. The object's decoder checks the kind separately.
31 pub fn decode(prefix: &[u8]) -> Result<Self, Error> {
32 let bytes = prefix.get(..3).ok_or(Error::Truncated)?;
33 match u16::from_be_bytes([bytes[1], bytes[2]]) {
34 1 => Ok(Self::V1),
35 version => Err(Error::UnsupportedVersion(version)),
36 }
37 }
38}
39
40/// The software version required to decode or apply an input from storage:
41/// the app schema its writes use, or the object format it is encoded in.
42/// Sync, setup and unlock all report it, so it lives with the formats.
43#[derive(Clone, Copy, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
44pub enum RequiredUpdate {
45 /// The application's schema.
46 AppSchema {
47 /// Required application schema version.
48 version: u32,
49 },
50 /// Coven's stored-object format.
51 CovenFormat {
52 /// Required object format version.
53 version: u16,
54 },
55}
56
57#[cfg(test)]
58#[path = "version_tests.rs"]
59mod tests;