Skip to main content

facet_postcard/
raw_postcard.rs

1extern crate alloc;
2
3use alloc::{borrow::Cow, vec::Vec};
4
5use facet_core::{OpaqueSerialize, PtrConst, Shape};
6
7/// Postcard-encoded opaque payload bytes.
8///
9/// This represents bytes that are already encoded using postcard's opaque
10/// payload encoding. It can be borrowed or owned.
11#[derive(Debug, Clone)]
12pub enum RawPostcard<'a> {
13    /// Borrowed postcard payload bytes.
14    Borrowed(&'a [u8]),
15    /// Owned postcard payload bytes.
16    Owned(Vec<u8>),
17}
18
19impl<'a> RawPostcard<'a> {
20    /// Creates a borrowed raw-postcard payload.
21    pub const fn borrowed(bytes: &'a [u8]) -> Self {
22        Self::Borrowed(bytes)
23    }
24
25    /// Creates an owned raw-postcard payload.
26    pub fn owned(bytes: Vec<u8>) -> Self {
27        Self::Owned(bytes)
28    }
29
30    /// Returns the payload as a byte slice.
31    pub fn as_bytes(&self) -> &[u8] {
32        match self {
33            Self::Borrowed(bytes) => bytes,
34            Self::Owned(bytes) => bytes,
35        }
36    }
37
38    /// Converts this payload into opaque adapter serialization inputs.
39    pub fn to_opaque_serialize(&self) -> OpaqueSerialize {
40        match self {
41            Self::Borrowed(bytes) => opaque_encoded_borrowed(bytes),
42            Self::Owned(bytes) => opaque_encoded_owned(bytes),
43        }
44    }
45}
46
47impl<'a> From<&'a [u8]> for RawPostcard<'a> {
48    fn from(value: &'a [u8]) -> Self {
49        Self::Borrowed(value)
50    }
51}
52
53impl<'a> From<Vec<u8>> for RawPostcard<'a> {
54    fn from(value: Vec<u8>) -> Self {
55        Self::Owned(value)
56    }
57}
58
59impl<'a> From<Cow<'a, [u8]>> for RawPostcard<'a> {
60    fn from(value: Cow<'a, [u8]>) -> Self {
61        match value {
62            Cow::Borrowed(bytes) => Self::Borrowed(bytes),
63            Cow::Owned(bytes) => Self::Owned(bytes),
64        }
65    }
66}
67
68#[repr(transparent)]
69struct RawPostcardBorrowed<'a>(&'a [u8]);
70
71#[repr(transparent)]
72struct RawPostcardOwned(Vec<u8>);
73
74static RAW_POSTCARD_BORROWED_SHAPE: Shape =
75    Shape::builder_for_sized::<RawPostcardBorrowed<'static>>("RawPostcardBorrowed").build();
76
77static RAW_POSTCARD_OWNED_SHAPE: Shape =
78    Shape::builder_for_sized::<RawPostcardOwned>("RawPostcardOwned").build();
79
80/// Builds opaque adapter serialization inputs for borrowed postcard payload bytes.
81///
82/// This is intended for `FacetOpaqueAdapter::serialize_map` when the adapter
83/// already has borrowed postcard-encoded payload bytes and wants passthrough
84/// serialization.
85pub fn opaque_encoded_borrowed(bytes: &&[u8]) -> OpaqueSerialize {
86    OpaqueSerialize {
87        ptr: PtrConst::new((bytes as *const &[u8]).cast::<RawPostcardBorrowed<'_>>()),
88        shape: &RAW_POSTCARD_BORROWED_SHAPE,
89    }
90}
91
92/// Builds opaque adapter serialization inputs for owned postcard payload bytes.
93///
94/// This is intended for `FacetOpaqueAdapter::serialize_map` when the adapter
95/// has owned postcard-encoded payload bytes and wants passthrough serialization.
96pub fn opaque_encoded_owned(bytes: &Vec<u8>) -> OpaqueSerialize {
97    OpaqueSerialize {
98        ptr: PtrConst::new((bytes as *const Vec<u8>).cast::<RawPostcardOwned>()),
99        shape: &RAW_POSTCARD_OWNED_SHAPE,
100    }
101}
102
103pub(crate) unsafe fn try_decode_passthrough_bytes<'a>(
104    ptr: PtrConst,
105    shape: &'static Shape,
106) -> Option<&'a [u8]> {
107    if shape == &RAW_POSTCARD_BORROWED_SHAPE {
108        let borrowed: &'a RawPostcardBorrowed<'a> = unsafe { ptr.get() };
109        return Some(borrowed.0);
110    }
111    if shape == &RAW_POSTCARD_OWNED_SHAPE {
112        let owned: &'a RawPostcardOwned = unsafe { ptr.get() };
113        return Some(owned.0.as_slice());
114    }
115    None
116}