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
//! Traits and functions for encoding and decoding (slices of) //! positive integers using Fibonacci Coding. //! //! Fibonacci coding is a method for representing a continuous stream //! of (positive) integers using a variable number of bits -- e.g., //! instead of taking up 2*32 bits for storing two `u32` words, these //! words will take up however many bits their fibonacci-encoded //! representation takes up. //! //! Fibonacci coding yields better results for smaller numbers than //! larger ones: The largest 32-bit words can take up to 47 bits, but //! to encode the number `1`, you only need 2 bits. //! //! Fibonacci coding is self-synchronizing: If a single bit is //! altered, a single number could be decoded as two (or two numbers //! decoded as one), but the remaining numbers will be read correctly. //! //! ## Value range //! //! Fibonacci coding can represent any number that can be expressed as //! addition of one or more Fibonacci numbers, so any integer greater //! than 1, up to the range of the given machine integer type. This //! means that the integer zero can not be encoded. //! //! If you should need to encode `0`, it is advisable to encode //! numbers incremented by one (preventing overflow by upgrading to //! the next-biggest integer type, or by not encoding the maximum //! value), and to subtract one from the decoded result. //! . //! //! # Examples //! //! ## Encoding a slice of numbers: //! ``` rust //! use fibonacci_codec::Encode; //! //! let numbers: Vec<u16> = vec![1, 50, 3003]; //! let encoded = &numbers.fib_encode().unwrap(); //! // code words: "11" (1), "001001011" (50), "000010010000100011" (3003) //! // These encoded words take up 4 bytes instead of 6 (3*16 bits)! //! assert_eq!(encoded.to_bytes(), [0b11001001, 0b01100001, 0b00100001, 0b00011000]); //! ``` //! //! ## Encoding the value zero: //! ``` rust //! use fibonacci_codec::Encode; //! //! let numbers: Vec<u16> = vec![0, 49, 3002]; //! let adjusted: Vec<u32> = numbers.iter().map(|n| *n as u32 + 1).collect(); //! let encoded = &adjusted.fib_encode().unwrap(); //! // code words: "11" (1), "001001011" (50), "000010010000100011" (3003) //! // These encoded words take up 4 bytes instead of 6 (3*16 bits)! //! assert_eq!(encoded.to_bytes(), [0b11001001, 0b01100001, 0b00100001, 0b00011000]); //! ``` //! //! # References: //! * [Wikipedia](https://en.wikipedia.org/wiki/Fibonacci_coding) //! * [Fraenkel, Aviezri S.; Klein, Shmuel T. (1996). "Robust universal complete codes for transmission and compression"](http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.37.3064) #[macro_use] extern crate failure_derive; // Macros need to be defined first: mod macros; mod decode; mod encode; pub mod int { include!(concat!(env!("OUT_DIR"), "/int.rs")); } pub use crate::decode::DecodeError; pub use crate::encode::*; pub use crate::int::funcs::*;