From aae7d92b44a90ad42bc946b760996b7a9062fefa Mon Sep 17 00:00:00 2001 From: Santiago Carmuega Date: Thu, 9 Nov 2023 18:22:42 -0300 Subject: [PATCH] feat(codec): add utility for untyped CBOR fragments (#327) --- pallas-codec/src/utils.rs | 80 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) diff --git a/pallas-codec/src/utils.rs b/pallas-codec/src/utils.rs index 5f088dd..c2db52e 100644 --- a/pallas-codec/src/utils.rs +++ b/pallas-codec/src/utils.rs @@ -649,6 +649,86 @@ impl minicbor::Encode for KeepRaw<'_, T> { } } +/// Struct to hold arbitrary CBOR to be processed independently +/// +/// # Examples +/// +/// ``` +/// use pallas_codec::utils::AnyCbor; +/// +/// let a = (123u16, (456u16, 789u16), 123u16); +/// let data = minicbor::to_vec(a).unwrap(); +/// +/// let (_, any, _): (u16, AnyCbor, u16) = minicbor::decode(&data).unwrap(); +/// let confirm: (u16, u16) = any.into_decode().unwrap(); +/// assert_eq!(confirm, (456u16, 789u16)); +/// ``` +#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)] +pub struct AnyCbor { + inner: Vec, +} + +impl AnyCbor { + pub fn raw_bytes(&self) -> &[u8] { + &self.inner + } + + pub fn unwrap(self) -> Vec { + self.inner + } + + pub fn from_encode(other: T) -> Self + where + T: Encode<()>, + { + let inner = minicbor::to_vec(other).unwrap(); + Self { inner } + } + + pub fn into_decode(self) -> Result + where + for<'b> T: Decode<'b, ()>, + { + minicbor::decode(&self.inner) + } +} + +impl Deref for AnyCbor { + type Target = Vec; + + fn deref(&self) -> &Self::Target { + &self.inner + } +} + +impl<'b, C> minicbor::Decode<'b, C> for AnyCbor { + fn decode( + d: &mut minicbor::Decoder<'b>, + _ctx: &mut C, + ) -> Result { + let all = d.input(); + let start = d.position(); + d.skip()?; + let end = d.position(); + + Ok(Self { + inner: Vec::from(&all[start..end]), + }) + } +} + +impl minicbor::Encode for AnyCbor { + fn encode( + &self, + e: &mut minicbor::Encoder, + _ctx: &mut C, + ) -> Result<(), minicbor::encode::Error> { + e.writer_mut() + .write_all(self.raw_bytes()) + .map_err(minicbor::encode::Error::write) + } +} + #[derive(Serialize, Deserialize, Clone, Debug)] #[serde(from = "Option::", into = "Option::")] pub enum Nullable