reth_nippy_jar/compression/
lz4.rs

1use crate::{compression::Compression, NippyJarError};
2use serde::{Deserialize, Serialize};
3
4/// Wrapper type for `lz4_flex` that implements [`Compression`].
5#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Default)]
6#[non_exhaustive]
7pub struct Lz4;
8
9impl Compression for Lz4 {
10    fn decompress_to(&self, value: &[u8], dest: &mut Vec<u8>) -> Result<(), NippyJarError> {
11        let previous_length = dest.len();
12
13        // SAFETY: We're setting len to the existing capacity.
14        unsafe {
15            dest.set_len(dest.capacity());
16        }
17
18        match lz4_flex::decompress_into(value, &mut dest[previous_length..]) {
19            Ok(written) => {
20                // SAFETY: `compress_into` can only write if there's enough capacity. Therefore, it
21                // shouldn't write more than our capacity.
22                unsafe {
23                    dest.set_len(previous_length + written);
24                }
25                Ok(())
26            }
27            Err(_) => {
28                // SAFETY: we are resetting it to the previous value.
29                unsafe {
30                    dest.set_len(previous_length);
31                }
32                Err(NippyJarError::OutputTooSmall)
33            }
34        }
35    }
36
37    fn decompress(&self, value: &[u8]) -> Result<Vec<u8>, NippyJarError> {
38        let mut multiplier = 1;
39
40        loop {
41            match lz4_flex::decompress(value, multiplier * value.len()) {
42                Ok(v) => return Ok(v),
43                Err(err) => {
44                    multiplier *= 2;
45                    if multiplier == 16 {
46                        return Err(NippyJarError::Custom(err.to_string()))
47                    }
48                }
49            }
50        }
51    }
52
53    fn compress_to(&self, src: &[u8], dest: &mut Vec<u8>) -> Result<usize, NippyJarError> {
54        let previous_length = dest.len();
55
56        // SAFETY: We're setting len to the existing capacity.
57        unsafe {
58            dest.set_len(dest.capacity());
59        }
60
61        match lz4_flex::compress_into(src, &mut dest[previous_length..]) {
62            Ok(written) => {
63                // SAFETY: `compress_into` can only write if there's enough capacity. Therefore, it
64                // shouldn't write more than our capacity.
65                unsafe {
66                    dest.set_len(previous_length + written);
67                }
68                Ok(written)
69            }
70            Err(_) => {
71                // SAFETY: we are resetting it to the previous value.
72                unsafe {
73                    dest.set_len(previous_length);
74                }
75                Err(NippyJarError::OutputTooSmall)
76            }
77        }
78    }
79
80    fn compress(&self, src: &[u8]) -> Result<Vec<u8>, NippyJarError> {
81        Ok(lz4_flex::compress(src))
82    }
83}