coven_format/
sealed_snapshot.rs1use crate::error::{exact_length, Error};
4use crate::sealed;
5use crate::sequence::Purpose;
6use crate::wire::{Decoder, Encoder, Wire};
7use coven_crypto::{Signature, SIGNATURE_LEN};
8use coven_foundation::id_source::KeyId;
9use coven_merge::Audience;
10
11#[derive(Clone, Debug, PartialEq, Eq)]
13pub struct SnapshotObjectPrefix {
14 pub audience: Audience,
16 pub key: KeyId,
18 pub covers: u64,
20 pub purpose: Purpose,
22}
23impl SnapshotObjectPrefix {
24 pub const MAX_SIGNED_PREFIX: usize = 3 + 17 + 16 + 8 + 5 + SIGNATURE_LEN;
26 pub fn signed_length(bytes: &[u8]) -> Result<usize, Error> {
28 Ok(Self::length(bytes)? + SIGNATURE_LEN)
29 }
30 pub fn plaintext_length(&self, object_length: u64) -> Result<u64, Error> {
32 crate::sealed_stream::plaintext_length(
33 object_length.checked_sub(self.encode()?.len() as u64 + 128).ok_or(Error::Truncated)?,
34 )
35 }
36 pub fn encode(&self) -> Result<Vec<u8>, Error> {
38 let mut out = Encoder::new();
39 out.bytes(&crate::FormatVersion::CURRENT.prefix(crate::kinds::SNAPSHOT))?;
40 self.audience.put(&mut out)?;
41 self.key.put(&mut out)?;
42 self.covers.put(&mut out)?;
43 self.purpose.put(&mut out)?;
44 Ok(out.bytes)
45 }
46 pub fn length(bytes: &[u8]) -> Result<usize, Error> {
48 sealed::prefix(bytes, crate::kinds::SNAPSHOT)?;
49 let purpose = match *bytes.get(3).ok_or(Error::Truncated)? {
50 0 => 28,
51 1 => 44,
52 tag => return Err(Error::UnknownTag { field: "audience", tag }),
53 };
54 match *bytes.get(purpose).ok_or(Error::Truncated)? {
55 0 | 2 => Ok(purpose + 1),
56 1 => Ok(purpose + 5),
57 tag => Err(Error::UnknownTag { field: "snapshot purpose", tag }),
58 }
59 }
60 pub fn decode_signed(bytes: &[u8]) -> Result<(Self, Signature), Error> {
62 let length = Self::length(bytes)?;
63 let prefix = Self::decode(bytes.get(..length).ok_or(Error::Truncated)?)?;
64 Ok((prefix, sealed::signature(&bytes[length..])?))
65 }
66 pub fn decode(bytes: &[u8]) -> Result<Self, Error> {
68 exact_length(bytes.len(), Self::length(bytes)?)?;
69 let mut input = Decoder::new(&bytes[3..])?;
70 let prefix = Self {
71 audience: Wire::get(&mut input)?,
72 key: Wire::get(&mut input)?,
73 covers: Wire::get(&mut input)?,
74 purpose: Wire::get(&mut input)?,
75 };
76 input.finish()?;
77 Ok(prefix)
78 }
79}
80
81#[cfg(test)]
82#[path = "sealed_snapshot_tests.rs"]
83mod tests;