fuel_block_committer_encoding/bundle/
decoder.rs

1use std::{io::Read, marker::PhantomData};
2
3use anyhow::Context;
4use flate2::read::GzDecoder;
5
6use crate::bundle::BundleV1;
7
8#[derive(Clone, Debug, Default)]
9pub struct Decoder {
10    private: PhantomData<()>,
11}
12
13impl Decoder {
14    pub fn decode(&self, data: &[u8]) -> anyhow::Result<super::Bundle> {
15        if data.len() < 2 {
16            anyhow::bail!("Bundle data too short to contain version");
17        }
18        let version = u16::from_be_bytes([data[0], data[1]]);
19        if version != 1 {
20            anyhow::bail!("Unsupported bundle version: {version}");
21        }
22
23        let data = Self::decompress(&data[2..])
24            .with_context(|| "failed to decompress BundleV1 contents")?;
25
26        let blocks: BundleV1 = postcard::from_bytes(&data)
27            .with_context(|| "failed to postcard decode decompressed contents of BundleV1")?;
28
29        Ok(super::Bundle::V1(blocks))
30    }
31
32    fn decompress(data: &[u8]) -> anyhow::Result<Vec<u8>> {
33        let mut decoder = GzDecoder::new(data);
34
35        let mut buf = vec![];
36        decoder.read_to_end(&mut buf)?;
37
38        Ok(buf)
39    }
40}
41
42#[cfg(test)]
43mod tests {
44    use crate::bundle::{Bundle, BundleV1, Encoder};
45
46    #[test]
47    fn complains_about_unsupported_version() {
48        // given
49        let encoder = Encoder::default();
50        let mut encoded_bundle = encoder
51            .encode(Bundle::V1(BundleV1 { blocks: vec![] }))
52            .unwrap();
53        encoded_bundle[..2].copy_from_slice(&5u16.to_be_bytes());
54        let decoder = super::Decoder::default();
55
56        // when
57        let err = decoder.decode(&encoded_bundle).unwrap_err();
58
59        // then
60        let expected = "Unsupported bundle version: 5";
61        assert_eq!(err.to_string(), expected);
62    }
63
64    #[test]
65    fn complains_about_not_enough_data() {
66        // given
67        let decoder = super::Decoder::default();
68
69        // when
70        let err = decoder.decode(&[1]).unwrap_err();
71
72        // then
73        assert_eq!(err.to_string(), "Bundle data too short to contain version");
74    }
75}