├── .gitignore ├── .travis.yml ├── Cargo.lock ├── Cargo.toml ├── LICENCE ├── README.md ├── benches └── lib.rs ├── src ├── decode.rs ├── encode.rs ├── lib.rs └── utils.rs └── tests └── lib.rs /.gitignore: -------------------------------------------------------------------------------- 1 | target 2 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: rust 2 | 3 | rust: 4 | - stable 5 | - beta 6 | - nightly 7 | 8 | branches: 9 | except: 10 | - dev 11 | - benches 12 | 13 | matrix: 14 | allow_failures: 15 | - rust: nightly 16 | 17 | os: 18 | - linux 19 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | [root] 2 | name = "bitsparrow" 3 | version = "2.0.0-rc4" 4 | 5 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "bitsparrow" 3 | version = "2.0.0-rc4" 4 | authors = ["maciej.hirsz@gmail.com"] 5 | description = "BitSparrow implementation in Rust" 6 | homepage = "http://bitsparrow.io/" 7 | documentation = "http://bitsparrow.io/doc/bitsparrow/" 8 | repository = "https://github.com/bitsparrow/bitsparrow-rust" 9 | license = "MIT" 10 | -------------------------------------------------------------------------------- /LICENCE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2017 BitSparrow 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # BitSparrow in Rust 2 | 3 | ![](https://api.travis-ci.org/bitsparrow/bitsparrow-rust.svg) 4 | 5 | **[Homepage](http://bitsparrow.io/) -** 6 | **[API Documentation](http://bitsparrow.io/doc/bitsparrow/) -** 7 | **[Cargo](https://crates.io/crates/bitsparrow)** 8 | 9 | ## Encoding 10 | 11 | ```rust 12 | use bitsparrow::Encoder; 13 | 14 | let buffer = Encoder::new() 15 | .uint8(100) 16 | .string("Foo") 17 | .end(); 18 | 19 | assert_eq!(buffer, &[0x64,0x03,0x46,0x6f,0x6f]) 20 | ``` 21 | 22 | Each method on the `Encoder` will consume the instance of the 23 | struct. If you need to break the monad chain, store the 24 | intermediate state of the encoder, e.g.: 25 | 26 | ```rust 27 | use bitsparrow::Encoder; 28 | 29 | let encoder = Encoder::new(); 30 | encoder.uint8(100); 31 | 32 | /* ... */ 33 | 34 | let buffer = encoder.string("Foo").end(); 35 | 36 | assert_eq!(buffer, &[0x64,0x03,0x46,0x6f,0x6f]); 37 | ``` 38 | 39 | ## Decoding 40 | 41 | ```rust 42 | use bitsparrow::Decoder; 43 | 44 | let buffer = &[0x64,0x03,0x46,0x6f,0x6f]; 45 | let mut decoder = Decoder::new(buffer); 46 | 47 | assert_eq!(100u8, decoder.uint8().unwrap()); 48 | assert_eq!("Foo", decoder.string().unwrap()); 49 | assert_eq!(true, decoder.end()); 50 | ``` 51 | 52 | Decoder allows you to retrieve the values in order they were 53 | encoded. Calling the `end` method is optional - it will return 54 | `true` if you have read the entire buffer, ensuring the entire 55 | buffer has been read. 56 | 57 | ## Performance 58 | 59 | All primitive number types are encoded and decoded using straight 60 | low level memory copying and type transmutations. Even on 61 | little-endian hardware (the encoded data is always big-endian) the 62 | cost of encoding/decoding is virtually none: 63 | 64 | ``` 65 | test allocate_8 ... bench: 26 ns/iter (+/- 4) 66 | test decode_f64 ... bench: 0 ns/iter (+/- 0) 67 | test decode_u64 ... bench: 0 ns/iter (+/- 0) 68 | test encode_f64 ... bench: 26 ns/iter (+/- 6) 69 | test encode_u64 ... bench: 26 ns/iter (+/- 3) 70 | ``` 71 | 72 | Encoding benchmark includes allocating 8 bytes on the heap, the 73 | `allocate_8` just creates `Vec::with_capacity(8)` to demonstrate that 74 | the actual encoding process is very, very cheap. 75 | 76 | ## The MIT License (MIT) 77 | 78 | Copyright (c) 2016 BitSparrow 79 | 80 | Permission is hereby granted, free of charge, to any person obtaining a copy 81 | of this software and associated documentation files (the "Software"), to deal 82 | in the Software without restriction, including without limitation the rights 83 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 84 | copies of the Software, and to permit persons to whom the Software is 85 | furnished to do so, subject to the following conditions: 86 | 87 | The above copyright notice and this permission notice shall be included in all 88 | copies or substantial portions of the Software. 89 | 90 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 91 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 92 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 93 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 94 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 95 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 96 | SOFTWARE. 97 | -------------------------------------------------------------------------------- /benches/lib.rs: -------------------------------------------------------------------------------- 1 | #![feature(test)] 2 | 3 | extern crate test; 4 | extern crate bitsparrow; 5 | 6 | use bitsparrow::*; 7 | 8 | use test::Bencher; 9 | 10 | #[bench] 11 | fn encode_u64(b: &mut Bencher) { 12 | b.iter(|| { 13 | Encoder::encode(::std::u64::MAX) 14 | }) 15 | } 16 | 17 | #[bench] 18 | fn encode_f64(b: &mut Bencher) { 19 | b.iter(|| { 20 | Encoder::encode(3.141592653589793f64) 21 | }) 22 | } 23 | 24 | #[bench] 25 | fn encode_slice(b: &mut Bencher) { 26 | b.iter(|| { 27 | Encoder::encode(b"hello world!") 28 | }) 29 | } 30 | 31 | #[bench] 32 | fn encode_tuple(b: &mut Bencher) { 33 | b.iter(|| { 34 | Encoder::encode(("hello world!", 3.14f32, false)) 35 | }) 36 | } 37 | 38 | #[bench] 39 | fn encode_complex_slice(b: &mut Bencher) { 40 | b.iter(|| { 41 | Encoder::encode(&[3.14f32, 2.15, 1.16]) 42 | }) 43 | } 44 | 45 | #[bench] 46 | fn decode_complex_vec(b: &mut Bencher) { 47 | let buffer = Encoder::encode(&[3.14f32, 2.15, 1.16]); 48 | 49 | b.iter(|| { 50 | let _foo: Vec = Decoder::decode(&buffer).unwrap(); 51 | }) 52 | } 53 | 54 | #[bench] 55 | fn decode_tuple(b: &mut Bencher) { 56 | let buffer = Encoder::encode((10u64, 3.14f32, true)); 57 | 58 | b.iter(|| { 59 | let _foo: (u64, f32, bool) = Decoder::decode(&buffer).unwrap(); 60 | }) 61 | } 62 | 63 | #[bench] 64 | fn decode_u64(b: &mut Bencher) { 65 | let buffer = Encoder::encode(::std::u64::MAX); 66 | 67 | b.iter(|| { 68 | let mut decoder = Decoder::new(&buffer); 69 | decoder.uint64().unwrap() 70 | }) 71 | } 72 | 73 | #[bench] 74 | fn decode_f64(b: &mut Bencher) { 75 | let buffer = Encoder::encode(3.141592653589793f64); 76 | 77 | b.iter(|| { 78 | let mut decoder = Decoder::new(&buffer); 79 | decoder.float64().unwrap() 80 | }) 81 | } 82 | -------------------------------------------------------------------------------- /src/decode.rs: -------------------------------------------------------------------------------- 1 | use std::{mem, ptr}; 2 | use std::str::from_utf8; 3 | 4 | use utils::{SIZE_MASKS, Error, Result}; 5 | 6 | /// Decoder reads from a binary slice buffer (`&[u8]`) and exposes 7 | /// methods to read BitSparrow types from it in the same order they 8 | /// were encoded by the `Encoder`. 9 | pub struct Decoder<'src> { 10 | index: usize, 11 | data: &'src [u8], 12 | ptr: *const u8, 13 | bool_index: usize, 14 | bool_shift: u8, 15 | } 16 | 17 | pub trait BitDecode<'src>: Sized + 'src { 18 | fn decode(&mut Decoder<'src>) -> Result; 19 | } 20 | 21 | macro_rules! read_bytes { 22 | ($decoder:expr, $t:ident) => ({ 23 | let size = mem::size_of::<$t>(); 24 | let end = $decoder.index + size; 25 | if end > $decoder.data.len() { 26 | return Err(Error::ReadingOutOfBounds); 27 | } 28 | 29 | unsafe { 30 | let mut value: $t = mem::uninitialized(); 31 | let ptr = &mut value as *mut $t as *mut u8; 32 | 33 | ptr::copy_nonoverlapping( 34 | $decoder.data.as_ptr().offset($decoder.index as isize), 35 | ptr, 36 | size 37 | ); 38 | 39 | $decoder.index = end; 40 | 41 | Ok($t::from_be(value)) 42 | } 43 | }) 44 | } 45 | 46 | 47 | impl<'src> Decoder<'src> { 48 | /// Create a new `Decoder` reading from a `&[u8]` slice buffer. 49 | #[inline] 50 | pub fn new(data: &[u8]) -> Decoder { 51 | Decoder { 52 | index: 0, 53 | data: data, 54 | ptr: data.as_ptr(), 55 | bool_index: ::std::usize::MAX, 56 | bool_shift: 0, 57 | } 58 | } 59 | 60 | #[inline] 61 | pub fn decode>(data: &'src [u8]) -> Result { 62 | let mut d = Decoder::new(data); 63 | let value = try!(BitDecode::decode(&mut d)); 64 | if !d.end() { 65 | return Err(Error::BufferNotEmpty); 66 | } 67 | Ok(value) 68 | } 69 | 70 | #[inline] 71 | pub fn read>(&mut self) -> Result { 72 | BitDecode::decode(self) 73 | } 74 | 75 | /// Read a `u8` from the buffer and progress the internal index. 76 | #[inline] 77 | pub fn uint8(&mut self) -> Result { 78 | if self.index >= self.data.len() { 79 | return Err(Error::ReadingOutOfBounds); 80 | } 81 | let uint8 = unsafe { *self.ptr.offset(self.index as isize) }; 82 | self.index += 1; 83 | return Ok(uint8); 84 | } 85 | 86 | /// Read a `u16` from the buffer and progress the internal index. 87 | #[inline] 88 | pub fn uint16(&mut self) -> Result { 89 | read_bytes!(self, u16) 90 | } 91 | 92 | /// Read a `u32` from the buffer and progress the internal index. 93 | #[inline] 94 | pub fn uint32(&mut self) -> Result { 95 | read_bytes!(self, u32) 96 | } 97 | 98 | /// Read a `u64` from the buffer and progress the internal index. 99 | #[inline] 100 | pub fn uint64(&mut self) -> Result { 101 | read_bytes!(self, u64) 102 | } 103 | 104 | /// Read an `i8` from the buffer and progress the internal index. 105 | #[inline] 106 | pub fn int8(&mut self) -> Result { 107 | let uint8 = try!(self.uint8()); 108 | 109 | Ok(uint8 as i8) 110 | } 111 | 112 | /// Read an `i16` from the buffer and progress the internal index. 113 | #[inline] 114 | pub fn int16(&mut self) -> Result { 115 | read_bytes!(self, i16) 116 | } 117 | 118 | /// Read an `i32` from the buffer and progress the internal index. 119 | #[inline] 120 | pub fn int32(&mut self) -> Result { 121 | read_bytes!(self, i32) 122 | } 123 | 124 | /// Read an `i64` from the buffer and progress the internal index. 125 | #[inline] 126 | pub fn int64(&mut self) -> Result { 127 | read_bytes!(self, i64) 128 | } 129 | 130 | /// Read a `float32` from the buffer and progress the internal index. 131 | #[inline] 132 | pub fn float32(&mut self) -> Result { 133 | let uint32 = try!(self.uint32()); 134 | 135 | Ok(unsafe { mem::transmute(uint32) }) 136 | } 137 | 138 | /// Read a `float64` from the buffer and progress the internal index. 139 | #[inline] 140 | pub fn float64(&mut self) -> Result { 141 | let uint64 = try!(self.uint64()); 142 | 143 | Ok(unsafe { mem::transmute(uint64) }) 144 | } 145 | 146 | /// Read a `bool` from the buffer and progress the internal index. If 147 | /// a `bool` was previously read from the buffer, calling `bool()` 148 | /// on the `Decoder` again will read a boolean from the same index 149 | /// without progressing, but instead shifting to read the next bit. 150 | /// This behavior is symmetric to how the `Encoder` stores the `bool`s, 151 | /// and is completely transparent when using the API. 152 | /// 153 | /// ``` 154 | /// use bitsparrow::Decoder; 155 | /// 156 | /// // Reading `bools` from a single byte. 157 | /// let buffer = &[0b11100001]; 158 | /// let mut decoder = Decoder::new(buffer); 159 | /// 160 | /// assert_eq!(true, decoder.bool().unwrap()); 161 | /// assert_eq!(false, decoder.bool().unwrap()); 162 | /// assert_eq!(false, decoder.bool().unwrap()); 163 | /// assert_eq!(false, decoder.bool().unwrap()); 164 | /// assert_eq!(false, decoder.bool().unwrap()); 165 | /// assert_eq!(true, decoder.bool().unwrap()); 166 | /// assert_eq!(true, decoder.bool().unwrap()); 167 | /// assert_eq!(true, decoder.bool().unwrap()); 168 | /// 169 | /// // Ensure we've read the entire buffer 170 | /// assert_eq!(true, decoder.end()); 171 | /// ``` 172 | #[inline] 173 | pub fn bool(&mut self) -> Result { 174 | if self.bool_index == self.index && self.bool_shift < 7 { 175 | self.bool_shift += 1; 176 | let bits = self.data[self.index - 1]; 177 | let bool_bit = 1 << self.bool_shift; 178 | return Ok(bits & bool_bit == bool_bit); 179 | } 180 | 181 | let bits = try!(self.uint8()); 182 | self.bool_index = self.index; 183 | self.bool_shift = 0; 184 | 185 | Ok(bits & 1 == 1) 186 | } 187 | 188 | /// Read a `usize` from the buffer and progress the index. Detailed 189 | /// explanation on how BitSparrow stores `size` can be found on 190 | /// [the homepage](http://bitsparrow.io). 191 | #[inline(always)] 192 | pub fn size(&mut self) -> Result { 193 | let high = try!(self.uint8()); 194 | 195 | // 1 byte (no signature) 196 | if (high & 128) == 0 { 197 | return Ok(high as usize); 198 | } 199 | 200 | let mut ext_bytes = (!high).leading_zeros() as usize; 201 | let mut size = (high ^ SIZE_MASKS[ext_bytes]) as usize; 202 | 203 | while ext_bytes != 0 { 204 | ext_bytes -= 1; 205 | size = (size << 8) | try!(self.uint8()) as usize; 206 | } 207 | 208 | Ok(size) 209 | } 210 | 211 | /// Read an arbitary sized binary data from the buffer and 212 | /// progress the index. 213 | /// 214 | /// **Note:** BitSparrow internally prefixes `bytes` with 215 | /// `size` so you don't have to worry about how many bytes 216 | /// you need to read. 217 | #[inline] 218 | pub fn bytes(&mut self) -> Result<&'src [u8]> { 219 | // Order of addition is important here! 220 | // Calling `size` will modify the `index`. 221 | let len = try!(self.size()); 222 | let end = len + self.index; 223 | 224 | if end > self.data.len() { 225 | return Err(Error::ReadingOutOfBounds); 226 | } 227 | 228 | let bytes = unsafe { ::std::slice::from_raw_parts( 229 | self.ptr.offset(self.index as isize), 230 | len 231 | ) }; 232 | 233 | self.index = end; 234 | 235 | Ok(bytes) 236 | } 237 | 238 | /// Read an arbitary sized owned `String` from the buffer and 239 | /// progress the index. 240 | /// 241 | /// **Note:** Analog to `bytes`, BitSparrow internally prefixes 242 | /// `string` with `size` so you don't have to worry about how 243 | /// many bytes you need to read. 244 | #[inline] 245 | pub fn string(&mut self) -> Result<&'src str> { 246 | from_utf8(try!(self.bytes())).map_err(Into::into) 247 | } 248 | 249 | /// Returns `true` if the entire buffer has been read, otherwise 250 | /// returns `false`. 251 | #[inline] 252 | pub fn end(&self) -> bool { 253 | self.index >= self.data.len() 254 | } 255 | } 256 | 257 | macro_rules! impl_decodable { 258 | ($func:ident, $t:ty) => { 259 | impl<'src> BitDecode<'src> for $t { 260 | #[inline] 261 | fn decode(d: &mut Decoder<'src>) -> Result { 262 | d.$func() 263 | } 264 | } 265 | } 266 | } 267 | 268 | impl_decodable!(uint16, u16); 269 | impl_decodable!(uint32, u32); 270 | impl_decodable!(uint64, u64); 271 | impl_decodable!(int8, i8); 272 | impl_decodable!(int16, i16); 273 | impl_decodable!(int32, i32); 274 | impl_decodable!(int64, i64); 275 | impl_decodable!(float32, f32); 276 | impl_decodable!(float64, f64); 277 | impl_decodable!(bool, bool); 278 | impl_decodable!(size, usize); 279 | 280 | impl<'src> BitDecode<'src> for &'src [u8] { 281 | #[inline] 282 | fn decode(d: &mut Decoder<'src>) -> Result { 283 | d.bytes() 284 | } 285 | } 286 | 287 | impl<'src> BitDecode<'src> for Vec { 288 | #[inline] 289 | fn decode(d: &mut Decoder<'src>) -> Result { 290 | // Order of addition is important here! 291 | // Calling `size` will modify the `index`. 292 | let len = try!(d.size()); 293 | let end = len + d.index; 294 | 295 | if end > d.data.len() { 296 | return Err(Error::ReadingOutOfBounds); 297 | } 298 | 299 | let mut vec = Vec::with_capacity(len); 300 | 301 | unsafe { 302 | ::std::ptr::copy_nonoverlapping( 303 | d.ptr.offset(d.index as isize), 304 | vec.as_mut_ptr(), 305 | len 306 | ); 307 | 308 | vec.set_len(len); 309 | } 310 | 311 | d.index = end; 312 | 313 | Ok(vec) 314 | } 315 | } 316 | 317 | impl<'src> BitDecode<'src> for &'src str { 318 | #[inline] 319 | fn decode(d: &mut Decoder<'src>) -> Result<&'src str> { 320 | d.string() 321 | } 322 | } 323 | 324 | impl<'src> BitDecode<'src> for String { 325 | #[inline] 326 | fn decode(d: &mut Decoder<'src>) -> Result { 327 | String::from_utf8(try!(BitDecode::decode(d))).map_err(Into::into) 328 | } 329 | } 330 | 331 | impl<'src, D: BitDecode<'src>> BitDecode<'src> for Vec { 332 | #[inline] 333 | fn decode(d: &mut Decoder<'src>) -> Result { 334 | let size = try!(d.size()); 335 | 336 | let mut vec = Vec::with_capacity(size); 337 | 338 | for _ in 0..size { 339 | vec.push(try!(D::decode(d))); 340 | } 341 | 342 | Ok(vec) 343 | } 344 | } 345 | 346 | macro_rules! impl_tuple { 347 | ($( $l:ident ),*) => { 348 | impl<'src, $($l),*> BitDecode<'src> for ($($l),*) where 349 | $( 350 | $l: BitDecode<'src>, 351 | )* 352 | { 353 | #[inline(always)] 354 | fn decode(d: &mut Decoder<'src>) -> Result { 355 | Ok(( $( try!($l::decode(d)) ),* )) 356 | } 357 | } 358 | } 359 | } 360 | 361 | impl_tuple!(A, B); 362 | impl_tuple!(A, B, C); 363 | impl_tuple!(A, B, C, D); 364 | impl_tuple!(A, B, C, D, E); 365 | impl_tuple!(A, B, C, D, E, F); 366 | impl_tuple!(A, B, C, D, E, F, G); 367 | impl_tuple!(A, B, C, D, E, F, G, H); 368 | impl_tuple!(A, B, C, D, E, F, G, H, I); 369 | impl_tuple!(A, B, C, D, E, F, G, H, I, J); 370 | -------------------------------------------------------------------------------- /src/encode.rs: -------------------------------------------------------------------------------- 1 | use std::{ptr, mem}; 2 | use utils::SIZE_MASKS; 3 | 4 | /// Encoder takes in typed data and produces a binary buffer 5 | /// represented as `Vec`. 6 | pub struct Encoder { 7 | data: Vec, 8 | bool_index: usize, 9 | bool_shift: u8, 10 | } 11 | 12 | pub trait BitEncode { 13 | fn encode(&self, &mut Encoder); 14 | 15 | #[inline(always)] 16 | fn size_hint() -> usize { 17 | 0 18 | } 19 | } 20 | 21 | impl Encoder { 22 | /// Create a new instance of the `Encoder`. 23 | #[inline(always)] 24 | pub fn new() -> Encoder { 25 | Encoder { 26 | data: Vec::new(), 27 | bool_index: ::std::usize::MAX, 28 | bool_shift: 0, 29 | } 30 | } 31 | 32 | /// Create a new instance of the `Encoder` with a preallocated buffer capacity. 33 | #[inline(always)] 34 | pub fn with_capacity(capacity: usize) -> Encoder { 35 | Encoder { 36 | data: Vec::with_capacity(capacity), 37 | bool_index: ::std::usize::MAX, 38 | bool_shift: 0, 39 | } 40 | } 41 | 42 | #[inline] 43 | pub fn encode(val: E) -> Vec { 44 | let mut e = Encoder::with_capacity(E::size_hint()); 45 | val.encode(&mut e); 46 | e.data 47 | } 48 | 49 | /// Store any type implementing `BitEncode` on the buffer. 50 | #[inline] 51 | pub fn write(&mut self, val: E) -> &mut Self { 52 | val.encode(self); 53 | 54 | self 55 | } 56 | 57 | /// Store a `u8` on the buffer. 58 | #[inline] 59 | pub fn uint8(&mut self, val: u8) -> &mut Self { 60 | self.data.push(val); 61 | 62 | self 63 | } 64 | 65 | /// Store a 'u16' on the buffer. 66 | #[inline] 67 | pub fn uint16(&mut self, val: u16) -> &mut Self { 68 | val.encode(self); 69 | 70 | self 71 | } 72 | 73 | /// Store a 'u32' on the buffer. 74 | #[inline] 75 | pub fn uint32(&mut self, val: u32) -> &mut Self { 76 | val.encode(self); 77 | 78 | self 79 | } 80 | 81 | /// Store a 'u64' on the buffer. 82 | #[inline] 83 | pub fn uint64(&mut self, val: u64) -> &mut Self { 84 | val.encode(self); 85 | 86 | self 87 | } 88 | 89 | /// Store an `i8` on the buffer. 90 | #[inline] 91 | pub fn int8(&mut self, val: i8) -> &mut Self { 92 | val.encode(self); 93 | 94 | self 95 | } 96 | 97 | /// Store an `i16` on the buffer. 98 | #[inline] 99 | pub fn int16(&mut self, val: i16) -> &mut Self { 100 | val.encode(self); 101 | 102 | self 103 | } 104 | 105 | #[inline] 106 | /// Store an `i32` on the buffer. 107 | pub fn int32(&mut self, val: i32) -> &mut Self { 108 | val.encode(self); 109 | 110 | self 111 | } 112 | 113 | #[inline] 114 | /// Store an `i32` on the buffer. 115 | pub fn int64(&mut self, val: i64) -> &mut Self { 116 | val.encode(self); 117 | 118 | self 119 | } 120 | 121 | /// Store an `f32` on the buffer. 122 | #[inline] 123 | pub fn float32(&mut self, val: f32) -> &mut Self { 124 | val.encode(self); 125 | 126 | self 127 | } 128 | 129 | /// Store an `f64` on the buffer. 130 | #[inline] 131 | pub fn float64(&mut self, val: f64) -> &mut Self { 132 | val.encode(self); 133 | 134 | self 135 | } 136 | 137 | /// Store a `bool` on the buffer. Calling `bool` multiple times 138 | /// in a row will attempt to store the information on a single 139 | /// byte. 140 | /// 141 | /// ``` 142 | /// use bitsparrow::Encoder; 143 | /// 144 | /// let buffer = Encoder::new() 145 | /// .bool(true) 146 | /// .bool(false) 147 | /// .bool(false) 148 | /// .bool(false) 149 | /// .bool(false) 150 | /// .bool(true) 151 | /// .bool(true) 152 | /// .bool(true) 153 | /// .end(); 154 | /// 155 | /// // booleans are stacked as bits on a single byte, right to left. 156 | /// assert_eq!(buffer, &[0b11100001]); 157 | /// ``` 158 | #[inline] 159 | pub fn bool(&mut self, val: bool) -> &mut Self { 160 | val.encode(self); 161 | 162 | self 163 | } 164 | 165 | /// Store a `usize` on the buffer. This will use a variable amount of bytes 166 | /// depending on the value of `usize`, making it a very powerful and flexible 167 | /// type to send around. BitSparrow uses `size` internally to prefix `string` 168 | /// and `bytes` as those can have an arbitrary length, and using a large 169 | /// number type such as u32 could be an overkill if all you want to send is 170 | /// `"Foo"`. Detailed explanation on how BitSparrow stores `size` can be found 171 | /// on [the homepage](http://bitsparrow.io). 172 | #[inline] 173 | pub fn size(&mut self, val: usize) -> &mut Self { 174 | self.size_with_reserve(val, 0); 175 | 176 | self 177 | } 178 | 179 | /// Store an arbitary collection of bytes represented as `&[u8]`, 180 | /// easy to use by dereferencing `Vec` with `&`. 181 | #[inline] 182 | pub fn bytes(&mut self, val: &[u8]) -> &mut Self { 183 | val.encode(self); 184 | 185 | self 186 | } 187 | 188 | /// Store an arbitrary UTF-8 Rust string on the buffer. 189 | #[inline] 190 | pub fn string(&mut self, val: &str) -> &mut Self { 191 | val.encode(self); 192 | 193 | self 194 | } 195 | 196 | /// Finish encoding, obtain the buffer and reset the encoder. 197 | #[inline(always)] 198 | pub fn end(&mut self) -> Vec { 199 | self.bool_index = ::std::usize::MAX; 200 | self.bool_shift = 0; 201 | 202 | mem::replace(&mut self.data, Vec::new()) 203 | } 204 | 205 | #[inline(always)] 206 | fn size_with_reserve(&mut self, size: usize, item_size: usize) { 207 | if size < 128 { 208 | // Encoding size means data will follow, so it makes sense to reserve 209 | // capacity on the buffer beforehand 210 | self.data.reserve(1 + size * item_size); 211 | self.data.push(size as u8); 212 | return; 213 | } 214 | 215 | let mut masked = size as u64; 216 | 217 | let lead = masked.leading_zeros() as usize; 218 | let bytes = if lead == 0 { 9 } else { 9 - (lead - 1) / 7 }; 219 | 220 | let mut buf: [u8; 9] = unsafe { mem::uninitialized() }; 221 | 222 | for i in (1 .. bytes).rev() { 223 | buf[i] = masked as u8; 224 | masked >>= 8; 225 | } 226 | buf[0] = (masked as u8) | SIZE_MASKS[bytes - 1]; 227 | 228 | // Same as above... 229 | self.data.reserve(bytes + size * item_size); 230 | self.data.extend_from_slice(&buf[0 .. bytes]); 231 | } 232 | } 233 | 234 | // impl BitEncode for u8 { 235 | // #[inline(always)] 236 | // fn encode(&self, e: &mut Encoder) { 237 | // e.data.push(*self); 238 | // } 239 | // } 240 | 241 | impl BitEncode for i8 { 242 | #[inline(always)] 243 | fn encode(&self, e: &mut Encoder) { 244 | e.data.push(*self as u8); 245 | } 246 | } 247 | 248 | macro_rules! impl_encodable { 249 | ($t:ty) => { 250 | impl BitEncode for $t { 251 | #[inline(always)] 252 | fn encode(&self, e: &mut Encoder) { 253 | unsafe { 254 | let ptr: *const u8 = mem::transmute(&self.to_be()); 255 | 256 | let len = e.data.len(); 257 | e.data.reserve(mem::size_of::<$t>()); 258 | e.data.set_len(len + mem::size_of::<$t>()); 259 | 260 | ptr::copy_nonoverlapping( 261 | ptr, 262 | e.data.as_mut_ptr().offset(len as isize), 263 | mem::size_of::<$t>() 264 | ); 265 | } 266 | } 267 | 268 | #[inline(always)] 269 | fn size_hint() -> usize { 270 | mem::size_of::<$t>() 271 | } 272 | } 273 | } 274 | } 275 | 276 | impl_encodable!(u16); 277 | impl_encodable!(u32); 278 | impl_encodable!(u64); 279 | impl_encodable!(i16); 280 | impl_encodable!(i32); 281 | impl_encodable!(i64); 282 | 283 | impl BitEncode for f32 { 284 | #[inline(always)] 285 | fn encode(&self, e: &mut Encoder) { 286 | BitEncode::encode(&unsafe { mem::transmute::(*self) }, e); 287 | } 288 | 289 | #[inline(always)] 290 | fn size_hint() -> usize { 291 | 8 292 | } 293 | } 294 | 295 | impl BitEncode for f64 { 296 | #[inline(always)] 297 | fn encode(&self, e: &mut Encoder) { 298 | BitEncode::encode(&unsafe { mem::transmute::(*self) }, e); 299 | } 300 | 301 | #[inline(always)] 302 | fn size_hint() -> usize { 303 | 8 304 | } 305 | } 306 | 307 | impl BitEncode for bool { 308 | #[inline(always)] 309 | fn encode(&self, e: &mut Encoder) { 310 | let bit = *self as u8; 311 | let index = e.data.len(); 312 | 313 | if e.bool_index == index && e.bool_shift < 7 { 314 | e.bool_shift += 1; 315 | e.data[index - 1] |= bit << e.bool_shift; 316 | } else { 317 | e.bool_index = index + 1; 318 | e.bool_shift = 0; 319 | e.data.push(bit); 320 | } 321 | } 322 | } 323 | 324 | impl BitEncode for usize { 325 | #[inline(always)] 326 | fn encode(&self, e: &mut Encoder) { 327 | e.size_with_reserve(*self, 0); 328 | } 329 | } 330 | 331 | impl BitEncode for [u8] { 332 | #[inline(always)] 333 | fn encode(&self, e: &mut Encoder) { 334 | e.size_with_reserve(self.len(), 1); 335 | 336 | unsafe { 337 | let len = e.data.len(); 338 | 339 | // Encoder::size must reserve capacity beforehand 340 | debug_assert!(e.data.capacity() >= len + self.len()); 341 | 342 | ptr::copy_nonoverlapping( 343 | self.as_ptr(), 344 | e.data.as_mut_ptr().offset(len as isize), 345 | self.len() 346 | ); 347 | 348 | e.data.set_len(len + self.len()); 349 | } 350 | } 351 | 352 | #[inline(always)] 353 | fn size_hint() -> usize { 354 | 16 355 | } 356 | } 357 | 358 | macro_rules! impl_deref { 359 | ($t:ty, $size:expr) => { 360 | impl<'a> BitEncode for &'a $t { 361 | #[inline(always)] 362 | fn encode(&self, e: &mut Encoder) { 363 | BitEncode::encode(*self, e); 364 | } 365 | 366 | #[inline(always)] 367 | fn size_hint() -> usize { 368 | $size 369 | } 370 | } 371 | } 372 | } 373 | 374 | impl_deref!(u16, 2); 375 | impl_deref!(u32, 4); 376 | impl_deref!(u64, 8); 377 | impl_deref!(i8, 1); 378 | impl_deref!(i16, 2); 379 | impl_deref!(i32, 4); 380 | impl_deref!(i64, 8); 381 | impl_deref!(f32, 4); 382 | impl_deref!(f64, 8); 383 | impl_deref!(usize, 1); 384 | impl_deref!(bool, 1); 385 | impl_deref!([u8], 16); 386 | 387 | macro_rules! impl_array { 388 | ($( $size:expr ),*) => { 389 | $( 390 | impl BitEncode for [u8; $size] { 391 | #[inline(always)] 392 | fn encode(&self, e: &mut Encoder) { 393 | BitEncode::encode(AsRef::<[u8]>::as_ref(self), e); 394 | } 395 | 396 | #[inline(always)] 397 | fn size_hint() -> usize { 398 | $size + 1 399 | } 400 | } 401 | 402 | impl<'a> BitEncode for &'a [u8; $size] { 403 | #[inline(always)] 404 | fn encode(&self, e: &mut Encoder) { 405 | BitEncode::encode(AsRef::<[u8]>::as_ref(self), e); 406 | } 407 | 408 | #[inline(always)] 409 | fn size_hint() -> usize { 410 | $size + 1 411 | } 412 | } 413 | 414 | impl BitEncode for [E; $size] { 415 | #[inline(always)] 416 | fn encode(&self, e: &mut Encoder) { 417 | BitEncode::encode(AsRef::<[E]>::as_ref(self), e); 418 | } 419 | 420 | #[inline(always)] 421 | fn size_hint() -> usize { 422 | $size * E::size_hint() + 1 423 | } 424 | } 425 | 426 | impl<'a, E: BitEncode> BitEncode for &'a [E; $size] { 427 | #[inline(always)] 428 | fn encode(&self, e: &mut Encoder) { 429 | BitEncode::encode(AsRef::<[E]>::as_ref(self), e); 430 | } 431 | 432 | #[inline(always)] 433 | fn size_hint() -> usize { 434 | $size * E::size_hint() + 1 435 | } 436 | } 437 | )* 438 | } 439 | } 440 | 441 | impl_array!( 442 | 0, 443 | 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 444 | 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 445 | ); 446 | 447 | impl<'a> BitEncode for &'a Vec { 448 | #[inline(always)] 449 | fn encode(&self, e: &mut Encoder) { 450 | BitEncode::encode(AsRef::<[u8]>::as_ref(*self), e); 451 | } 452 | 453 | #[inline(always)] 454 | fn size_hint() -> usize { 455 | 16 456 | } 457 | } 458 | 459 | impl<'a> BitEncode for &'a str { 460 | #[inline(always)] 461 | fn encode(&self, e: &mut Encoder) { 462 | BitEncode::encode(self.as_bytes(), e); 463 | } 464 | 465 | #[inline(always)] 466 | fn size_hint() -> usize { 467 | 16 468 | } 469 | } 470 | 471 | impl BitEncode for String { 472 | #[inline(always)] 473 | fn encode(&self, e: &mut Encoder) { 474 | BitEncode::encode(self.as_bytes(), e); 475 | } 476 | 477 | #[inline(always)] 478 | fn size_hint() -> usize { 479 | 16 480 | } 481 | } 482 | 483 | impl<'a> BitEncode for &'a String { 484 | #[inline(always)] 485 | fn encode(&self, e: &mut Encoder) { 486 | BitEncode::encode(self.as_bytes(), e); 487 | } 488 | 489 | #[inline(always)] 490 | fn size_hint() -> usize { 491 | 16 492 | } 493 | } 494 | 495 | impl BitEncode for [E] { 496 | #[inline(always)] 497 | fn encode(&self, e: &mut Encoder) { 498 | e.size_with_reserve(self.len(), E::size_hint()); 499 | for item in self { 500 | BitEncode::encode(item, e); 501 | } 502 | } 503 | } 504 | 505 | impl<'a, E: BitEncode> BitEncode for &'a [E] { 506 | #[inline(always)] 507 | fn encode(&self, e: &mut Encoder) { 508 | BitEncode::encode(*self, e); 509 | } 510 | } 511 | 512 | impl BitEncode for Vec { 513 | #[inline(always)] 514 | fn encode(&self, e: &mut Encoder) { 515 | BitEncode::encode(AsRef::<[E]>::as_ref(self), e); 516 | } 517 | } 518 | 519 | impl<'a, E: BitEncode> BitEncode for &'a Vec { 520 | #[inline(always)] 521 | fn encode(&self, e: &mut Encoder) { 522 | BitEncode::encode(AsRef::<[E]>::as_ref(*self), e); 523 | } 524 | } 525 | 526 | macro_rules! impl_tuple { 527 | ($( $l:ident: $n:tt ),*) => { 528 | impl<$($l),*> BitEncode for ($($l),*) where 529 | $( 530 | $l: BitEncode, 531 | )* 532 | { 533 | #[inline(always)] 534 | fn encode(&self, e: &mut Encoder) { 535 | e.data.reserve(Self::size_hint()); 536 | 537 | $( 538 | self.$n.encode(e); 539 | )* 540 | } 541 | 542 | #[inline] 543 | fn size_hint() -> usize { 544 | $( $l::size_hint() + )* 0 545 | } 546 | } 547 | 548 | impl<'a, $($l),*> BitEncode for &'a ($($l),*) where 549 | $( 550 | $l: BitEncode, 551 | )* 552 | { 553 | #[inline(always)] 554 | fn encode(&self, e: &mut Encoder) { 555 | BitEncode::encode(*self, e); 556 | } 557 | 558 | #[inline] 559 | fn size_hint() -> usize { 560 | $( $l::size_hint() + )* 0 561 | } 562 | } 563 | } 564 | } 565 | 566 | 567 | impl_tuple!(A: 0, B: 1); 568 | impl_tuple!(A: 0, B: 1, C: 2); 569 | impl_tuple!(A: 0, B: 1, C: 2, D: 3); 570 | impl_tuple!(A: 0, B: 1, C: 2, D: 3, E: 4); 571 | impl_tuple!(A: 0, B: 1, C: 2, D: 3, E: 4, F: 5); 572 | impl_tuple!(A: 0, B: 1, C: 2, D: 3, E: 4, F: 5, G: 6); 573 | impl_tuple!(A: 0, B: 1, C: 2, D: 3, E: 4, F: 5, G: 6, H: 7); 574 | impl_tuple!(A: 0, B: 1, C: 2, D: 3, E: 4, F: 5, G: 6, H: 7, I: 8); 575 | impl_tuple!(A: 0, B: 1, C: 2, D: 3, E: 4, F: 5, G: 6, H: 7, I: 8, J: 9); 576 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | //! For implementations in other languages, and more detailed 2 | //! information on the types check out http://bitsparrow.io/. 3 | //! 4 | //! # BitSparrow in Rust 5 | //! 6 | //! ## Encoding 7 | //! 8 | //! ``` 9 | //! use bitsparrow::Encoder; 10 | //! 11 | //! let buffer = Encoder::new() 12 | //! .uint8(100) 13 | //! .string("Foo") 14 | //! .end(); 15 | //! 16 | //! assert_eq!(buffer, &[0x64,0x03,0x46,0x6f,0x6f]) 17 | //! ``` 18 | //! 19 | //! Each method on the `Encoder` will return a mutable borrow of 20 | //! the encoder. If you need to break the monad chain, store the 21 | //! owned encoder as a variable before writing to it, e.g.: 22 | //! 23 | //! ``` 24 | //! use bitsparrow::Encoder; 25 | //! 26 | //! let mut encoder = Encoder::new(); 27 | //! encoder.uint8(100); 28 | //! 29 | //! /* 30 | //! * Many codes here 31 | //! */ 32 | //! 33 | //! let buffer = encoder.string("Foo").end(); 34 | //! 35 | //! assert_eq!(buffer, &[0x64_u8,0x03,0x46,0x6f,0x6f]); 36 | //! ``` 37 | //! 38 | //! ## Decoding 39 | //! 40 | //! ``` 41 | //! use bitsparrow::Decoder; 42 | //! 43 | //! let buffer = &[0x64,0x03,0x46,0x6f,0x6f]; 44 | //! let mut decoder = Decoder::new(buffer); 45 | //! 46 | //! assert_eq!(100u8, decoder.uint8().unwrap()); 47 | //! assert_eq!("Foo", decoder.string().unwrap()); 48 | //! assert_eq!(true, decoder.end()); 49 | //! ``` 50 | //! 51 | //! Decoder allows you to retrieve the values in order they were 52 | //! encoded. Calling the `end` method is optional - it will return 53 | //! `true` if you have read the entire buffer, ensuring the entire 54 | //! buffer has been read. 55 | 56 | mod encode; 57 | mod decode; 58 | mod utils; 59 | 60 | pub use utils::Error; 61 | pub use encode::{Encoder, BitEncode}; 62 | pub use decode::{Decoder, BitDecode}; 63 | -------------------------------------------------------------------------------- /src/utils.rs: -------------------------------------------------------------------------------- 1 | use std::{error, fmt}; 2 | use std::str::Utf8Error; 3 | use std::string::FromUtf8Error; 4 | 5 | pub static SIZE_MASKS: [u8; 9] = [ 6 | 0b00000000, 7 | 0b10000000, 8 | 0b11000000, 9 | 0b11100000, 10 | 0b11110000, 11 | 0b11111000, 12 | 0b11111100, 13 | 0b11111110, 14 | 0b11111111 15 | ]; 16 | 17 | /// Simple error type returned either by the `Decoder` or `Encoder` 18 | #[derive(Debug)] 19 | pub enum Error { 20 | Utf8Encoding, 21 | ReadingOutOfBounds, 22 | BufferNotEmpty, 23 | InvalidData, 24 | } 25 | 26 | impl error::Error for Error { 27 | fn description(&self) -> &str { 28 | use Error::*; 29 | 30 | match *self { 31 | Utf8Encoding => "Couldn't decode UTF-8 string", 32 | ReadingOutOfBounds => "Attempted to read out of bounds", 33 | BufferNotEmpty => "There is still data to read", 34 | InvalidData => "Data does not match requested type", 35 | } 36 | } 37 | } 38 | 39 | impl fmt::Display for Error { 40 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 41 | f.write_str(error::Error::description(self)) 42 | } 43 | } 44 | 45 | impl From for Error { 46 | fn from(_: Utf8Error) -> Error { 47 | Error::Utf8Encoding 48 | } 49 | } 50 | 51 | impl From for Error { 52 | fn from(_: FromUtf8Error) -> Error { 53 | Error::Utf8Encoding 54 | } 55 | } 56 | 57 | pub type Result = ::std::result::Result; 58 | -------------------------------------------------------------------------------- /tests/lib.rs: -------------------------------------------------------------------------------- 1 | extern crate bitsparrow; 2 | 3 | use bitsparrow::{Encoder, Decoder}; 4 | 5 | #[test] 6 | fn eat_own_dog_food() { 7 | const PI: f64 = 3.141592653589793; 8 | static EXPECTED: &'static [u8] = &[ 9 | 0xc8,0x23,0x29,0x49,0x96,0x02,0xd2,0xd6,0x8a,0xd0,0xb6,0x69,0xfd, 10 | 0x2e,0x0f,0x42,0x69,0x74,0x53,0x70,0x61,0x72,0x72,0x6f,0x77,0x20, 11 | 0xf0,0x9f,0x90,0xa6,0x83,0x69,0x53,0x70,0x61,0x72,0x72,0x6f,0x77, 12 | 0x20,0x2f,0xcb,0x88,0x73,0x70,0x65,0x72,0x2e,0x6f,0xca,0x8a,0x2f, 13 | 0x0a,0x0a,0x55,0x6e,0x64,0x65,0x72,0x20,0x74,0x68,0x65,0x20,0x63, 14 | 0x6c,0x61,0x73,0x73,0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6f,0x6e, 15 | 0x20,0x75,0x73,0x65,0x64,0x20,0x69,0x6e,0x20,0x74,0x68,0x65,0x20, 16 | 0x48,0x61,0x6e,0x64,0x62,0x6f,0x6f,0x6b,0x20,0x6f,0x66,0x20,0x74, 17 | 0x68,0x65,0x20,0x42,0x69,0x72,0x64,0x73,0x20,0x6f,0x66,0x20,0x74, 18 | 0x68,0x65,0x20,0x57,0x6f,0x72,0x6c,0x64,0x20,0x28,0x48,0x42,0x57, 19 | 0x29,0x20,0x6d,0x61,0x69,0x6e,0x20,0x67,0x72,0x6f,0x75,0x70,0x69, 20 | 0x6e,0x67,0x73,0x20,0x6f,0x66,0x20,0x74,0x68,0x65,0x20,0x73,0x70, 21 | 0x61,0x72,0x72,0x6f,0x77,0x73,0x20,0x61,0x72,0x65,0x20,0x74,0x68, 22 | 0x65,0x20,0x74,0x72,0x75,0x65,0x20,0x73,0x70,0x61,0x72,0x72,0x6f, 23 | 0x77,0x73,0x20,0x28,0x67,0x65,0x6e,0x75,0x73,0x20,0x50,0x61,0x73, 24 | 0x73,0x65,0x72,0x29,0x2c,0x20,0x74,0x68,0x65,0x20,0x73,0x6e,0x6f, 25 | 0x77,0x66,0x69,0x6e,0x63,0x68,0x65,0x73,0x20,0x28,0x74,0x79,0x70, 26 | 0x69,0x63,0x61,0x6c,0x6c,0x79,0x20,0x6f,0x6e,0x65,0x20,0x67,0x65, 27 | 0x6e,0x75,0x73,0x2c,0x20,0x4d,0x6f,0x6e,0x74,0x69,0x66,0x72,0x69, 28 | 0x6e,0x67,0x69,0x6c,0x6c,0x61,0x29,0x2c,0x20,0x61,0x6e,0x64,0x20, 29 | 0x74,0x68,0x65,0x20,0x72,0x6f,0x63,0x6b,0x20,0x73,0x70,0x61,0x72, 30 | 0x72,0x6f,0x77,0x73,0x20,0x28,0x50,0x65,0x74,0x72,0x6f,0x6e,0x69, 31 | 0x61,0x20,0x61,0x6e,0x64,0x20,0x74,0x68,0x65,0x20,0x70,0x61,0x6c, 32 | 0x65,0x20,0x72,0x6f,0x63,0x6b,0x66,0x69,0x6e,0x63,0x68,0x29,0x2e, 33 | 0x20,0x54,0x68,0x65,0x73,0x65,0x20,0x67,0x72,0x6f,0x75,0x70,0x73, 34 | 0x20,0x61,0x72,0x65,0x20,0x73,0x69,0x6d,0x69,0x6c,0x61,0x72,0x20, 35 | 0x74,0x6f,0x20,0x65,0x61,0x63,0x68,0x20,0x6f,0x74,0x68,0x65,0x72, 36 | 0x2c,0x20,0x61,0x6e,0x64,0x20,0x61,0x72,0x65,0x20,0x65,0x61,0x63, 37 | 0x68,0x20,0x66,0x61,0x69,0x72,0x6c,0x79,0x20,0x68,0x6f,0x6d,0x6f, 38 | 0x67,0x65,0x6e,0x65,0x6f,0x75,0x73,0x2c,0x20,0x65,0x73,0x70,0x65, 39 | 0x63,0x69,0x61,0x6c,0x6c,0x79,0x20,0x50,0x61,0x73,0x73,0x65,0x72, 40 | 0x2e,0x5b,0x34,0x5d,0x20,0x53,0x6f,0x6d,0x65,0x20,0x63,0x6c,0x61, 41 | 0x73,0x73,0x69,0x66,0x69,0x63,0x61,0x74,0x69,0x6f,0x6e,0x73,0x20, 42 | 0x61,0x6c,0x73,0x6f,0x20,0x69,0x6e,0x63,0x6c,0x75,0x64,0x65,0x20, 43 | 0x74,0x68,0x65,0x20,0x73,0x70,0x61,0x72,0x72,0x6f,0x77,0x2d,0x77, 44 | 0x65,0x61,0x76,0x65,0x72,0x73,0x20,0x28,0x50,0x6c,0x6f,0x63,0x65, 45 | 0x70,0x61,0x73,0x73,0x65,0x72,0x29,0x20,0x61,0x6e,0x64,0x20,0x73, 46 | 0x65,0x76,0x65,0x72,0x61,0x6c,0x20,0x6f,0x74,0x68,0x65,0x72,0x20, 47 | 0x41,0x66,0x72,0x69,0x63,0x61,0x6e,0x20,0x67,0x65,0x6e,0x65,0x72, 48 | 0x61,0x20,0x28,0x6f,0x74,0x68,0x65,0x72,0x77,0x69,0x73,0x65,0x20, 49 | 0x63,0x6c,0x61,0x73,0x73,0x69,0x66,0x69,0x65,0x64,0x20,0x61,0x6d, 50 | 0x6f,0x6e,0x67,0x20,0x74,0x68,0x65,0x20,0x77,0x65,0x61,0x76,0x65, 51 | 0x72,0x73,0x2c,0x20,0x50,0x6c,0x6f,0x63,0x65,0x69,0x64,0x61,0x65, 52 | 0x29,0x5b,0x34,0x5d,0x20,0x77,0x68,0x69,0x63,0x68,0x20,0x61,0x72, 53 | 0x65,0x20,0x6d,0x6f,0x72,0x70,0x68,0x6f,0x6c,0x6f,0x67,0x69,0x63, 54 | 0x61,0x6c,0x6c,0x79,0x20,0x73,0x69,0x6d,0x69,0x6c,0x61,0x72,0x20, 55 | 0x74,0x6f,0x20,0x50,0x61,0x73,0x73,0x65,0x72,0x2e,0x5b,0x35,0x5d, 56 | 0x20,0x41,0x63,0x63,0x6f,0x72,0x64,0x69,0x6e,0x67,0x20,0x74,0x6f, 57 | 0x20,0x61,0x20,0x73,0x74,0x75,0x64,0x79,0x20,0x6f,0x66,0x20,0x6d, 58 | 0x6f,0x6c,0x65,0x63,0x75,0x6c,0x61,0x72,0x20,0x61,0x6e,0x64,0x20, 59 | 0x73,0x6b,0x65,0x6c,0x65,0x74,0x61,0x6c,0x20,0x65,0x76,0x69,0x64, 60 | 0x65,0x6e,0x63,0x65,0x20,0x62,0x79,0x20,0x4a,0x6f,0x6e,0x20,0x46, 61 | 0x6a,0x65,0x6c,0x64,0x73,0xc3,0xa5,0x20,0x61,0x6e,0x64,0x20,0x63, 62 | 0x6f,0x6c,0x6c,0x65,0x61,0x67,0x75,0x65,0x73,0x2c,0x20,0x74,0x68, 63 | 0x65,0x20,0x63,0x69,0x6e,0x6e,0x61,0x6d,0x6f,0x6e,0x20,0x69,0x62, 64 | 0x6f,0x6e,0x20,0x6f,0x66,0x20,0x74,0x68,0x65,0x20,0x50,0x68,0x69, 65 | 0x6c,0x69,0x70,0x70,0x69,0x6e,0x65,0x73,0x2c,0x20,0x70,0x72,0x65, 66 | 0x76,0x69,0x6f,0x75,0x73,0x6c,0x79,0x20,0x63,0x6f,0x6e,0x73,0x69, 67 | 0x64,0x65,0x72,0x65,0x64,0x20,0x74,0x6f,0x20,0x62,0x65,0x20,0x61, 68 | 0x20,0x77,0x68,0x69,0x74,0x65,0x2d,0x65,0x79,0x65,0x2c,0x20,0x69, 69 | 0x73,0x20,0x61,0x20,0x73,0x69,0x73,0x74,0x65,0x72,0x20,0x74,0x61, 70 | 0x78,0x6f,0x6e,0x20,0x74,0x6f,0x20,0x74,0x68,0x65,0x20,0x73,0x70, 71 | 0x61,0x72,0x72,0x6f,0x77,0x73,0x20,0x61,0x73,0x20,0x64,0x65,0x66, 72 | 0x69,0x6e,0x65,0x64,0x20,0x62,0x79,0x20,0x74,0x68,0x65,0x20,0x48, 73 | 0x42,0x57,0x2e,0x20,0x54,0x68,0x65,0x79,0x20,0x74,0x68,0x65,0x72, 74 | 0x65,0x66,0x6f,0x72,0x65,0x20,0x63,0x6c,0x61,0x73,0x73,0x69,0x66, 75 | 0x79,0x20,0x69,0x74,0x20,0x61,0x73,0x20,0x69,0x74,0x73,0x20,0x6f, 76 | 0x77,0x6e,0x20,0x73,0x75,0x62,0x66,0x61,0x6d,0x69,0x6c,0x79,0x20, 77 | 0x77,0x69,0x74,0x68,0x69,0x6e,0x20,0x50,0x61,0x73,0x73,0x65,0x72, 78 | 0x69,0x64,0x61,0x65,0x2e,0x5b,0x35,0x5d,0x06,0x01,0x02,0x03,0x04, 79 | 0x05,0x06,0x64,0xa7,0x10,0xcf,0x42,0x40,0xf0,0x3f,0xff,0xff,0xff, 80 | 0x40,0x49,0x0f,0xdb,0x40,0x09,0x21,0xfb,0x54,0x44,0x2d,0x18 81 | ]; 82 | let long_text = "Sparrow /ˈsper.oʊ/\n\nUnder the classification used in \ 83 | the Handbook of the Birds of the World (HBW) main groupings \ 84 | of the sparrows are the true sparrows (genus Passer), the \ 85 | snowfinches (typically one genus, Montifringilla), and the \ 86 | rock sparrows (Petronia and the pale rockfinch). These groups \ 87 | are similar to each other, and are each fairly homogeneous, \ 88 | especially Passer.[4] Some classifications also include the \ 89 | sparrow-weavers (Plocepasser) and several other African genera \ 90 | (otherwise classified among the weavers, Ploceidae)[4] which \ 91 | are morphologically similar to Passer.[5] According to a study \ 92 | of molecular and skeletal evidence by Jon Fjeldså and \ 93 | colleagues, the cinnamon ibon of the Philippines, previously \ 94 | considered to be a white-eye, is a sister taxon to the \ 95 | sparrows as defined by the HBW. They therefore classify it as \ 96 | its own subfamily within Passeridae.[5]"; 97 | 98 | let bytes = [1,2,3,4,5,6]; 99 | 100 | let buffer = Encoder::new() 101 | .uint8(200) 102 | .uint16(9001) 103 | .uint32(1234567890) 104 | .int8(-42) 105 | .int16(-30000) 106 | .int32(-1234567890) 107 | .string("BitSparrow 🐦") 108 | .string(long_text) 109 | .bytes(&bytes) 110 | .size(100) 111 | .size(10000) 112 | .size(1000000) 113 | .size(1073741823) 114 | .float32(PI as f32) 115 | .float64(PI) 116 | .end(); 117 | 118 | assert_eq!(buffer, EXPECTED); 119 | 120 | let mut decoder = Decoder::new(&buffer); 121 | assert_eq!(decoder.uint8().unwrap(), 200); 122 | assert_eq!(decoder.uint16().unwrap(), 9001); 123 | assert_eq!(decoder.uint32().unwrap(), 1234567890); 124 | assert_eq!(decoder.int8().unwrap(), -42); 125 | assert_eq!(decoder.int16().unwrap(), -30000); 126 | assert_eq!(decoder.int32().unwrap(), -1234567890); 127 | assert_eq!(decoder.string().unwrap(), "BitSparrow 🐦"); 128 | assert_eq!(decoder.string().unwrap(), long_text); 129 | assert_eq!(decoder.bytes().unwrap(), bytes); 130 | assert_eq!(decoder.size().unwrap(), 100); 131 | assert_eq!(decoder.size().unwrap(), 10000); 132 | assert_eq!(decoder.size().unwrap(), 1000000); 133 | assert_eq!(decoder.size().unwrap(), 1073741823); 134 | assert_eq!(decoder.float32().unwrap(), PI as f32); 135 | assert_eq!(decoder.float64().unwrap(), PI); 136 | assert!(decoder.end()); 137 | } 138 | 139 | macro_rules! test_type { 140 | ($fnname:ident, $t:ident, $v:expr) => ( 141 | #[test] 142 | fn $fnname() { 143 | let buffer = Encoder::new().$t($v).end(); 144 | let mut decoder = Decoder::new(&buffer); 145 | assert_eq!(decoder.$t().unwrap(), $v); 146 | assert!(decoder.end()); 147 | } 148 | ) 149 | } 150 | 151 | test_type!(bool_true, bool, true); 152 | test_type!(bool_false, bool, false); 153 | test_type!(size_zero, size, 0_usize); 154 | test_type!(size_1, size, 0x7F_usize); 155 | test_type!(size_2, size, 0x3FFF_usize); 156 | test_type!(size_3, size, 0x1FFFFF_usize); 157 | test_type!(size_4, size, 0x0FFFFFFF_usize); 158 | test_type!(size_5, size, 0x07FFFFFFFF_usize); 159 | test_type!(size_6, size, 0x03FFFFFFFFFF_usize); 160 | test_type!(size_7, size, 0x01FFFFFFFFFFFF_usize); 161 | test_type!(size_8, size, 0x00FFFFFFFFFFFFFF_usize); 162 | test_type!(size_9, size, 0xFFFFFFFFFFFFFFFF_usize); 163 | test_type!(size_max, size, ::std::usize::MAX); 164 | test_type!(uint8_zero, uint8, 0_u8); 165 | test_type!(uint8_max, uint8, ::std::u8::MAX); 166 | test_type!(uint16_zero, uint16, 0_u16); 167 | test_type!(uint16_max, uint16, ::std::u16::MAX); 168 | test_type!(uint32_zero, uint32, 0_u32); 169 | test_type!(uint32_max, uint32, ::std::u32::MAX); 170 | test_type!(uint64_zero, uint64, 0_u64); 171 | test_type!(uint64_max, uint64, ::std::u64::MAX); 172 | test_type!(int8_zero, int8, 0_i8); 173 | test_type!(int8_max, int8, ::std::i8::MAX); 174 | test_type!(int8_min, int8, ::std::i8::MIN); 175 | test_type!(int16_zero, int16, 0_i16); 176 | test_type!(int16_max, int16, ::std::i16::MAX); 177 | test_type!(int16_min, int16, ::std::i16::MIN); 178 | test_type!(int32_zero, int32, 0_i32); 179 | test_type!(int32_max, int32, ::std::i32::MAX); 180 | test_type!(int32_min, int32, ::std::i32::MIN); 181 | test_type!(int64_zero, int64, 0); 182 | test_type!(int64_max, int64, ::std::i64::MAX); 183 | test_type!(int64_min, int64, ::std::i64::MIN); 184 | test_type!(float32_pos, float32, 3.141592653589793_f32); 185 | test_type!(float32_neg, float32, -3.141592653589793_f32); 186 | test_type!(float64_pos, float64, 3.141592653589793_f64); 187 | test_type!(float64_neg, float64, -3.141592653589793_f64); 188 | test_type!(string, string, "Foobar 🐦"); 189 | test_type!(bytes, bytes, &[ 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 190 | 100, 110, 120, 130, 140, 150, 160, 170, 180, 190, 191 | 200, 210, 220, 230, 240, 250, 255]); 192 | 193 | #[test] 194 | fn size_check_len_1() { 195 | assert_eq!(Encoder::encode(0x7Fusize).len(), 1); 196 | } 197 | 198 | #[test] 199 | fn size_check_len_2() { 200 | assert_eq!(Encoder::encode(0x3FFFusize).len(), 2); 201 | } 202 | 203 | #[test] 204 | fn size_check_len_3() { 205 | assert_eq!(Encoder::encode(0x1FFFFFusize).len(), 3); 206 | } 207 | 208 | #[test] 209 | fn size_check_len_4() { 210 | assert_eq!(Encoder::encode(0x0FFFFFFFusize).len(), 4); 211 | } 212 | 213 | #[test] 214 | fn size_check_len_5() { 215 | assert_eq!(Encoder::encode(0x07FFFFFFFFusize).len(), 5); 216 | } 217 | 218 | #[test] 219 | fn size_check_len_6() { 220 | assert_eq!(Encoder::encode(0x03FFFFFFFFFFusize).len(), 6); 221 | } 222 | 223 | #[test] 224 | fn size_check_len_7() { 225 | assert_eq!(Encoder::encode(0x01FFFFFFFFFFFFusize).len(), 7); 226 | } 227 | 228 | #[test] 229 | fn size_check_len_8() { 230 | assert_eq!(Encoder::encode(0x00FFFFFFFFFFFFFFusize).len(), 8); 231 | } 232 | 233 | #[test] 234 | fn size_check_len_9() { 235 | assert_eq!(Encoder::encode(0xFFFFFFFFFFFFFFFFusize).len(), 9); 236 | } 237 | 238 | #[test] 239 | fn stacking_bools() { 240 | let buffer = Encoder::new() 241 | .bool(true) 242 | .bool(false) 243 | .bool(true) 244 | .bool(false) 245 | .bool(false) 246 | .bool(false) 247 | .bool(true) 248 | .bool(true) 249 | .bool(false) 250 | .uint8(10) 251 | .bool(true) 252 | .end(); 253 | 254 | assert_eq!(buffer.len(), 4); 255 | 256 | let mut decoder = Decoder::new(&buffer); 257 | assert_eq!(decoder.bool().unwrap(), true); 258 | assert_eq!(decoder.bool().unwrap(), false); 259 | assert_eq!(decoder.bool().unwrap(), true); 260 | assert_eq!(decoder.bool().unwrap(), false); 261 | assert_eq!(decoder.bool().unwrap(), false); 262 | assert_eq!(decoder.bool().unwrap(), false); 263 | assert_eq!(decoder.bool().unwrap(), true); 264 | assert_eq!(decoder.bool().unwrap(), true); 265 | assert_eq!(decoder.bool().unwrap(), false); 266 | assert_eq!(decoder.uint8().unwrap(), 10); 267 | assert_eq!(decoder.bool().unwrap(), true); 268 | assert_eq!(decoder.end(), true); 269 | } 270 | 271 | #[test] 272 | fn encode_tuple() { 273 | let buffer = Encoder::encode(("foo", 3.14f32, true)); 274 | 275 | let mut decoder = Decoder::new(&buffer); 276 | 277 | assert_eq!(decoder.string().unwrap(), "foo"); 278 | assert_eq!(decoder.float32().unwrap(), 3.14); 279 | assert_eq!(decoder.bool().unwrap(), true); 280 | assert_eq!(decoder.end(), true); 281 | } 282 | 283 | #[test] 284 | fn decode_tuple() { 285 | let buffer = Encoder::new() 286 | .string("foo") 287 | .float32(3.14) 288 | .bool(true) 289 | .end(); 290 | 291 | let tuple: (String, f32, bool) = Decoder::decode(&buffer).unwrap(); 292 | 293 | assert_eq!(tuple, ("foo".into(), 3.14, true)); 294 | } 295 | 296 | #[test] 297 | fn encode_complex_slice() { 298 | let buffer = Encoder::encode(&[3.14f32, 2.15, 1.16]); 299 | 300 | let mut decoder = Decoder::new(&buffer); 301 | assert_eq!(decoder.size().unwrap(), 3); 302 | assert_eq!(decoder.float32().unwrap(), 3.14); 303 | assert_eq!(decoder.float32().unwrap(), 2.15); 304 | assert_eq!(decoder.float32().unwrap(), 1.16); 305 | assert_eq!(decoder.end(), true); 306 | } 307 | 308 | #[test] 309 | fn decode_complex_vec() { 310 | let buffer = Encoder::new() 311 | .size(3) 312 | .float32(3.14) 313 | .float32(2.15) 314 | .float32(1.16) 315 | .end(); 316 | 317 | let floats: Vec = Decoder::decode(&buffer).unwrap(); 318 | 319 | assert_eq!(floats, &[3.14, 2.15, 1.16]); 320 | } 321 | 322 | #[test] 323 | fn encode_decode_slices() { 324 | let data: (&str, &[u8]) = ("foo", b"bar"); 325 | 326 | let buffer = Encoder::encode(data); 327 | 328 | let decoded: (&str, &[u8]) = Decoder::decode(&buffer).unwrap(); 329 | 330 | assert_eq!(data, decoded); 331 | } 332 | --------------------------------------------------------------------------------