1use crate::error::{bound, exact_length, require, Error, Rule};
4
5use coven_crypto::{SEALED_OBJECT_CHUNK_OVERHEAD, SIGNATURE_LEN};
6
7pub const STORED_CHUNK_OVERHEAD: usize = 4 + SEALED_OBJECT_CHUNK_OVERHEAD;
10
11pub(crate) fn signature(bytes: &[u8]) -> Result<coven_crypto::Signature, Error> {
12 exact_length(bytes.len(), SIGNATURE_LEN)?;
13 Ok(coven_crypto::Signature::from_bytes(bytes.try_into().expect("a signature's length")))
14}
15
16pub(crate) fn prefix(bytes: &[u8], kind: u8) -> Result<(), Error> {
17 let prefix = bytes.get(..3).ok_or(Error::Truncated)?;
18 if prefix[0] != kind {
19 return Err(Error::UnknownTag { field: "sealed object kind", tag: prefix[0] });
20 }
21 let crate::FormatVersion::V1 = crate::FormatVersion::decode(prefix)?;
22 Ok(())
23}
24
25pub(crate) fn chunk_length(prefix: &[u8], maximum: usize) -> Result<usize, Error> {
26 let bytes: [u8; 4] = prefix.get(..4).ok_or(Error::Truncated)?.try_into().expect("four bytes");
27 let length = u32::from_be_bytes(bytes) as usize;
28 bound(length, maximum, "sealed chunk")?;
29 require(length > 0, "sealed chunk", Rule::Chunk)?;
30 Ok(length + STORED_CHUNK_OVERHEAD)
31}
32
33pub(crate) fn chunk(bytes: &[u8], maximum: usize) -> Result<&[u8], Error> {
34 exact_length(bytes.len(), chunk_length(bytes, maximum)?)?;
35 Ok(&bytes[4..])
36}
37
38pub(crate) fn encode_chunk(bytes: &[u8]) -> Result<Vec<u8>, Error> {
39 let length = bytes.len().checked_sub(SEALED_OBJECT_CHUNK_OVERHEAD).ok_or(Error::Truncated)?;
40 require(length > 0, "sealed chunk", Rule::Chunk)?;
41 bound(length, crate::wire::MAX_OBJECT, "sealed chunk")?;
42 let mut result = Vec::new();
43 result.try_reserve_exact(4 + bytes.len())?;
44 result.extend_from_slice(&(length as u32).to_be_bytes());
45 result.extend_from_slice(bytes);
46 Ok(result)
47}
48
49#[cfg(test)]
50#[path = "sealed_tests.rs"]
51mod tests;