oxihuman_core/
compression_snappy.rs1#![allow(dead_code)]
4
5#[derive(Debug, Clone, Default)]
9pub struct SnappyConfig {
10 pub verify_checksum: bool,
11}
12
13#[derive(Debug, Clone)]
15pub struct SnappyCompressor {
16 pub config: SnappyConfig,
17}
18
19impl SnappyCompressor {
20 pub fn new(config: SnappyConfig) -> Self {
21 Self { config }
22 }
23
24 pub fn default_compressor() -> Self {
25 Self::new(SnappyConfig {
26 verify_checksum: false,
27 })
28 }
29}
30
31pub fn snappy_compress(data: &[u8]) -> Vec<u8> {
33 let mut out = Vec::with_capacity(data.len() + 4);
35 out.extend_from_slice(&(data.len() as u32).to_le_bytes());
36 out.extend_from_slice(data);
37 out
38}
39
40pub fn snappy_decompress(data: &[u8]) -> Result<Vec<u8>, String> {
42 if data.len() < 4 {
44 return Err("snappy: input too short".to_string());
45 }
46 let expected = u32::from_le_bytes(data[..4].try_into().unwrap_or_default()) as usize;
47 let payload = &data[4..];
48 if payload.len() < expected {
49 return Err("snappy: truncated payload".to_string());
50 }
51 Ok(payload[..expected].to_vec())
52}
53
54pub fn snappy_max_compressed_length(input_len: usize) -> usize {
56 32 + input_len + input_len / 6
57}
58
59pub fn snappy_validate_compressed_buffer(data: &[u8]) -> bool {
61 data.len() >= 4
62}
63
64pub fn snappy_roundtrip_ok(data: &[u8]) -> bool {
66 snappy_decompress(&snappy_compress(data))
67 .map(|d| d == data)
68 .unwrap_or(false)
69}
70
71#[cfg(test)]
72mod tests {
73 use super::*;
74
75 #[test]
76 fn test_default_config() {
77 let c = SnappyCompressor::default_compressor();
79 assert!(!c.config.verify_checksum);
80 }
81
82 #[test]
83 fn test_compress_empty() {
84 assert_eq!(snappy_compress(&[]).len(), 4);
86 }
87
88 #[test]
89 fn test_roundtrip_ascii() {
90 assert!(snappy_roundtrip_ok(b"snappy test string"));
92 }
93
94 #[test]
95 fn test_roundtrip_binary() {
96 let data: Vec<u8> = (0u8..=255).collect();
98 assert!(snappy_roundtrip_ok(&data));
99 }
100
101 #[test]
102 fn test_decompress_too_short() {
103 assert!(snappy_decompress(&[0, 1]).is_err());
105 }
106
107 #[test]
108 fn test_max_compressed_length() {
109 assert!(snappy_max_compressed_length(100) > 100);
111 }
112
113 #[test]
114 fn test_validate_valid() {
115 assert!(snappy_validate_compressed_buffer(&[0, 0, 0, 0]));
117 }
118
119 #[test]
120 fn test_validate_too_short() {
121 assert!(!snappy_validate_compressed_buffer(&[0, 0, 0]));
123 }
124
125 #[test]
126 fn test_new_config() {
127 let c = SnappyCompressor::new(SnappyConfig {
129 verify_checksum: true,
130 });
131 assert!(c.config.verify_checksum);
132 }
133}