use std::ops::Deref; use minicbor::{data::Tag, Decode, Encode}; /// Utility for skipping parts of the CBOR payload, use only for debugging #[derive(Debug, PartialEq, PartialOrd, Eq, Ord)] pub struct SkipCbor {} impl<'b, const N: usize> minicbor::Decode<'b> for SkipCbor { fn decode(d: &mut minicbor::Decoder<'b>) -> Result { { let probe = d.probe(); println!("skipped cbor value {}: {:?}", N, probe.datatype()?); } d.skip()?; Ok(SkipCbor {}) } } impl minicbor::Encode for SkipCbor { fn encode( &self, _e: &mut minicbor::Encoder, ) -> Result<(), minicbor::encode::Error> { todo!() } } /// Custom collection to ensure ordered pairs of values /// /// Since the ordering of the entries requires a particular order to maintain /// canonicalization for isomorphic decoding / encoding operators, we use a Vec /// as the underlaying struct for storage of the items (as opposed to a BTreeMap /// or HashMap). #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] pub enum KeyValuePairs { Def(Vec<(K, V)>), Indef(Vec<(K, V)>), } impl Deref for KeyValuePairs { type Target = Vec<(K, V)>; fn deref(&self) -> &Self::Target { match self { KeyValuePairs::Def(x) => x, KeyValuePairs::Indef(x) => x, } } } impl<'b, K, V> minicbor::decode::Decode<'b> for KeyValuePairs where K: Encode + Decode<'b>, V: Encode + Decode<'b>, { fn decode(d: &mut minicbor::Decoder<'b>) -> Result { let datatype = d.datatype()?; let items: Result, _> = d.map_iter::()?.collect(); let items = items?; match datatype { minicbor::data::Type::Map => Ok(KeyValuePairs::Def(items)), minicbor::data::Type::MapIndef => Ok(KeyValuePairs::Indef(items)), _ => Err(minicbor::decode::Error::message( "invalid data type for keyvaluepairs", )), } } } impl minicbor::encode::Encode for KeyValuePairs where K: Encode, V: Encode, { fn encode( &self, e: &mut minicbor::Encoder, ) -> Result<(), minicbor::encode::Error> { match self { KeyValuePairs::Def(x) => { e.map(x.len() as u64)?; for (k, v) in x.iter() { k.encode(e)?; v.encode(e)?; } } KeyValuePairs::Indef(x) => { e.begin_map()?; for (k, v) in x.iter() { k.encode(e)?; v.encode(e)?; } e.end()?; } } Ok(()) } } /// A struct that maintains a reference to whether a cbor array was indef or not #[derive(Debug, PartialEq, Eq, PartialOrd, Ord)] pub enum MaybeIndefArray { Def(Vec), Indef(Vec), } impl Deref for MaybeIndefArray { type Target = Vec; fn deref(&self) -> &Self::Target { match self { MaybeIndefArray::Def(x) => x, MaybeIndefArray::Indef(x) => x, } } } impl<'b, A> minicbor::decode::Decode<'b> for MaybeIndefArray where A: minicbor::decode::Decode<'b>, { fn decode(d: &mut minicbor::Decoder<'b>) -> Result { let datatype = d.datatype()?; match datatype { minicbor::data::Type::Array => Ok(Self::Def(d.decode()?)), minicbor::data::Type::ArrayIndef => Ok(Self::Indef(d.decode()?)), _ => Err(minicbor::decode::Error::message( "unknown data type of maybe indef array", )), } } } impl minicbor::encode::Encode for MaybeIndefArray where A: minicbor::encode::Encode, { fn encode( &self, e: &mut minicbor::Encoder, ) -> Result<(), minicbor::encode::Error> { match self { MaybeIndefArray::Def(x) => { e.encode(x)?; } // TODO: this seemed necesary on alonzo, but breaks on byron. We need to double check. //MaybeIndefArray::Indef(x) if x.is_empty() => { // e.encode(x)?; //} MaybeIndefArray::Indef(x) => { e.begin_array()?; for v in x.iter() { e.encode(v)?; } e.end()?; } }; Ok(()) } } /// Order-preserving set of attributes /// /// There's no guarantee that the entries on a Cardano cbor entity that uses /// maps for its representation will follow the canonical order specified by the /// standard. To implement an isomorphic codec, we need a way of preserving the /// original order in which the entries were encoded. To acomplish this, we /// transform key-value structures into an orderer vec of `properties`, where /// each entry represents a a cbor-encodable variant of an attribute of the /// struct. #[derive(Debug, PartialEq)] pub struct OrderPreservingProperties

(Vec

); impl

Deref for OrderPreservingProperties

{ type Target = Vec

; fn deref(&self) -> &Self::Target { &self.0 } } impl<'b, P> minicbor::decode::Decode<'b> for OrderPreservingProperties

where P: Decode<'b>, { fn decode(d: &mut minicbor::Decoder<'b>) -> Result { let len = d.map()?.unwrap_or_default(); let components: Result<_, _> = (0..len).map(|_| d.decode()).collect(); Ok(Self(components?)) } } impl

minicbor::encode::Encode for OrderPreservingProperties

where P: Encode, { fn encode( &self, e: &mut minicbor::Encoder, ) -> Result<(), minicbor::encode::Error> { e.map(self.0.len() as u64)?; for component in &self.0 { e.encode(component)?; } Ok(()) } } /// Wraps a struct so that it is encoded/decoded as a cbor bytes #[derive(Debug)] pub struct CborWrap(pub T); impl<'b, T> minicbor::Decode<'b> for CborWrap where T: minicbor::Decode<'b>, { fn decode(d: &mut minicbor::Decoder<'b>) -> Result { d.tag()?; let cbor = d.bytes()?; let wrapped = minicbor::decode(cbor)?; Ok(CborWrap(wrapped)) } } impl minicbor::Encode for CborWrap where T: minicbor::Encode, { fn encode( &self, e: &mut minicbor::Encoder, ) -> Result<(), minicbor::encode::Error> { let buf = minicbor::to_vec(&self.0).map_err(|_| { minicbor::encode::Error::message("error encoding cbor-wrapped structure") })?; e.tag(Tag::Cbor)?; e.bytes(&buf)?; Ok(()) } } impl Deref for CborWrap { type Target = T; fn deref(&self) -> &Self::Target { &self.0 } } #[derive(Debug)] pub struct TagWrap(I); impl<'b, I, const T: u64> minicbor::Decode<'b> for TagWrap where I: minicbor::Decode<'b>, { fn decode(d: &mut minicbor::Decoder<'b>) -> Result { d.tag()?; Ok(TagWrap(d.decode()?)) } } impl minicbor::Encode for TagWrap where I: minicbor::Encode, { fn encode( &self, e: &mut minicbor::Encoder, ) -> Result<(), minicbor::encode::Error> { e.tag(Tag::Unassigned(T))?; e.encode(&self.0)?; Ok(()) } } /// An empty map /// /// don't ask me why, that's what the CDDL asks for. #[derive(Debug)] pub struct EmptyMap; impl<'b> minicbor::decode::Decode<'b> for EmptyMap { fn decode(d: &mut minicbor::Decoder<'b>) -> Result { d.skip()?; Ok(EmptyMap) } } impl minicbor::encode::Encode for EmptyMap { fn encode( &self, e: &mut minicbor::Encoder, ) -> Result<(), minicbor::encode::Error> { e.map(0)?; Ok(()) } } /// An array with zero or one elements /// /// A common pattern seen in the CDDL is to represent optional values as an /// array containing zero or more items. This structure reflects that pattern /// while providing semantic meaning. #[derive(Debug)] pub struct ZeroOrOneArray(Option); impl Deref for ZeroOrOneArray { type Target = Option; fn deref(&self) -> &Self::Target { &self.0 } } impl<'b, T> minicbor::decode::Decode<'b> for ZeroOrOneArray where T: Decode<'b>, { fn decode(d: &mut minicbor::Decoder<'b>) -> Result { let len = d.array()?; match len { Some(0) => Ok(ZeroOrOneArray(None)), Some(1) => Ok(ZeroOrOneArray(Some(d.decode()?))), Some(_) => Err(minicbor::decode::Error::message( "found invalid len for zero-or-one pattern", )), None => Err(minicbor::decode::Error::message( "found invalid indefinite len array for zero-or-one pattern", )), } } } impl minicbor::encode::Encode for ZeroOrOneArray where T: minicbor::Encode, { fn encode( &self, e: &mut minicbor::Encoder, ) -> Result<(), minicbor::encode::Error> { match &self.0 { Some(x) => { e.array(1)?; e.encode(x)?; } None => { e.array(0)?; } } Ok(()) } }