encoder/
encoder.rs

1// SPDX-License-Identifier: CC0-1.0
2
3//! Example of creating an encoder that encodes a slice of encodable objects.
4
5use bitcoin_consensus_encoding as encoding;
6use encoding::{ArrayEncoder, BytesEncoder, CompactSizeEncoder, Encodable, Encoder2, SliceEncoder};
7
8fn main() {
9    let v = vec![Inner::new(0xcafe_babe), Inner::new(0xdead_beef)];
10    let b = vec![0xab, 0xcd];
11
12    let adt = Adt::new(v, b);
13    let encoded = encoding::encode_to_vec(&adt);
14
15    let want = [0x02, 0xca, 0xfe, 0xba, 0xbe, 0xde, 0xad, 0xbe, 0xef, 0xab, 0xcd];
16    assert_eq!(encoded, want);
17}
18
19/// Some abstract data type.
20struct Adt {
21    v: Vec<Inner>,
22    b: Vec<u8>,
23}
24
25impl Adt {
26    /// Constructs a new `Adt`.
27    pub fn new(v: Vec<Inner>, b: Vec<u8>) -> Self { Self { v, b } }
28}
29
30encoding::encoder_newtype! {
31    /// The encoder for the [`Adt`] type.
32    pub struct AdtEncoder<'e>(Encoder2<Encoder2<CompactSizeEncoder, SliceEncoder<'e, Inner>>, BytesEncoder<'e>>);
33}
34
35impl Encodable for Adt {
36    type Encoder<'a>
37        = AdtEncoder<'a>
38    where
39        Self: 'a;
40
41    fn encoder(&self) -> Self::Encoder<'_> {
42        let a = Encoder2::new(
43            CompactSizeEncoder::new(self.v.len()),
44            SliceEncoder::without_length_prefix(&self.v),
45        );
46        let b = BytesEncoder::without_length_prefix(self.b.as_ref());
47
48        AdtEncoder(Encoder2::new(a, b))
49    }
50}
51
52/// A simple data type to use as list item.
53#[derive(Debug, Default, Clone)]
54pub struct Inner(u32);
55
56impl Inner {
57    /// Constructs a new `Inner`.
58    pub fn new(x: u32) -> Self { Self(x) }
59
60    /// Returns some meaningful 4 byte array for this type.
61    pub fn to_array(&self) -> [u8; 4] { self.0.to_be_bytes() }
62}
63
64encoding::encoder_newtype! {
65    /// The encoder for the [`Inner`] type.
66    pub struct InnerEncoder(ArrayEncoder<4>);
67}
68
69impl Encodable for Inner {
70    type Encoder<'e> = InnerEncoder;
71    fn encoder(&self) -> Self::Encoder<'_> {
72        InnerEncoder(ArrayEncoder::without_length_prefix(self.to_array()))
73    }
74}