density_rs/algorithms/chameleon/
chameleon.rs1use crate::algorithms::PLAIN_FLAG;
2use crate::codec::codec::Codec;
3use crate::codec::decoder::Decoder;
4use crate::codec::quad_encoder::QuadEncoder;
5use crate::errors::decode_error::DecodeError;
6use crate::errors::encode_error::EncodeError;
7use crate::io::read_buffer::ReadBuffer;
8use crate::io::read_signature::ReadSignature;
9use crate::io::write_buffer::WriteBuffer;
10use crate::io::write_signature::WriteSignature;
11use crate::{BIT_SIZE_U16, BIT_SIZE_U32, BYTE_SIZE_U32};
12use std::slice::{from_raw_parts, from_raw_parts_mut};
13
14pub(crate) const CHAMELEON_HASH_BITS: usize = BIT_SIZE_U16;
15pub(crate) const CHAMELEON_HASH_MULTIPLIER: u32 = 0x9D6EF916;
16
17pub(crate) const FLAG_SIZE_BITS: u8 = 1;
18pub(crate) const MAP_FLAG: u64 = 0x1;
19
20pub(crate) const PLAIN_PLAIN_FLAGS: u64 = (PLAIN_FLAG << 1) | PLAIN_FLAG;
21pub(crate) const MAP_PLAIN_FLAGS: u64 = (PLAIN_FLAG << 1) | MAP_FLAG;
22pub(crate) const PLAIN_MAP_FLAGS: u64 = (MAP_FLAG << 1) | PLAIN_FLAG;
23pub(crate) const DECODE_TWIN_FLAG_MASK: u64 = 0x3;
26pub(crate) const DECODE_TWIN_FLAG_MASK_BITS: u8 = 2;
27pub(crate) const DECODE_FLAG_MASK: u64 = 0x1;
28pub(crate) const DECODE_FLAG_MASK_BITS: u8 = 1;
29
30pub struct State {
31 pub(crate) chunk_map: Vec<u32>,
32}
33
34pub struct Chameleon {
35 pub state: State,
36}
37
38impl Chameleon {
39 pub fn new() -> Self {
40 Chameleon {
41 state: State { chunk_map: vec![0; 1 << CHAMELEON_HASH_BITS] },
42 }
43 }
44
45 pub fn encode(input: &[u8], output: &mut [u8]) -> Result<usize, EncodeError> {
46 let mut chameleon = Chameleon::new();
47 chameleon.encode(input, output)
48 }
49
50 pub fn decode(input: &[u8], output: &mut [u8]) -> Result<usize, DecodeError> {
51 let mut chameleon = Chameleon::new();
52 chameleon.decode(input, output)
53 }
54
55 #[inline(always)]
56 fn decode_plain(&mut self, in_buffer: &mut ReadBuffer) -> u32 {
57 let quad = in_buffer.read_u32_le();
58 let hash = (quad.wrapping_mul(CHAMELEON_HASH_MULTIPLIER) >> (BIT_SIZE_U32 - CHAMELEON_HASH_BITS)) as u16;
59 self.state.chunk_map[hash as usize] = quad;
60 quad
61 }
62
63 #[inline(always)]
64 fn decode_map(&mut self, in_buffer: &mut ReadBuffer) -> u32 {
65 let hash = in_buffer.read_u16_le();
66 let quad = self.state.chunk_map[hash as usize];
67 quad
68 }
69
70 #[unsafe(no_mangle)]
71 pub extern "C" fn chameleon_encode(input: *const u8, input_size: usize, output: *mut u8, output_size: usize) -> usize {
72 unsafe { Self::encode(from_raw_parts(input, input_size), from_raw_parts_mut(output, output_size)).unwrap_or(0) }
73 }
74
75 #[unsafe(no_mangle)]
76 pub extern "C" fn chameleon_decode(input: *const u8, input_size: usize, output: *mut u8, output_size: usize) -> usize {
77 unsafe { Self::decode(from_raw_parts(input, input_size), from_raw_parts_mut(output, output_size)).unwrap_or(0) }
78 }
79
80 #[unsafe(no_mangle)]
81 pub extern "C" fn chameleon_safe_encode_buffer_size(size: usize) -> usize {
82 Self::safe_encode_buffer_size(size)
83 }
84}
85
86impl QuadEncoder for Chameleon {
87 #[inline(always)]
88 fn encode_quad(&mut self, quad: u32, out_buffer: &mut WriteBuffer, signature: &mut WriteSignature) {
89 let hash_u16 = (quad.wrapping_mul(CHAMELEON_HASH_MULTIPLIER) >> (BIT_SIZE_U32 - CHAMELEON_HASH_BITS)) as u16;
90 let dictionary_value = &mut self.state.chunk_map[hash_u16 as usize];
91 if *dictionary_value != quad {
92 signature.push_bits(PLAIN_FLAG, FLAG_SIZE_BITS);
93 out_buffer.push(&quad.to_le_bytes());
94
95 *dictionary_value = quad;
96 } else {
97 signature.push_bits(MAP_FLAG, FLAG_SIZE_BITS);
98 out_buffer.push(&hash_u16.to_le_bytes());
99 }
100 }
101}
102
103impl Decoder for Chameleon {
104 #[inline(always)]
105 fn decode_unit(&mut self, in_buffer: &mut ReadBuffer, signature: &mut ReadSignature, out_buffer: &mut WriteBuffer) {
106 let (quad_a, quad_b) = match signature.read_bits(DECODE_TWIN_FLAG_MASK, DECODE_TWIN_FLAG_MASK_BITS) {
107 PLAIN_PLAIN_FLAGS => { (self.decode_plain(in_buffer), self.decode_plain(in_buffer)) }
108 MAP_PLAIN_FLAGS => { (self.decode_map(in_buffer), self.decode_plain(in_buffer)) }
109 PLAIN_MAP_FLAGS => { (self.decode_plain(in_buffer), self.decode_map(in_buffer)) }
110 _ => { (self.decode_map(in_buffer), self.decode_map(in_buffer)) }
111 };
112 out_buffer.push(&quad_a.to_le_bytes());
113 out_buffer.push(&quad_b.to_le_bytes());
114 }
115
116 #[inline(always)]
117 fn decode_partial_unit(&mut self, in_buffer: &mut ReadBuffer, signature: &mut ReadSignature, out_buffer: &mut WriteBuffer) -> bool {
118 for _ in 0..Self::decode_unit_size() / BYTE_SIZE_U32 {
119 let quad = match signature.read_bits(DECODE_FLAG_MASK, DECODE_FLAG_MASK_BITS) {
120 PLAIN_FLAG => {
121 match in_buffer.remaining() {
122 0 => { return true; }
123 1..=3 => {
124 out_buffer.push(in_buffer.read(in_buffer.remaining()));
125 return true;
126 }
127 _ => { self.decode_plain(in_buffer) }
128 }
129 }
130 _ => { self.decode_map(in_buffer) }
131 };
132 out_buffer.push(&quad.to_le_bytes());
133 }
134 false
135 }
136}
137
138impl Codec for Chameleon {
139 #[inline(always)]
140 fn block_size() -> usize { BYTE_SIZE_U32 * (Self::signature_significant_bytes() << 3) }
141
142 #[inline(always)]
143 fn decode_unit_size() -> usize { 8 }
144
145 #[inline(always)]
146 fn signature_significant_bytes() -> usize { 8 }
147
148 fn clear_state(&mut self) {
149 self.state.chunk_map.fill(0);
150 }
151}