Skip to main content

greentic_types/
envelope.rs

1//! Canonical CBOR envelope for typed payloads.
2use alloc::string::String;
3
4#[cfg(feature = "serde")]
5use serde::{Deserialize, Serialize};
6
7use crate::cbor::canonical;
8use crate::cbor_bytes::CborBytes;
9
10/// Envelope carrying a canonical CBOR payload.
11#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
12#[derive(Clone, Debug, PartialEq, Eq)]
13pub struct Envelope {
14    /// Domain-specific kind (pack/component/etc.).
15    pub kind: String,
16    /// Schema identifier for the body.
17    pub schema: String,
18    /// Schema version for the body.
19    pub version: u32,
20    /// Canonical CBOR-encoded payload.
21    pub body: CborBytes,
22}
23
24impl Envelope {
25    /// Ensure the body payload is canonical CBOR.
26    pub fn ensure_canonical(&self) -> canonical::Result<()> {
27        self.body.ensure_canonical()
28    }
29}
30
31#[cfg(feature = "serde")]
32impl Envelope {
33    /// Build an envelope from a serializable body, encoding as canonical CBOR.
34    pub fn new<T: serde::Serialize>(
35        kind: impl Into<String>,
36        schema: impl Into<String>,
37        version: u32,
38        body: &T,
39    ) -> canonical::Result<Self> {
40        let bytes = canonical::to_canonical_cbor(body)?;
41        Ok(Self {
42            kind: kind.into(),
43            schema: schema.into(),
44            version,
45            body: CborBytes::new(bytes),
46        })
47    }
48
49    /// Decode the CBOR body to the requested type.
50    pub fn decode_body<T: serde::de::DeserializeOwned>(&self) -> canonical::Result<T> {
51        self.body.ensure_canonical()?;
52        self.body.decode::<T>()
53    }
54}