1/*
2 * Copyright (c) 2023.
3 *
4 * This software is free software; You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license
5 */
6
7use alloc::vec;
8use alloc::vec::Vec;
9
10use crate::constants::DEFLATE_BLOCKTYPE_UNCOMPRESSED;
11
12mod fast_match_finder;
13
14const _SEQ_LENGTH_SHIFT: u32 = 23;
15
16const _SEQ_LITRUNLEN_MASK: u32 = (1_u32 << _SEQ_LENGTH_SHIFT) - 1;
17
18pub(crate) struct _Sequence
19{
20 /*
21 * Bits 0..22: the number of literals in this run. This may be 0 and
22 * can be at most MAX_BLOCK_LENGTH. The literals are not stored
23 * explicitly in this structure; instead, they are read directly from
24 * the uncompressed data.
25 *
26 * Bits 23..31: the length of the match which follows the literals, or 0
27 * if this literal run was the last in the block, so there is no match
28 * which follows it.
29 */
30 litrunlen_and_length: u32
31}
32
33#[derive(Debug, Copy, Clone)]
34pub enum DeflateEncodingStrategy
35{
36 NoCompression
37}
38
39impl DeflateEncodingStrategy
40{
41 #[allow(dead_code)]
42 fn to_level(self) -> u8
43 {
44 match self
45 {
46 Self::NoCompression => 0
47 }
48 }
49}
50
51pub struct DeflateEncodingOptions
52{
53 strategy: DeflateEncodingStrategy
54}
55
56impl Default for DeflateEncodingOptions
57{
58 fn default() -> Self
59 {
60 DeflateEncodingOptions {
61 strategy: DeflateEncodingStrategy::NoCompression
62 }
63 }
64}
65
66/// A simple Deflate Encoder.
67///
68/// Not yet complete
69pub struct DeflateEncoder<'a>
70{
71 data: &'a [u8],
72 options: DeflateEncodingOptions,
73 output_position: usize,
74 input_position: usize,
75 output: Vec<u8>
76}
77
78impl<'a> DeflateEncoder<'a>
79{
80 /// Create a new deflate encoder.
81 ///
82 /// The
83 pub fn new(data: &'a [u8]) -> DeflateEncoder<'a>
84 {
85 DeflateEncoder::new_with_options(data, DeflateEncodingOptions::default())
86 }
87 pub fn new_with_options(data: &'a [u8], options: DeflateEncodingOptions) -> DeflateEncoder<'a>
88 {
89 let length = data.len() + 1024;
90 let out_array = vec![0; length];
91
92 DeflateEncoder {
93 data,
94 options,
95 output_position: 0,
96 input_position: 0,
97 output: out_array
98 }
99 }
100
101 #[cfg(feature = "zlib")]
102 fn write_zlib_header(&mut self)
103 {
104 const ZLIB_CM_DEFLATE: u16 = 8;
105 const ZLIB_CINFO_32K_WINDOW: u16 = 7;
106
107 let level_hint = self.options.strategy.to_level();
108
109 let mut hdr = (ZLIB_CM_DEFLATE << 8) | (ZLIB_CINFO_32K_WINDOW << 12);
110
111 hdr |= u16::from(level_hint) << 6;
112 hdr |= 31 - (hdr % 31);
113
114 self.output[self.output_position..self.output_position + 2]
115 .copy_from_slice(&hdr.to_be_bytes());
116 }
117 /// Encode a deflate data block with no compression
118 ///
119 /// # Argument
120 /// - `bytes`: number of bytes to compress from input as non-compressed
121 /// bytes
122 fn encode_no_compression(&mut self, bytes: usize)
123 {
124 let final_position = self.input_position + bytes;
125
126 /*
127 * If the input is zero-length, we still must output a block in order
128 * for the output to be a valid DEFLATE stream. Handle this case
129 * specially to avoid potentially passing NULL to memcpy() below.
130 */
131 if self.data.is_empty()
132 {
133 /* BFINAL and BTYPE */
134 self.output[self.output_position] = (1 | (DEFLATE_BLOCKTYPE_UNCOMPRESSED << 1)) as u8;
135 self.output_position += 1;
136 /* LEN and NLEN */
137 let num: u32 = 0xFFFF0000;
138 self.output[self.output_position..self.output_position + 4]
139 .copy_from_slice(&num.to_le_bytes());
140 self.output_position += 4;
141 return;
142 }
143 loop
144 {
145 let mut bfinal = 0;
146 let mut len = usize::from(u16::MAX);
147
148 if final_position - self.input_position <= usize::from(u16::MAX)
149 {
150 bfinal = 1;
151 len = final_position - self.input_position;
152 }
153 /*
154 * Output BFINAL and BTYPE. The stream is already byte-aligned
155 * here, so this step always requires outputting exactly 1 byte.
156 */
157 self.output[self.output_position] =
158 (bfinal | (DEFLATE_BLOCKTYPE_UNCOMPRESSED << 1)) as u8;
159
160 self.output_position += 1;
161 // output len and nlen
162 let len_u16 = len as u16;
163
164 self.output[self.output_position..self.output_position + 2]
165 .copy_from_slice(&len_u16.to_le_bytes());
166 self.output_position += 2;
167
168 self.output[self.output_position..self.output_position + 2]
169 .copy_from_slice(&(!len_u16).to_le_bytes());
170 self.output_position += 2;
171
172 // copy from input to output
173 self.output[self.output_position..self.output_position + len]
174 .copy_from_slice(&self.data[self.input_position..self.input_position + len]);
175 self.output_position += len;
176 self.input_position += len;
177
178 if self.input_position == final_position
179 {
180 break;
181 }
182 }
183 }
184
185 /// Encode a deflate stream
186 pub fn encode_deflate(&mut self)
187 {
188 match self.options.strategy
189 {
190 DeflateEncodingStrategy::NoCompression =>
191 {
192 self.encode_no_compression(self.data.len());
193 }
194 }
195 }
196
197 #[cfg(feature = "zlib")]
198 pub fn encode_zlib(&mut self) -> Vec<u8>
199 {
200 let extra = 40 * ((self.data.len() + 41) / 40);
201 self.output = vec![0_u8; self.data.len() + extra];
202 self.write_zlib_header();
203 self.output_position = 2;
204
205 self.encode_deflate();
206
207 // add adler hash
208 let hash = crate::utils::calc_adler_hash(self.data);
209 self.output[self.output_position..self.output_position + 4]
210 .copy_from_slice(&hash.to_be_bytes());
211 self.output_position += 4;
212
213 self.output.truncate(self.output_position);
214
215 core::mem::take(&mut self.output)
216 }
217}
218