zune_inflate/
encoder.rs

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}