1pub mod flat;
3
4pub use minicbor;
6
7pub mod utils;
9
10pub trait Fragment: Sized + for<'b> minicbor::Decode<'b, ()> + minicbor::Encode<()> {}
11
12impl<T> Fragment for T where T: for<'b> minicbor::Decode<'b, ()> + minicbor::Encode<()> + Sized {}
13
14#[macro_export]
15macro_rules! codec_by_datatype {
16 (
17 $enum_name:ident $( < $lifetime:lifetime > )?,
18 $( $( $cbortype:ident )|* => $one_f:ident ),*,
19 ($( $( $vars:ident ),+ => $many_f:ident )?)
20 ) => {
21 impl<$( $lifetime, )? '__b $(:$lifetime)?, C> minicbor::decode::Decode<'__b, C> for $enum_name $(<$lifetime>)? {
22 fn decode(d: &mut minicbor::Decoder<'__b>, ctx: &mut C) -> Result<Self, minicbor::decode::Error> {
23 match d.datatype()? {
24 $( minicbor::data::Type::Array => {
25 d.array()?;
26 Ok($enum_name::$many_f($({ let $vars = d.decode_with(ctx)?; $vars }, )+ ))
28 }, )?
29 $( $( minicbor::data::Type::$cbortype )|* => Ok($enum_name::$one_f(d.decode_with(ctx)?)), )*
30 _ => Err(minicbor::decode::Error::message(
31 "Unknown cbor data type for this macro-defined enum.")
32 ),
33 }
34 }
35 }
36
37 impl< $( $lifetime, )? C> minicbor::encode::Encode<C> for $enum_name $(<$lifetime>)? {
38 fn encode<W: minicbor::encode::Write>(
39 &self,
40 e: &mut minicbor::Encoder<W>,
41 ctx: &mut C,
42 ) -> Result<(), minicbor::encode::Error<W::Error>> {
43 match self {
44 $( $enum_name::$many_f ($( $vars ),+) => {
45 let length: u64 = 0 $(+ { let _ = $vars; 1 })+;
47 e.array(length)?;
48 $( e.encode_with($vars, ctx)?; )+
49 }, )?
50 $( $enum_name::$one_f(__x666) => {
51 e.encode_with(__x666, ctx)?;
52 } )*
53 };
54
55 Ok(())
56 }
57 }
58 }
59}
60
61#[cfg(test)]
62mod tests {
63 use super::minicbor::{self, decode, encode, Decode, Encode};
64
65 #[derive(Clone, Debug)]
66 enum Thing {
67 Coin(u32),
68 Change(bool),
69 Multiasset(bool, u64, i32),
70 }
71
72 codec_by_datatype! {
73 Thing,
74 U8 | U16 | U32 => Coin,
75 Bool => Change,
76 (b, u, i => Multiasset)
77 }
78
79 #[cfg(test)]
80 pub fn roundtrip_codec<T: Encode<()> + for<'a> Decode<'a, ()> + std::fmt::Debug>(
81 query: T,
82 ) -> () {
83 let mut cbor = Vec::new();
84 match encode(query, &mut cbor) {
85 Ok(_) => (),
86 Err(err) => panic!("Unable to encode data ({:?})", err),
87 };
88 println!("{:-<70}\nResulting CBOR: {:02x?}", "", cbor);
89
90 let query: T = decode(&cbor).unwrap();
91 println!("Decoded data: {:?}", query);
92 }
93
94 #[test]
95 fn roundtrip_codec_by_datatype() {
96 roundtrip_codec(Thing::Coin(0xfafa));
97 roundtrip_codec(Thing::Change(false));
98 roundtrip_codec(Thing::Multiasset(true, 10, -20));
99 }
100}