1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
//! # Arcode
//! An arithmetic coder for Rust.
//!
//!
//! [](https://crates.io/crates/arcode)
//! [](https://crates.io/crates/arcode)
//! [](https://crates.io/crates/arcode)
//!
//! ## About
//!
//! This crate provides the an efficient implementation of
//! an [arithmetic encoder/decoder](https://en.wikipedia.org/wiki/Arithmetic_coding). This crate is based off the paper
//! that describes arithmetic coding found [here](https://web.stanford.edu/class/ee398a/handouts/papers/WittenACM87ArithmCoding.pdf).
//! This implementation features many readability and performance improvements,
//! especially on the decoding side.
//!
//! The goal of this project is not to provide an out-of-the-box compression
//! solution. Arithmetic coding ([entropy encoding](https://en.wikipedia.org/wiki/Entropy_encoding)) is the backbone of almost every
//! modern day compression scheme. This crate is meant to be included in future
//! projects that rely on an efficient entropy coder e.g. [PPM](https://en.wikipedia.org/wiki/Prediction_by_partial_matching), [LZ77/LZ78](https://en.wikipedia.org/wiki/LZ77_and_LZ78),
//! [h265/HEVC](https://en.wikipedia.org/wiki/High_Efficiency_Video_Coding).
//!
//! ## Core components
//!
//! There are a lot of structs available for use but for the average user there
//! are only a few that will be used.
//! - [`Model`] models of the probability of symbols. Counts can be adjusted
//! as encoding is done to improve compression.
//! - [`Encoder`](ArithmeticEncoder) encodes symbols given a source model and a
//! symbol.
//! - ['Decoder'](ArithmeticDecoder) decodes symbols given a source model and a
//! bitstream.
//!
//! # Examples
//! In the git repository there is an [old_complex.rs](https://github.com/cgburgess/arcode-rs/blob/master/example/example.rs)
//! file that does context switching on a per character basis. A simpler example can be found at [new_simple.rs](https://github.com/cgburgess/arcode-rs/blob/master/tests/integration_test.rs)
//!
//! ## Input and output bitstreams
//! In order for arithmetic coding to work streams need to be read a bit at a
//! time (for decoding and for the encoders output). Because of this, [BitBit](https://docs.rs/bitbit) is required. **Wrapping whatever your input is in a buffered reader/writer
//! should greatly improve performance.**
//!
//! Using bitbit to create an input stream.
//! ```rust
//! use std::io::Cursor;
//!
//! use arcode::bitbit::{BitReader, BitWriter, MSB};
//!
//! fn read_example() {
//! // normally you would have a Read type with a BufReader
//! let mut source = Cursor::new(vec![0u8; 4]);
//! let input: BitReader<_, MSB> = BitReader::new(&mut source);
//! }
//!
//! fn out_example() {
//! // once again would be Write type with a BufWriter
//! let compressed = Cursor::new(vec![]);
//! let mut compressed_writer = BitWriter::new(compressed);
//! }
//! ```
//!
//! ### Source Model(s)
//! Depending on your application you could have one or many source models.
//! The source model is relied on by the encoder and the decoder. If the decoder
//! ever becomes out of phase with the encoder you will be decoding nonsense.
//!
//! #### Model Builder
//! In order to make a source model you need to use the [`model::Builder`]
//! struct.
//!
//! ```rust
//! use arcode::{EOFKind, Model};
//!
//! fn source_model_example() {
//! // create a new model that has symbols 0-256
//! // 8 bit values + one EOF marker
//! let mut model_with_eof = Model::builder()
//! .num_symbols(256)
//! .eof(EOFKind::EndAddOne)
//! .build();
//!
//! // model for 8 bit 0 - 255, if we arent using
//! // the EOF flag we can set it to NONE or let it default
//! // to none as in the second example below.
//! let model_without_eof = Model::builder().num_symbols(256).eof(EOFKind::None).build();
//! let model_without_eof = Model::builder().num_symbols(256).build();
//!
//! // we can also create a model for 0-255 using num_bits
//! let model_8_bit = Model::builder().num_bits(8).build();
//!
//! // update the probability of symbol 4.
//! model_with_eof.update_symbol(4);
//! }
//! ```
//! ## Encode
//! Encoding some simple input
//! ```rust
//! use std::io::{Cursor, Result};
//!
//! use arcode::{bitbit::BitWriter, ArithmeticEncoder, EOFKind, Model};
//!
//! /// Encodes bytes and returns the compressed form
//! fn encode(data: &[u8]) -> Result<Vec<u8>> {
//! let mut model = Model::builder().num_bits(8).eof(EOFKind::EndAddOne).build();
//!
//! // make a stream to collect the compressed data
//! let compressed = Cursor::new(vec![]);
//! let mut compressed_writer = BitWriter::new(compressed);
//!
//! let mut encoder = ArithmeticEncoder::new(48);
//!
//! for &sym in data {
//! encoder.encode(sym as u32, &model, &mut compressed_writer)?;
//! model.update_symbol(sym as u32);
//! }
//!
//! encoder.encode(model.eof(), &model, &mut compressed_writer)?;
//! encoder.finish_encode(&mut compressed_writer)?;
//! compressed_writer.pad_to_byte()?;
//!
//! // retrieves the bytes from the writer. This will
//! // be cleaner when bitbit updates. Not necessary if
//! // using files or a stream
//! Ok(compressed_writer.get_ref().get_ref().clone())
//! }
//! ```
//! ### Decode
//! ```rust
//! use std::io::{Cursor, Result};
//!
//! use arcode::{
//! bitbit::{BitReader, MSB},
//! ArithmeticDecoder, EOFKind, Model,
//! };
//!
//! /// Decompresses the data
//! fn decode(data: &[u8]) -> Result<Vec<u8>> {
//! let mut model = Model::builder().num_bits(8).eof(EOFKind::EndAddOne).build();
//!
//! let mut input_reader = BitReader::<_, MSB>::new(data);
//! let mut decoder = ArithmeticDecoder::new(48);
//! let mut decompressed_data = vec![];
//!
//! while !decoder.finished() {
//! let sym = decoder.decode(&model, &mut input_reader)?;
//! model.update_symbol(sym);
//! decompressed_data.push(sym as u8);
//! }
//!
//! decompressed_data.pop(); // remove the EOF
//!
//! Ok(decompressed_data)
//! }
//! ```
pub use bitbit;
pub use ArithmeticDecoder;
pub use ArithmeticEncoder;
pub use ;
pub use Range;