engine/snapshot/compression/
decoder.rs

1// Copyright 2020-2021 IOTA Stiftung
2// SPDX-License-Identifier: Apache-2.0
3
4use thiserror::Error as DeriveError;
5
6#[derive(Debug, DeriveError)]
7#[error("Lz4 Decode Failed: {0}")]
8pub struct Lz4DecodeError(String);
9
10/// Public function to decompress some data into an output.
11pub fn decompress_into(input: &[u8], output: &mut Vec<u8>) -> Result<(), Lz4DecodeError> {
12    Lz4Decoder {
13        input,
14        output,
15        token: 0,
16    }
17    .complete()?;
18
19    Ok(())
20}
21
22/// Decompress data using an LZ4 Algorithm.
23pub fn decompress(input: &[u8]) -> Result<Vec<u8>, Lz4DecodeError> {
24    let mut vec = Vec::with_capacity(4096);
25
26    decompress_into(input, &mut vec)?;
27
28    Ok(vec)
29}
30
31/// Lz4Decoder implementation.
32struct Lz4Decoder<'a> {
33    input: &'a [u8],
34    output: &'a mut Vec<u8>,
35    token: u8,
36}
37
38impl<'a> Lz4Decoder<'a> {
39    fn take(&mut self, size: usize) -> Result<&[u8], Lz4DecodeError> {
40        Self::take_internal(&mut self.input, size)
41    }
42
43    #[inline]
44    fn take_internal(input: &mut &'a [u8], size: usize) -> Result<&'a [u8], Lz4DecodeError> {
45        if input.len() < size {
46            Err(Lz4DecodeError("Unexpected End".into()))
47        } else {
48            let res = Ok(&input[..size]);
49
50            *input = &input[size..];
51
52            res
53        }
54    }
55
56    fn output(output: &mut Vec<u8>, buf: &[u8]) {
57        output.extend_from_slice(&buf[..buf.len()]);
58    }
59
60    fn duplicate(&mut self, start: usize, length: usize) {
61        for i in start..start + length {
62            let b = self.output[i];
63            self.output.push(b);
64        }
65    }
66
67    #[inline]
68    fn read_int(&mut self) -> Result<usize, Lz4DecodeError> {
69        let mut size = 0;
70
71        loop {
72            let extra = self.take(1)?[0];
73            size += extra as usize;
74
75            if extra != 0xFF {
76                break;
77            }
78        }
79
80        Ok(size)
81    }
82
83    fn read_u16(&mut self) -> Result<u16, Lz4DecodeError> {
84        let bytes = self.take(2)?.try_into().expect("Conversion can never fail.");
85        Ok(u16::from_le_bytes(bytes))
86    }
87
88    fn read_literal(&mut self) -> Result<(), Lz4DecodeError> {
89        let mut literal = (self.token >> 4) as usize;
90
91        if literal == 15 {
92            literal += self.read_int()?;
93        }
94
95        Self::output(self.output, Self::take_internal(&mut self.input, literal)?);
96
97        Ok(())
98    }
99
100    fn read_duplicate(&mut self) -> Result<(), Lz4DecodeError> {
101        let offset = self.read_u16()?;
102
103        let mut length = (4 + (self.token & 0xF)) as usize;
104
105        if length == 4 + 15 {
106            length += self.read_int()?;
107        }
108
109        let start = self.output.len().wrapping_sub(offset as usize);
110
111        if start < self.output.len() {
112            self.duplicate(start, length);
113
114            Ok(())
115        } else {
116            Err(Lz4DecodeError("Invalid Duplicate".into()))
117        }
118    }
119
120    #[inline]
121    fn complete(&mut self) -> Result<(), Lz4DecodeError> {
122        while !self.input.is_empty() {
123            self.token = self.take(1)?[0];
124
125            self.read_literal()?;
126
127            if self.input.is_empty() {
128                break;
129            }
130
131            self.read_duplicate()?;
132        }
133
134        Ok(())
135    }
136}