Skip to main content

greentic_types/
cbor_bytes.rs

1//! Lightweight wrappers around CBOR payloads and optional blobs.
2use alloc::{string::String, vec::Vec};
3use serde::{Deserialize, Serialize, de::DeserializeOwned};
4
5use crate::cbor::canonical;
6#[cfg(feature = "serde")]
7use serde_bytes::ByteBuf;
8
9/// A canonical CBOR byte buffer that can be re-validated or decoded.
10#[derive(Clone, Debug, PartialEq, Eq)]
11pub struct CborBytes(pub Vec<u8>);
12
13impl CborBytes {
14    /// Wrap an existing buffer.
15    pub fn new(bytes: Vec<u8>) -> Self {
16        Self(bytes)
17    }
18
19    /// Access the raw bytes.
20    pub fn as_slice(&self) -> &[u8] {
21        &self.0
22    }
23
24    /// Consume this wrapper and return the owned bytes.
25    pub fn into_vec(self) -> Vec<u8> {
26        self.0
27    }
28
29    /// Ensure the payload follows canonical CBOR rules.
30    pub fn ensure_canonical(&self) -> canonical::Result<()> {
31        canonical::ensure_canonical(&self.0)
32    }
33
34    /// Re-encode the payload in canonical form.
35    pub fn canonicalize(self) -> canonical::Result<Self> {
36        canonical::canonicalize(&self.0).map(Self)
37    }
38
39    /// Deserialize the payload into `T`.
40    pub fn decode<T: DeserializeOwned>(&self) -> canonical::Result<T> {
41        canonical::from_cbor(&self.0)
42    }
43}
44
45impl From<Vec<u8>> for CborBytes {
46    fn from(bytes: Vec<u8>) -> Self {
47        Self(bytes)
48    }
49}
50
51impl From<CborBytes> for Vec<u8> {
52    fn from(cbor: CborBytes) -> Self {
53        cbor.0
54    }
55}
56
57#[cfg(feature = "serde")]
58impl Serialize for CborBytes {
59    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
60    where
61        S: serde::Serializer,
62    {
63        serializer.serialize_bytes(&self.0)
64    }
65}
66
67#[cfg(feature = "serde")]
68impl<'de> Deserialize<'de> for CborBytes {
69    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
70    where
71        D: serde::Deserializer<'de>,
72    {
73        let bytes = ByteBuf::deserialize(deserializer)?;
74        Ok(CborBytes(bytes.into_vec()))
75    }
76}
77
78/// Optional tuple for passing content type plus canonical CBOR.
79#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
80#[derive(Clone, Debug, PartialEq, Eq)]
81pub struct Blob {
82    /// MIME type describing the payload.
83    pub content_type: String,
84    /// Raw CBOR payload bytes.
85    pub bytes: Vec<u8>,
86}
87
88impl Blob {
89    /// Build a blob with the supplied content type header.
90    pub fn new(content_type: impl Into<String>, bytes: Vec<u8>) -> Self {
91        Self {
92            content_type: content_type.into(),
93            bytes,
94        }
95    }
96}