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
//! Variable length signed and unsigned integer types. //! Types support up to 128-bit integers and encoded to 1-17 bytes. //! //! Encoding rules are based on [SQLite 4 Varuint type](https://!sqlite.org/src4/doc/trunk/www/varint.wiki) //! with modifications for support of 128-bit long integers. //! Varint is encoded using the [Protobuf ZigZag approach](https://!developers.google.com/protocol-buffers/docs/encoding#signed-integers) //! and reuses `Varuint` as a storage. //! //! Unlike the Protobuf encoding rules `Varuint` needs the first byte only to find out the length of the //! whole value. Microbenchmarks say that it is a lot faster. //! //! ## How to use //! //! Add dependency to your Cargo.toml: //! //! ```cargo //! [dependencies] //! varuint = "0.4" //! ``` //! //! Add imports to your code: //! //! ```rust,no_run //! //! use varuint::{Varint, Varuint, Serializable, Deserializable}; //! ``` //! //! Use it: //! //! ```rust,no_run //! use std::mem; //! use std::io::Read; //! //! use varuint::*; //! //! fn test_varint(v: i128, size: usize) { //! let v = Varint(v); //! assert_eq!(size, v.size_hint()); //! let mut arr: [u8; 17] = unsafe { mem::uninitialized() }; //! { //! let mut buf = &mut arr as &mut [u8]; //! assert_eq!(size, v.serialize(&mut buf).unwrap()); //! } //! let mut buf: &[u8] = &arr; //! let mut read: &mut Read = &mut buf; //! assert_eq!(v, Varint::deserialize(read).unwrap()); //! } //! //! fn main() { //! test_varint(0, 1); //! test_varint(1, 1); //! test_varint(-1, 1); //! } //! ``` //! //! ## Encoding rules //! //! Encoding rules for `Varuint` are (assuming value is `V`): //! //! * If `V<=240` then output a single byte `A0` equal to `V`. //! * If `V<=2031` then output `A0` as `(V-240)/256 + 241` and `A1` as `(V-240)%256`. //! * If `V<=67567` then output `A0` as `248`, `A1` as `(V-2032)/256`, and `A2` as `(V-2032)%256`. //! * If `V<=16777215` then output `A0` as `249` and `A1` through `A3` as a little-endian 3-byte integer. //! * If `V<=4294967295` then output `A0` as `250` and `A1..A4` as a little-ending 4-byte integer. //! * If `V<=1099511627775` then output `A0` as `251` and `A1..A5` as a little-ending 5-byte integer. //! * If `V<=281474976710655` then output `A0` as `252` and `A1..A6` as a little-ending 6-byte integer. //! * If `V<=72057594037927935` then output `A0` as `253` and `A1..A7` as a little-ending 7-byte integer. //! * If `V<=9223372036854775807` then output `A0` as `254` and `A1..A8` as a little-ending 8-byte integer. //! * Otherwise output `A0` as `255` and `A1..A16` as a little-endian 16-byte integer. //! //! `Varint` converted to the `Varuint` in the first place and then encoded as an unsigned integer. //! Conversion method makes values closer to 0 take less space. //! See [Protobuf docs](https://!developers.google.com/protocol-buffers/docs/encoding#signed-integers) //! for details. mod varuint; #[macro_use] #[cfg(feature = "serde-support")] extern crate serde_derive; #[cfg(feature = "serde-support")] extern crate serde; pub use varuint::{Serializable, Deserializable, Varuint, Varint};