lzma_rs/encode/
dumbencoder.rs
1use crate::compress::{Options, UnpackedSize};
2use crate::encode::rangecoder;
3use byteorder::{LittleEndian, WriteBytesExt};
4use std::io;
5
6pub struct Encoder<'a, W>
7where
8 W: 'a + io::Write,
9{
10 rangecoder: rangecoder::RangeEncoder<'a, W>,
11 literal_probs: [[u16; 0x300]; 8],
12 is_match: [u16; 4], unpacked_size: UnpackedSize,
14}
15
16const LC: u32 = 3;
17const LP: u32 = 0;
18const PB: u32 = 2;
19
20impl<'a, W> Encoder<'a, W>
21where
22 W: io::Write,
23{
24 pub fn from_stream(stream: &'a mut W, options: &Options) -> io::Result<Self> {
25 let dict_size = 0x0080_0000;
26
27 let props = (LC + 9 * (LP + 5 * PB)) as u8;
29 lzma_info!("Properties {{ lc: {}, lp: {}, pb: {} }}", LC, LP, PB);
30 stream.write_u8(props)?;
31
32 lzma_info!("Dict size: {}", dict_size);
34 stream.write_u32::<LittleEndian>(dict_size)?;
35
36 match &options.unpacked_size {
38 UnpackedSize::WriteToHeader(unpacked_size) => {
39 let value: u64 = match unpacked_size {
40 None => {
41 lzma_info!("Unpacked size: unknown");
42 0xFFFF_FFFF_FFFF_FFFF
43 }
44 Some(x) => {
45 lzma_info!("Unpacked size: {}", x);
46 *x
47 }
48 };
49 stream.write_u64::<LittleEndian>(value)?;
50 }
51 UnpackedSize::SkipWritingToHeader => {}
52 };
53
54 let encoder = Encoder {
55 rangecoder: rangecoder::RangeEncoder::new(stream),
56 literal_probs: [[0x400; 0x300]; 8],
57 is_match: [0x400; 4],
58 unpacked_size: options.unpacked_size,
59 };
60
61 Ok(encoder)
62 }
63
64 pub fn process<R>(mut self, input: R) -> io::Result<()>
65 where
66 R: io::Read,
67 {
68 let mut prev_byte = 0u8;
69 let mut input_len = 0;
70
71 for (out_len, byte_result) in input.bytes().enumerate() {
72 let byte = byte_result?;
73 let pos_state = out_len & 3;
74 input_len = out_len;
75
76 self.rangecoder
78 .encode_bit(&mut self.is_match[pos_state], false)?;
79
80 self.encode_literal(byte, prev_byte)?;
81 prev_byte = byte;
82 }
83
84 self.finish(input_len + 1)
85 }
86
87 fn finish(&mut self, input_len: usize) -> io::Result<()> {
88 match self.unpacked_size {
89 UnpackedSize::SkipWritingToHeader | UnpackedSize::WriteToHeader(Some(_)) => {}
90 UnpackedSize::WriteToHeader(None) => {
91 let pos_state = input_len & 3;
93
94 self.rangecoder
96 .encode_bit(&mut self.is_match[pos_state], true)?;
97 self.rangecoder.encode_bit(&mut 0x400, false)?;
99
100 for _ in 0..4 {
102 self.rangecoder.encode_bit(&mut 0x400, false)?;
103 }
104
105 for _ in 0..6 {
108 self.rangecoder.encode_bit(&mut 0x400, true)?;
109 }
110 for _ in 0..30 {
115 self.rangecoder.encode_bit(&mut 0x400, true)?;
116 }
117 }
119 }
120
121 self.rangecoder.finish()
123 }
124
125 fn encode_literal(&mut self, byte: u8, prev_byte: u8) -> io::Result<()> {
126 let prev_byte = prev_byte as usize;
127
128 let mut result: usize = 1;
129 let lit_state = prev_byte >> 5;
130 let probs = &mut self.literal_probs[lit_state];
131
132 for i in 0..8 {
133 let bit = ((byte >> (7 - i)) & 1) != 0;
134 self.rangecoder.encode_bit(&mut probs[result], bit)?;
135 result = (result << 1) ^ (bit as usize);
136 }
137
138 Ok(())
139 }
140}