├── .gitignore ├── .travis.yml ├── Cargo.toml ├── LICENSE-MIT ├── src ├── traits.rs ├── impls │ ├── mod.rs │ ├── primitives.rs │ └── collections.rs ├── errors.rs ├── lib.rs └── macros.rs ├── RELEASES.md ├── tests └── lib.rs ├── README.md └── LICENSE-APACHE /.gitignore: -------------------------------------------------------------------------------- 1 | target 2 | Cargo.lock 3 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: rust 2 | rust: 3 | - stable 4 | - beta 5 | - nightly 6 | matrix: 7 | allow_failures: 8 | - rust: nightly -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "bytevec" 3 | version = "0.2.0" 4 | authors = ["Fernando Ulloa "] 5 | description = "A Rust serialization library that uses byte vectors" 6 | license = "Apache-2.0/MIT" 7 | repository = "https://github.com/fero23/bytevec" 8 | documentation = "http://fero23.github.io/doc/bytevec/" 9 | readme = "README.md" 10 | keywords = ["serialization", "deserialization", "byte", "vector", "binary"] 11 | 12 | [dependencies] 13 | -------------------------------------------------------------------------------- /LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016 Fernando Ulloa 2 | 3 | Permission is hereby granted, free of charge, to any 4 | person obtaining a copy of this software and associated 5 | documentation files (the "Software"), to deal in the 6 | Software without restriction, including without 7 | limitation the rights to use, copy, modify, merge, 8 | publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software 10 | is furnished to do so, subject to the following 11 | conditions: 12 | 13 | The above copyright notice and this permission notice 14 | shall be included in all copies or substantial portions 15 | of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 18 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 19 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 20 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 21 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 24 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 | DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /src/traits.rs: -------------------------------------------------------------------------------- 1 | use {BVEncodeResult, BVDecodeResult, BVSize}; 2 | use errors::{ByteVecError, BVExpectedSize}; 3 | 4 | /// Provides serialization functionality for the implementing types. 5 | pub trait ByteEncodable { 6 | /// Returns the total length of the byte buffer 7 | /// than can be obtained through the `encode` method 8 | fn get_size(&self) -> Option where Size: BVSize + ByteEncodable; 9 | /// Returs a byte representation of the original data object 10 | fn encode(&self) -> BVEncodeResult> where Size: BVSize + ByteEncodable; 11 | } 12 | 13 | /// Provides deserialization functionality for the implementing types. 14 | pub trait ByteDecodable: Sized { 15 | /// Returns an instance of `Self` obtained from the deserialization of the provided byte buffer. 16 | fn decode(bytes: &[u8]) -> BVDecodeResult where Size: BVSize + ByteDecodable; 17 | /// Returns the result of `decode` if `bytes.len()` is less or equal than `limit` 18 | fn decode_max(bytes: &[u8], limit: Size) -> BVDecodeResult 19 | where Size: BVSize + ByteDecodable 20 | { 21 | if bytes.len() <= limit.as_usize() { 22 | Self::decode::(bytes) 23 | } else { 24 | Err(ByteVecError::BadSizeDecodeError { 25 | expected: BVExpectedSize::LessOrEqualThan(limit.as_usize()), 26 | actual: bytes.len(), 27 | }) 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /src/impls/mod.rs: -------------------------------------------------------------------------------- 1 | mod collections; 2 | mod primitives; 3 | 4 | /// Represents the generic integral type of the structure size indicators 5 | pub trait BVSize: Sized { 6 | /// Returns a `Self` value casted from an `usize` value 7 | fn from_usize(val: usize) -> Self; 8 | /// Returns an `usize` value casted from a `Self` value 9 | fn as_usize(&self) -> usize; 10 | /// Returns the max value for `Self` 11 | fn max_value() -> Self; 12 | /// Calls the `checked_add` method of `self` passing `rhs` 13 | fn checked_add(self, rhs: Self) -> Option; 14 | /// Returns the returned value of [`std::mem::size_of`][1] for `Self` 15 | /// [1]: http://doc.rust-lang.org/stable/std/mem/fn.size_of.html 16 | fn get_size_of() -> Self; 17 | } 18 | 19 | macro_rules! def_BVSize { 20 | ($($t:ty),*) => { 21 | $( 22 | impl BVSize for $t { 23 | fn from_usize(val: usize) -> $t { 24 | val as $t 25 | } 26 | 27 | fn as_usize(&self) -> usize { 28 | *self as usize 29 | } 30 | 31 | fn max_value() -> Self { 32 | <$t>::max_value() 33 | } 34 | 35 | fn checked_add(self, rhs: Self) -> Option<$t> { 36 | self.checked_add(rhs) 37 | } 38 | 39 | fn get_size_of() -> Self { 40 | <$t>::from_usize(::std::mem::size_of::<$t>()) 41 | } 42 | } 43 | )* 44 | } 45 | } 46 | 47 | def_BVSize!(u8, u16, u32, u64); -------------------------------------------------------------------------------- /RELEASES.md: -------------------------------------------------------------------------------- 1 | # Version 0.2.0 (2016-06-06) 2 | - Rename the `bytevec_impls` macro to `bytevec_decl`. This macro now accepts a pub 3 | access modifier on the declared `struct` and on its fields. 4 | - Reintroduce the `bytevec_impls` macro. This macro now can do a partial or full implementation 5 | of the serialization and deserialization operations for an externally declared `struct`. Partial 6 | implementation in this context meaning that it can be implemented for only a subset of the 7 | actual fields of the `struct` rather than for all the fields. The remaining fields will be 8 | obtained from the value returned from [`Default::default()`] on deserialization. 9 | - Change the fixed u32 type for the size indicators used in the byte representation of a complex 10 | structure. The methods of `ByteEncodable` and `ByteDecodable` now use an integral type parameter 11 | `Size` constrained by the `BVSize` trait. This trait is implemented for `u8`, `u16`, `u32` and `u64`. 12 | This now lifts the 4GB fixed limit of byte buffer, as the user now can use `u64` for the size indicator. 13 | - Add a `decode_max` method to the `ByteDecodable` trait, so users are now able to set a limit to the 14 | length of byte buffer on deserialization. If the limit is less or equal than the buffer length, it will 15 | call and return the value returned from `decode`, otherwise it will return a `BadSizeDecodeError`. 16 | - Change endianness from big endian to little endian. 17 | 18 | [`Default::default()`]: http://doc.rust-lang.org/stable/std/default/trait.Default.html#tymethod.default 19 | 20 | # Version 0.1.1 (2016-05-30) 21 | - Minor fix to correct wrong usage of a `BVExpectedSize` value. 22 | 23 | # Version 0.1.0 (2016-05-29) 24 | - Introduce the `ByteEncodable` and `ByteDecodable` traits that provide methods for serialization 25 | and deserialization respectively. 26 | - Implementations of the `ByteEncodable` and `ByteDecodable` traits for most base types. 27 | - Introduce the `bytevec_impls` macro for custom `struct` declarations that automatically implement 28 | the `ByteEncodable` and `ByteDecodable` traits. 29 | - `bytevec_impls` can only define private structs. 30 | - Big endian encoding for primitive data types. 31 | - u32 fixed length for the size indicators. 32 | - Max 4GB fixed limit. -------------------------------------------------------------------------------- /src/errors.rs: -------------------------------------------------------------------------------- 1 | use std::str::Utf8Error; 2 | use std::convert::From; 3 | use std::error::Error; 4 | use std::fmt::{self, Display}; 5 | 6 | use self::ByteVecError::*; 7 | use self::BVExpectedSize::*; 8 | 9 | #[derive(Debug, Clone, Copy)] 10 | pub enum BVExpectedSize { 11 | LessOrEqualThan(usize), 12 | MoreThan(usize), 13 | EqualTo(usize), 14 | } 15 | 16 | #[derive(Debug, Clone)] 17 | pub enum ByteVecError { 18 | StringDecodeUtf8Error(Utf8Error), 19 | BadSizeDecodeError { 20 | expected: BVExpectedSize, 21 | actual: usize, 22 | }, 23 | OverflowError, 24 | } 25 | 26 | impl Display for ByteVecError { 27 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 28 | match *self { 29 | StringDecodeUtf8Error(utf8_error) => write!(f, "StringDecodeUtf8Error: {}", utf8_error), 30 | BadSizeDecodeError { expected, actual } => { 31 | write!(f, 32 | "The size expected for the structure is {}, but the size of the given \ 33 | buffer is {}", 34 | match expected { 35 | LessOrEqualThan(expected) => format!("less or equal than {}", expected), 36 | MoreThan(expected) => format!("more than {}", expected), 37 | EqualTo(expected) => expected.to_string(), 38 | }, 39 | actual) 40 | } 41 | OverflowError => { 42 | write!(f, 43 | "OverflowError: The size of the data structure surpasses the \ 44 | max value of the integral generic type") 45 | } 46 | } 47 | } 48 | } 49 | 50 | impl Error for ByteVecError { 51 | fn description(&self) -> &str { 52 | match *self { 53 | StringDecodeUtf8Error(ref utf8_error) => utf8_error.description(), 54 | BadSizeDecodeError { .. } => { 55 | "the size specified for the structure differs from the size of the given buffer" 56 | } 57 | OverflowError => "the size of the data structure surpasses max value of the size type", 58 | } 59 | } 60 | 61 | fn cause(&self) -> Option<&Error> { 62 | match *self { 63 | StringDecodeUtf8Error(ref utf8_error) => Some(utf8_error), 64 | _ => None, 65 | } 66 | } 67 | } 68 | 69 | impl From for ByteVecError { 70 | fn from(error: Utf8Error) -> ByteVecError { 71 | StringDecodeUtf8Error(error) 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/impls/primitives.rs: -------------------------------------------------------------------------------- 1 | use traits::{ByteEncodable, ByteDecodable}; 2 | use errors::{ByteVecError, BVExpectedSize}; 3 | use std::mem::transmute; 4 | use {BVEncodeResult, BVDecodeResult, BVSize}; 5 | use std::mem::size_of; 6 | 7 | macro_rules! impl_integrals { 8 | {$($t:ty : $size:expr),*} => { 9 | $( 10 | impl ByteEncodable for $t { 11 | fn get_size(&self) -> Option where Size: BVSize + ByteEncodable { 12 | Some(Size::from_usize($size)) 13 | } 14 | 15 | fn encode(&self) -> BVEncodeResult> 16 | where Size: BVSize + ByteEncodable 17 | { 18 | unsafe { 19 | let bytes: [u8; $size] = transmute(self.to_le()); 20 | Ok(bytes.to_vec()) 21 | } 22 | } 23 | } 24 | 25 | impl ByteDecodable for $t { 26 | fn decode(bytes: &[u8]) -> BVDecodeResult<$t> 27 | where Size: BVSize + ByteDecodable 28 | { 29 | if bytes.len() == $size { 30 | let mut t_bytes = [0u8; $size]; 31 | for (b, s) in (&mut t_bytes).into_iter().zip(bytes) { 32 | *b = *s; 33 | } 34 | unsafe { Ok(<$t>::from_le(transmute(t_bytes))) } 35 | } else { 36 | Err(ByteVecError::BadSizeDecodeError { 37 | expected: BVExpectedSize::EqualTo($size as usize), 38 | actual: bytes.len() 39 | }) 40 | } 41 | } 42 | } 43 | )* 44 | } 45 | } 46 | 47 | impl_integrals! { 48 | u8: 1, 49 | u16: 2, 50 | u32: 4, 51 | u64: 8, 52 | i8: 1, 53 | i16: 2, 54 | i32: 4, 55 | i64: 8 56 | } 57 | 58 | macro_rules! as_unsized_impl { 59 | {$($t:ty : $unsizd:ty),*} => { 60 | $( 61 | impl ByteEncodable for $t { 62 | fn get_size(&self) -> Option 63 | where Size: BVSize + ByteEncodable 64 | { 65 | Some(Size::from_usize(size_of::<$t>())) 66 | } 67 | 68 | fn encode(&self) -> BVEncodeResult> 69 | where Size: BVSize + ByteEncodable 70 | { 71 | unsafe { 72 | let unsigned: $unsizd = transmute(*self); 73 | unsigned.encode::() 74 | } 75 | } 76 | } 77 | 78 | impl ByteDecodable for $t { 79 | fn decode(bytes: &[u8]) -> BVDecodeResult<$t> 80 | where Size: BVSize + ByteDecodable 81 | { 82 | let unsigned = try!(<$unsizd>::decode::(bytes)); 83 | unsafe { Ok(transmute(unsigned)) } 84 | } 85 | } 86 | )* 87 | } 88 | } 89 | 90 | as_unsized_impl! { 91 | f32: u32, 92 | f64: u64, 93 | char: u32 94 | } 95 | 96 | impl ByteEncodable for usize { 97 | fn get_size(&self) -> Option 98 | where Size: BVSize + ByteEncodable 99 | { 100 | Some(Size::from_usize(size_of::())) 101 | } 102 | 103 | fn encode(&self) -> BVEncodeResult> 104 | where Size: BVSize + ByteEncodable 105 | { 106 | match size_of::() { 107 | 2 => (*self as u16).encode::(), 108 | 4 => (*self as u32).encode::(), 109 | 8 => (*self as u64).encode::(), 110 | _ => panic!("unknown size for usize"), 111 | } 112 | } 113 | } 114 | 115 | impl ByteDecodable for usize { 116 | fn decode(bytes: &[u8]) -> BVDecodeResult 117 | where Size: BVSize + ByteDecodable 118 | { 119 | Ok(match size_of::() { 120 | 2 => try!(u16::decode::(bytes)).as_usize(), 121 | 4 => try!(u32::decode::(bytes)).as_usize(), 122 | 8 => try!(u64::decode::(bytes)).as_usize(), 123 | _ => panic!("unknown size for usize"), 124 | }) 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /tests/lib.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] 2 | extern crate bytevec; 3 | 4 | use bytevec::{ByteEncodable, ByteDecodable}; 5 | 6 | #[test] 7 | fn test_serialize_vec() { 8 | bytevec_decl! { 9 | #[derive(PartialEq, Eq, Debug)] 10 | struct Employee { 11 | id: u32, 12 | profile: Profile, 13 | dept: String 14 | } 15 | 16 | #[derive(PartialEq, Eq, Debug)] 17 | struct Profile { 18 | id: u32, 19 | name: String, 20 | last_name: String 21 | } 22 | } 23 | 24 | let employees_1 = vec![ 25 | Employee { 26 | id: 1, 27 | profile: Profile { 28 | id: 10000, 29 | name: "Michael".to_string(), 30 | last_name: "Jackson".to_string() 31 | }, 32 | dept: "music".to_string() 33 | }, 34 | Employee { 35 | id: 2, 36 | profile: Profile { 37 | id: 10001, 38 | name: "John".to_string(), 39 | last_name: "Cena".to_string() 40 | }, 41 | dept: "wrestling".to_string() 42 | } 43 | ]; 44 | let bytes = employees_1.encode::().unwrap(); 45 | let employees_2 = Vec::::decode::(&bytes).unwrap(); 46 | assert_eq!(employees_1, employees_2); 47 | } 48 | 49 | 50 | bytevec_decl! { 51 | #[derive(PartialEq, Eq, Debug)] 52 | struct MeetingsLog { 53 | id: u32, 54 | owner: String, 55 | meetings: std::collections::HashMap 56 | } 57 | } 58 | 59 | #[test] 60 | fn test_serialize_slices() { 61 | let slice = &['1', '2', '3']; 62 | let bytes = slice.encode::().unwrap(); 63 | let vec = Vec::::decode::(&bytes).unwrap(); 64 | assert_eq!(vec, slice); 65 | } 66 | 67 | #[test] 68 | fn test_serialize_set() { 69 | let mut set_1 = std::collections::HashSet::new(); 70 | set_1.insert(("One!".to_string(), 1u32)); 71 | set_1.insert(("Two!".to_string(), 2)); 72 | set_1.insert(("Three!".to_string(), 3)); 73 | let bytes = set_1.encode::().unwrap(); 74 | let set_2 = std::collections::HashSet::decode::(&bytes).unwrap(); 75 | assert_eq!(set_1, set_2); 76 | } 77 | 78 | #[test] 79 | fn test_serialize_tuple() { 80 | let pair1 = ("Hello".to_string(), "World".to_string()); 81 | let bytes = pair1.encode::().unwrap(); 82 | let pair2 = <(String, String)>::decode::(&bytes).unwrap(); 83 | assert_eq!(pair1, pair2); 84 | } 85 | 86 | #[test] 87 | fn test_serialize_map() { 88 | let mut classes_1 = std::collections::HashMap::new(); 89 | classes_1.insert(101usize, "Programming 1".to_string()); 90 | classes_1.insert(102, "Basic CS".to_string()); 91 | let bytes = classes_1.encode::().unwrap(); 92 | let classes_2 = std::collections::HashMap::decode::(&bytes).unwrap(); 93 | assert_eq!(classes_1, classes_2); 94 | } 95 | 96 | #[test] 97 | fn test_serialize_slice_with_map_containers() { 98 | let slice = &[ 99 | MeetingsLog { 100 | id: 1, 101 | owner: "Jack".to_string(), 102 | meetings: { 103 | let mut meetings_jack = std::collections::HashMap::new(); 104 | meetings_jack.insert("New York".to_string(), "Michael".to_string()); 105 | meetings_jack.insert("Nippon".to_string(), "Koichi".to_string()); 106 | meetings_jack 107 | } 108 | }, 109 | MeetingsLog { 110 | id: 2, 111 | owner: "Juan".to_string(), 112 | meetings: { 113 | let mut meeting_juan = std::collections::HashMap::new(); 114 | meeting_juan.insert("España".to_string(), "José".to_string()); 115 | meeting_juan.insert("Korea".to_string(), "Lee Hyun".to_string()); 116 | meeting_juan 117 | } 118 | } 119 | ]; 120 | 121 | let bytes = slice.encode::().unwrap(); 122 | let vec = >::decode::(&bytes).unwrap(); 123 | assert_eq!(vec, slice); 124 | } 125 | 126 | #[test] 127 | fn test_u8_upper_limit_encode_err() { 128 | let vec = vec![0u32; 100]; 129 | assert!(vec.encode::().is_err()); 130 | } 131 | 132 | #[test] 133 | fn test_decode_limit_err() { 134 | let vec = vec![0u32; 100]; 135 | let bytes = vec.encode::().unwrap(); 136 | assert!(>::decode_max::(&bytes, 100).is_err()); 137 | } -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | //! bytevec: A Rust serialization library that uses byte vectors 2 | //! ============================================================ 3 | //! 4 | //! bytevec takes advantage of Rust's concise and stable type system to 5 | //! serialize data objects to a byte vector (`Vec`) and back. 6 | //! 7 | //! What does it do? 8 | //! ---------------- 9 | //! Rust has a very powerful type system with predictable sizes for most 10 | //! types, starting with the primitive types, so it's fairly easy to convert 11 | //! any type to a collection of bytes and convert it back. This library intends 12 | //! to give the user the means of converting a given type instance to a byte vector 13 | //! and store it or send it through the wire to another device, with the possibility 14 | //! of getting the value back from the byte vector anytime using the library traits. 15 | //! 16 | //! Of course, Rust isn't magical enough to implement the traits to serialize 17 | //! the functions automatically, as every type has its quirks. This library 18 | //! uses two traits to give a type the functionality it needs to do that: 19 | //! `ByteEncodable` and `ByteDecodable`. 20 | //! 21 | //! ###The `ByteEncodable` trait 22 | //! A type that implements this trait is able to use the `encode` method that 23 | //! yields a `Vec` byte sequence. Seems prone to failure right? Of course it is, 24 | //! internally it uses `unsafe` blocks to extract the bytes of a given type, so 25 | //! it can be pretty unsafe. That's why it always checks for any possible error and 26 | //! returns the vector wrapped around a `BVEncodeResult` instance. If everything 27 | //! goes `Ok`, we will be able to get a byte vector value that represents the 28 | //! original data structure. 29 | //! 30 | //! bytevec doesn't actually do a 1:1 conversion of the bytes of the original 31 | //! type instance, as not every Rust type is stored on the stack. For any type 32 | //! that wraps a heap stored value, it will give a representation of the 33 | //! underlying value. 34 | //! 35 | //! bytevec implements `ByteEncodable` out of the box for the following types: 36 | //! 37 | //! - The integral types: `u8`, `u16`, `u32`, `u64`, `i8`, `i16`, `i32`, `i64` 38 | //! 39 | //! - The floating point types: `f32` and `f64` 40 | //! 41 | //! - `char`, `str` and `String` 42 | //! 43 | //! - [`Vec`](http://doc.rust-lang.org/stable/std/vec/struct.Vec.html) 44 | //! 45 | //! - [`&[T]`](http://doc.rust-lang.org/stable/std/primitive.slice.html) 46 | //! 47 | //! - [`HashMap`](http://doc.rust-lang.org/stable/std/collections/struct.HashMap.html) 48 | //! 49 | //! - [`HashSet`](http://doc.rust-lang.org/stable/std/collections/struct.HashSet.html) 50 | //! 51 | //! - Tuples with up to 12 elements 52 | //! 53 | //! - Custom `struct`s 54 | //! 55 | //! For collections and other structures, automatic implementation of bytevec 56 | //! requires that all of its underlying elements implement the `ByteEncodable` 57 | //! trait. 58 | //! 59 | //! ###The bytevec serialization format 60 | //! bytevec doesn't follow any particular serialization format. It follows simple 61 | //! rules when translating some type value to bytes: 62 | //! 63 | //! - For a primitive type such as the integral types, floating points 64 | //! or char that have fixed size, it will just grab the bytes and put them 65 | //! on a `u8` buffer of the same length as the size of the type through 66 | //! [`std::mem::transmute`][1]. These types are converted to and from little endian on 67 | //! serialization and deserialization respectively. 68 | //! 69 | //! - String and str don't store their byte count, it's up to their container (if any) 70 | //! to store the size of the byte buffer of the string. 71 | //! 72 | //! - Complex data structures such as `struct`s, tuples and collections need to store 73 | //! the sizes of their underlying data fields. These sizes are stored as values of a generic 74 | //! integral type parameter `Size` that should be provided in every call of the methods of the 75 | //! `ByteEncodable` and `ByteDecodable` traits. This type parameter is propagated to the 76 | //! serialization and deserialization operations of the contained data fields. The type parameter 77 | //! `Size` is constrained by the `BVSize` trait. Currently the types that implement this trait 78 | //! are `u8`, `u16`, `u32` and `u64`. Users should select the type for the `Size` type parameter 79 | //! according to the expected size of the byte buffer. If the expected size exceeds the 80 | //! 232 byte length limit of `u32`, use `u64` instead. 81 | //! 82 | //! - For structures with defined fields such as a custom `struct` or a tuple, 83 | //! it will store the size of each field on a sequence of `Size` values at the start 84 | //! of the slice segment for the structure, followed by the actual bytes of 85 | //! the values of the fields. 86 | //! 87 | //! - For any collection with variable length, it will first store the length 88 | //! (in elements, not byte count) on a `Size` value, followed by the byte count 89 | //! (yes, of `Size`) of each element, and then the actual values of the elements. 90 | //! All of this done in order, order is important, the same order of serialization 91 | //! is the order of deserialization. 92 | //! 93 | //! - All serializable values can be nested, so any structure that implements 94 | //! `ByteEncodable` containing a `Vec`, `String`, or another structure that also implements 95 | //! `ByteEncodable` will be serialized along all its fields. 96 | //! 97 | //! ###The `ByteDecodable` trait 98 | //! Given a byte vector retrieved from memory, a file, or maybe a TCP connection, 99 | //! the user will be able to pass the vector to the `decode` method of 100 | //! a type that implements the `ByteDecodable` trait. `decode` will do a few checks 101 | //! on the byte vector and if the required sizes matches, it will yield a type instance wrapped 102 | //! in a `BVDecodeResult`. If the size doesn't match, or if some other conversion problem 103 | //! arises, it will yield a `ByteVecError` detailing the failure. 104 | //! 105 | //! Almost all of the out of the box implementations of `ByteEncodable` also 106 | //! implement `ByteDecodable`, but some of them, particularly the slices and 107 | //! the tuple references don't make sense when deserialized, as they can't 108 | //! point to the original data they were referencing. This is usually a problem 109 | //! that requires some tweaking, but bytevec allows data conversion from byte 110 | //! buffers that were originally referenced data to a new instance of an owned data type, 111 | //! as long as the size requirements are the same. This way, slice data can 112 | //! be assigned to a `Vec` instance for example, as long as they share the same 113 | //! type of the underlying elements. 114 | //! 115 | //! The `ByteDecodable` trait also provides the `decode_max` method, which like `decode`, it 116 | //! accepts the byte buffer to deserialize, but additionally, this method also accepts 117 | //! a `limit` argument. This parameter is compared to the length of the `u8` buffer and 118 | //! if the buffer length is greater than it, it will return a `BadSizeDecodeError`, 119 | //! otherwise it will return the result of `decode` on the byte buffer. 120 | //! 121 | //! ###Example: Serialization and deserialization of a slice 122 | //! 123 | //! ```rust 124 | //! # #[macro_use] 125 | //! # extern crate bytevec; 126 | //! # 127 | //! # use bytevec::{ByteEncodable, ByteDecodable}; 128 | //! # fn main() { 129 | //! let slice = &["Rust", "Is", "Awesome!"]; 130 | //! let bytes = slice.encode::().unwrap(); 131 | //! let vec = >::decode::(&bytes).unwrap(); 132 | //! assert_eq!(vec, slice); 133 | //! # } 134 | //! ``` 135 | //! [1]: http://doc.rust-lang.org/stable/std/mem/fn.transmute.html 136 | 137 | #[macro_use] 138 | mod macros; 139 | mod traits; 140 | pub mod errors; 141 | mod impls; 142 | 143 | pub use traits::{ByteEncodable, ByteDecodable}; 144 | pub type BVEncodeResult = Result; 145 | pub type BVDecodeResult = Result; 146 | pub use impls::BVSize; -------------------------------------------------------------------------------- /src/macros.rs: -------------------------------------------------------------------------------- 1 | /// Implements the byte serialization traits for the given structures. 2 | /// 3 | /// This macro implements both the `ByteEncodable` and `ByteDecodable` traits 4 | /// for the given `struct` definitions. This macro does not declare the `struct` 5 | /// definitions, the user should either declare them separately or use the 6 | /// `bytevec_decl` trait. 7 | /// 8 | /// This trait also allows the user to create a partial implementation of the 9 | /// serialization operations for a select number of the fields of the 10 | /// structure. If the actual definition of the `struct` has more fields than 11 | /// the one provided to the macro, only the listed fields in the macro invocation 12 | /// will be serialized and deserialized. In the deserialization process, the 13 | /// rest of the fields of the `struct` will be initialized using the value 14 | /// returned from the [`Default::default()`][1] method, so the `struct` must 15 | /// implement [`Default`][2]. 16 | /// 17 | /// # Examples 18 | /// 19 | /// ```rust 20 | /// # #[macro_use] 21 | /// # extern crate bytevec; 22 | /// # 23 | /// # use bytevec::{ByteEncodable, ByteDecodable}; 24 | /// # 25 | /// #[derive(PartialEq, Eq, Debug, Default)] 26 | /// struct Vertex3d { 27 | /// x: u32, 28 | /// y: u32, 29 | /// z: u32 30 | /// } 31 | /// 32 | /// bytevec_impls! { 33 | /// impl Vertex3d { 34 | /// x: u32, 35 | /// y: u32 36 | /// } 37 | /// } 38 | /// 39 | /// fn main() { 40 | /// let p1 = Vertex3d {x: 32, y: 436, z: 0}; 41 | /// let bytes = p1.encode::().unwrap(); 42 | /// let p2 = Vertex3d::decode::(&bytes).unwrap(); 43 | /// assert_eq!(p1, p2); 44 | /// } 45 | /// ``` 46 | /// [1]: http://doc.rust-lang.org/stable/std/default/trait.Default.html#tymethod.default 47 | /// [2]: http://doc.rust-lang.org/stable/std/default/trait.Default.html 48 | #[macro_export] 49 | macro_rules! bytevec_impls { 50 | {$(impl $name:ident {$($field:ident : $t:ty),*})*} => { 51 | $( 52 | impl $crate::ByteEncodable for $name 53 | { 54 | fn get_size(&self) -> Option 55 | where Size: $crate::BVSize + $crate::ByteEncodable 56 | { 57 | let mut size = Some(Size::from_usize(0)); 58 | $( 59 | size = size.and_then(|size: Size| 60 | self.$field.get_size::().and_then(|field_size| 61 | size.checked_add(field_size).and_then( 62 | |acc_size| acc_size.checked_add( 63 | Size::get_size_of()) 64 | ) 65 | ) 66 | ); 67 | )* 68 | size 69 | } 70 | 71 | fn encode(&self) -> $crate::BVEncodeResult> 72 | where Size: $crate::BVSize + $crate::ByteEncodable 73 | { 74 | if self.get_size::().is_some() { 75 | let mut bytes = Vec::new(); 76 | $( 77 | let field_size: Option = self.$field.get_size::(); 78 | bytes.extend_from_slice(&try!( 79 | field_size.unwrap().encode::())); 80 | )* 81 | $( 82 | bytes.extend_from_slice(&try!(self.$field.encode::())); 83 | )* 84 | Ok(bytes) 85 | } else { 86 | Err($crate::errors::ByteVecError::OverflowError) 87 | } 88 | } 89 | } 90 | 91 | #[allow(dead_code, unused_assignments)] 92 | impl $crate::ByteDecodable for $name { 93 | fn decode(bytes: &[u8]) -> $crate::BVDecodeResult<$name> 94 | where Size: $crate::BVSize + $crate::ByteDecodable 95 | { 96 | let mut index = 0; 97 | let mut sizes = ::std::collections::HashMap::new(); 98 | $( 99 | if bytes[index..].len() >= Size::get_size_of().as_usize() { 100 | sizes.insert(stringify!($field), 101 | try!(Size::decode::( 102 | &bytes[index..index + Size::get_size_of().as_usize()]))); 103 | index += Size::get_size_of().as_usize(); 104 | } 105 | else { 106 | return Err($crate::errors::ByteVecError::BadSizeDecodeError { 107 | expected: $crate::errors::BVExpectedSize::MoreThan( 108 | Size::get_size_of().as_usize() + index), 109 | actual: bytes.len() 110 | }); 111 | } 112 | )* 113 | 114 | let body_size = sizes.values().fold(0, |acc, ref size| acc + size.as_usize()); 115 | if body_size == bytes[index..].len() { 116 | Ok($name { 117 | $( 118 | $field: { 119 | let size = sizes[stringify!($field)].as_usize(); 120 | let field = try!(<$t as $crate::ByteDecodable>::decode::( 121 | &bytes[index..index + size])); 122 | index += size; 123 | field 124 | }, 125 | )* 126 | ..Default::default() 127 | }) 128 | } else { 129 | Err($crate::errors::ByteVecError::BadSizeDecodeError { 130 | expected: $crate::errors::BVExpectedSize::EqualTo( 131 | Size::get_size_of().as_usize() * sizes.len() + body_size), 132 | actual: bytes.len() 133 | }) 134 | } 135 | } 136 | } 137 | )* 138 | }; 139 | } 140 | 141 | 142 | /// Declares the given structures and implements the byte serialization traits. 143 | /// 144 | /// This macro allows the user to declare an arbitrary number of structures that 145 | /// automatically implement both the `ByteEncodable` and `ByteDecodable` traits, 146 | /// as long as all of the fields also implement both traits. 147 | /// 148 | /// # Examples 149 | /// 150 | /// ```rust 151 | /// # #[macro_use] 152 | /// # extern crate bytevec; 153 | /// # 154 | /// # use bytevec::{ByteEncodable, ByteDecodable}; 155 | /// # 156 | /// bytevec_decl! { 157 | /// #[derive(PartialEq, Eq, Debug)] 158 | /// pub struct Point { 159 | /// x: u32, 160 | /// y: u32 161 | /// } 162 | /// } 163 | /// 164 | /// fn main() { 165 | /// let p1 = Point {x: 32, y: 436}; 166 | /// let bytes = p1.encode::().unwrap(); 167 | /// let p2 = Point::decode::(&bytes).unwrap(); 168 | /// assert_eq!(p1, p2); 169 | /// } 170 | /// ``` 171 | #[macro_export] 172 | macro_rules! bytevec_decl { 173 | {$($(#[$attr:meta])* struct $name:ident {$($field:ident : $t:ty),*})*} => { 174 | $( 175 | $(#[$attr])* 176 | #[derive(Default)] 177 | struct $name { 178 | $($field: $t),* 179 | } 180 | bytevec_impls!(impl $name {$($field:$t),*}); 181 | )* 182 | }; 183 | 184 | {$($(#[$attr:meta])* pub struct $name:ident {$(pub $field:ident : $t:ty),*})*} => { 185 | $( 186 | $(#[$attr])* 187 | #[derive(Default)] 188 | pub struct $name { 189 | $(pub $field: $t),* 190 | } 191 | bytevec_impls!(impl $name {$($field:$t),*}); 192 | )* 193 | }; 194 | 195 | {$($(#[$attr:meta])* pub struct $name:ident {$($field:ident : $t:ty),*})*} => { 196 | $( 197 | $(#[$attr])* 198 | #[derive(Default)] 199 | pub struct $name { 200 | $($field: $t),* 201 | } 202 | bytevec_impls!(impl $name {$($field:$t),*}); 203 | )* 204 | }; 205 | } 206 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | bytevec: A Rust serialization library that uses byte vectors 2 | ============================================================ 3 | 4 | [![Build Status](https://travis-ci.org/fero23/bytevec.svg?branch=master)](https://travis-ci.org/fero23/bytevec) 5 | [![](https://img.shields.io/crates/v/bytevec.svg)](https://crates.io/crates/bytevec) 6 | [![MIT licensed](https://img.shields.io/badge/license-MIT-blue.svg)](./LICENSE-MIT) 7 | [![Apache 2.0 licensed](https://img.shields.io/badge/license-APACHE%202.0-blue.svg)](./LICENSE-APACHE) 8 | 9 | bytevec takes advantage of Rust's concise and stable type system to 10 | serialize data objects to a byte vector (`Vec`) and back. 11 | 12 | Read the documentation [here](http://fero23.github.io/doc/bytevec/). 13 | 14 | What does it do? 15 | ---------------- 16 | Rust has a very powerful type system with predictable sizes for most 17 | types, starting with the primitive types, so it's fairly easy to convert 18 | any type to a collection of bytes and convert it back. This library intends 19 | to give the user the means of converting a given type instance to a byte vector 20 | and store it or send it through the wire to another device, with the possibility 21 | of getting the value back from the byte vector anytime using the library traits. 22 | 23 | Of course, Rust isn't magical enough to implement the traits to serialize 24 | the functions automatically, as every type has its quirks. This library 25 | uses two traits to give a type the functionality it needs to do that: 26 | `ByteEncodable` and `ByteDecodable`. 27 | 28 | ### The `ByteEncodable` trait 29 | A type that implements this trait is able to use the `encode` method that 30 | yields a `Vec` byte sequence. Seems prone to failure right? Of course it is, 31 | internally it uses `unsafe` blocks to extract the bytes of a given type, so 32 | it can be pretty unsafe. That's why it always checks for any possible error and 33 | returns the vector wrapped around a `BVEncodeResult` instance. If everything 34 | goes `Ok`, we will be able to get a byte vector value that represents the 35 | original data structure. 36 | 37 | bytevec doesn't actually do a 1:1 conversion of the bytes of the original 38 | type instance, as not every Rust type is stored on the stack. For any type 39 | that wraps a heap stored value, it will give a representation of the 40 | underlying value. 41 | 42 | bytevec implements `ByteEncodable` out of the box for the following types: 43 | - The integral types: `u8`, `u16`, `u32`, `u64`, `i8`, `i16`, `i32`, `i64` 44 | - The floating point types: `f32` and `f64` 45 | - `char`, `str` and `String` 46 | - [`Vec`](http://doc.rust-lang.org/stable/std/vec/struct.Vec.html) 47 | - [`&[T]`](http://doc.rust-lang.org/stable/std/primitive.slice.html) 48 | - [`HashMap`](http://doc.rust-lang.org/stable/std/collections/struct.HashMap.html) 49 | - [`HashSet`](http://doc.rust-lang.org/stable/std/collections/struct.HashSet.html) 50 | - Tuples with up to 12 elements 51 | - Custom `struct`s 52 | 53 | For collections and other structures, automatic implementation of bytevec 54 | requires that all of its underlying elements implement the `ByteEncodable` 55 | trait. 56 | 57 | ### The bytevec serialization format 58 | bytevec doesn't follow any particular serialization format. It follows simple 59 | rules when translating some type value to bytes: 60 | - For a primitive type such as the integral types, floating points 61 | or char that have fixed size, it will just grab the bytes and put them 62 | on a `u8` buffer of the same length as the size of the type through 63 | [`std::mem::transmute`]. These types are converted to and from little endian on 64 | serialization and deserialization respectively. 65 | - String and str don't store their byte count, it's up to their container (if any) 66 | to store the size of the byte buffer of the string. 67 | - Complex data structures such as `struct`s, tuples and collections need to store 68 | the sizes of their underlying data fields. These sizes are stored as values of a generic 69 | integral type parameter `Size` that should be provided in every call of the methods of the 70 | `ByteEncodable` and `ByteDecodable` traits. This type parameter is propagated to the 71 | serialization and deserialization operations of the contained data fields. The type parameter 72 | `Size` is constrained by the `BVSize` trait. Currently the types that implement this trait 73 | are `u8`, `u16`, `u32` and `u64`. Users should select the type for the `Size` type parameter 74 | according to the expected size of the byte buffer. If the expected size exceeds the 75 | 232 byte length limit of `u32`, use `u64` instead. 76 | - For structures with defined fields such as a custom `struct` or a tuple, 77 | it will store the size of each field on a sequence of `Size` values at the start 78 | of the slice segment for the structure, followed by the actual bytes of 79 | the values of the fields. 80 | - For any collection with variable length, it will first store the length 81 | (in elements, not byte count) on a `Size` value, followed by the byte count 82 | (yes, of `Size`) of each element, and then the actual values of the elements. 83 | All of this done in order, order is important, the same order of serialization 84 | is the order of deserialization. 85 | - All serializable values can be nested, so any structure that implements 86 | `ByteEncodable` containing a `Vec`, `String`, or another structure that also implements 87 | `ByteEncodable` will be serialized along all its fields. 88 | 89 | ### The `ByteDecodable` trait 90 | Given a byte vector retrieved from memory, a file, or maybe a TCP connection, 91 | the user will be able to pass the vector to the `decode` method of 92 | a type that implements the `ByteDecodable` trait. `decode` will do a few checks 93 | on the byte vector and if the required sizes matches, it will yield a type instance wrapped 94 | in a `BVDecodeResult`. If the size doesn't match, or if some other conversion problem 95 | arises, it will yield a `ByteVecError` detailing the failure. 96 | 97 | Almost all of the out of the box implementations of `ByteEncodable` also 98 | implement `ByteDecodable`, but some of them, particularly the slices and 99 | the tuple references don't make sense when deserialized, as they can't 100 | point to the original data they were referencing. This is usually a problem 101 | that requires some tweaking, but bytevec allows data conversion from byte 102 | buffers that were originally referenced data to a new instance of an owned data type, 103 | as long as the size requirements are the same. This way, slice data can 104 | be assigned to a `Vec` instance for example, as long as they share the same 105 | type of the underlying elements. 106 | 107 | The `ByteDecodable` trait also provides the `decode_max` method, which like `decode`, it 108 | accepts the byte buffer to deserialize, but additionally, this method also accepts 109 | a `limit` argument. This parameter is compared to the length of the `u8` buffer and 110 | if the buffer length is greater than it, it will return a `BadSizeDecodeError`, 111 | otherwise it will return the result of `decode` on the byte buffer. 112 | 113 | ### Example: Serialization and deserialization of a slice 114 | 115 | ```rust 116 | let slice = &["Rust", "Is", "Awesome!"]; 117 | let bytes = slice.encode::().unwrap(); 118 | let vec = >::decode::(&bytes).unwrap(); 119 | assert_eq!(vec, slice); 120 | ``` 121 | 122 | ### The `bytevec_decl` macro 123 | This macro allows the user to declare an arbitrary number of structures that 124 | automatically implement both the `ByteEncodable` and `ByteDecodable` traits, 125 | as long as all of the fields also implement both traits. 126 | 127 | ```rust 128 | #[macro_use] 129 | extern crate bytevec; 130 | 131 | use bytevec::{ByteEncodable, ByteDecodable}; 132 | 133 | bytevec_decl! { 134 | #[derive(PartialEq, Eq, Debug)] 135 | pub struct Point { 136 | x: u32, 137 | y: u32 138 | } 139 | } 140 | 141 | fn main() { 142 | let p1 = Point {x: 32, y: 436}; 143 | let bytes = p1.encode::().unwrap(); 144 | let p2 = Point::decode::(&bytes).unwrap(); 145 | assert_eq!(p1, p2); 146 | } 147 | ``` 148 | 149 | ### The `bytevec_impls` macro 150 | 151 | This macro implements both the `ByteEncodable` and `ByteDecodable` traits 152 | for the given `struct` definitions. This macro does not declare the `struct` 153 | definitions, the user should either declare them separately or use the 154 | `bytevec_decl` trait. 155 | 156 | This trait also allows the user to create a partial implementation of the 157 | serialization operations for a select number of the fields of the 158 | structure. If the actual definition of the `struct` has more fields than 159 | the one provided to the macro, only the listed fields in the macro invocation 160 | will be serialized and deserialized. In the deserialization process, the 161 | rest of the fields of the `struct` will be initialized using the value 162 | returned from the [`Default::default()`] method, so the `struct` must 163 | implement [`Default`]. 164 | 165 | ```rust 166 | #[macro_use] 167 | extern crate bytevec; 168 | 169 | use bytevec::{ByteEncodable, ByteDecodable}; 170 | 171 | #[derive(PartialEq, Eq, Debug, Default)] 172 | struct Vertex3d { 173 | x: u32, 174 | y: u32, 175 | z: u32 176 | } 177 | 178 | bytevec_impls! { 179 | impl Vertex3d { 180 | x: u32, 181 | y: u32 182 | } 183 | } 184 | 185 | fn main() { 186 | let p1 = Vertex3d {x: 32, y: 436, z: 0}; 187 | let bytes = p1.encode::().unwrap(); 188 | let p2 = Vertex3d::decode::(&bytes).unwrap(); 189 | assert_eq!(p1, p2); 190 | } 191 | ``` 192 | 193 | #### This all sounds like your usual serialization library, but why bother with bytes? 194 | bytevec certainly isn't for everyone. It isn't a full serialization library like 195 | [rustc_serialize] or [serde], nor is it trying to become one. This is for the people 196 | that for any reason can't handle text based serialization and just need 197 | to get some bytes fast and recreate an object out of them with low overhead through the use 198 | of a small crate with no dependencies. 199 | 200 | ## License 201 | This library is distributed under both the MIT license and the Apache License (Version 2.0). 202 | You are free to use any of them as you see fit. 203 | 204 | [`Default`]: http://doc.rust-lang.org/stable/std/default/trait.Default.html 205 | [`Default::default()`]: http://doc.rust-lang.org/stable/std/default/trait.Default.html#tymethod.default 206 | [`std::mem::transmute`]: http://doc.rust-lang.org/stable/std/mem/fn.transmute.html 207 | [rustc_serialize]: https://github.com/rust-lang-nursery/rustc-serialize 208 | [serde]: https://github.com/serde-rs/serde -------------------------------------------------------------------------------- /LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright [yyyy] [name of copyright owner] 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. -------------------------------------------------------------------------------- /src/impls/collections.rs: -------------------------------------------------------------------------------- 1 | use traits::{ByteEncodable, ByteDecodable}; 2 | use errors::{ByteVecError, BVExpectedSize}; 3 | use {BVEncodeResult, BVDecodeResult, BVSize}; 4 | use std::collections::{HashMap, HashSet}; 5 | use std::hash::Hash; 6 | 7 | macro_rules! validate_collection { 8 | ($byte_vec:ident, $index:ident, $len:ident, $size_vec:ident, $ret:expr) => {{ 9 | if $byte_vec.len() >= Size::get_size_of().as_usize() { 10 | $len = try!(Size::decode::( 11 | &$byte_vec[..Size::get_size_of().as_usize()])).as_usize(); 12 | $index = Size::get_size_of().as_usize(); 13 | let sizes_len = $len * Size::get_size_of().as_usize(); 14 | if $byte_vec[Size::get_size_of().as_usize()..].len() >= sizes_len { 15 | $size_vec = Vec::new(); 16 | for _ in 0..$len { 17 | $size_vec.push(try!(Size::decode::( 18 | &$byte_vec[$index..$index + Size::get_size_of().as_usize()]))); 19 | $index += Size::get_size_of().as_usize(); 20 | } 21 | let body_size = $size_vec.iter().fold(0, |acc, ref size| acc + size.as_usize()); 22 | if body_size == $byte_vec[Size::get_size_of().as_usize() + sizes_len..].len() { 23 | $ret 24 | } else { 25 | Err(ByteVecError::BadSizeDecodeError { 26 | expected: BVExpectedSize::EqualTo( 27 | Size::get_size_of().as_usize() + sizes_len + body_size), 28 | actual: $byte_vec.len() 29 | }) 30 | } 31 | } 32 | else { 33 | Err(ByteVecError::BadSizeDecodeError { 34 | expected: BVExpectedSize::MoreThan(Size::get_size_of().as_usize() + sizes_len), 35 | actual: $byte_vec.len() 36 | }) 37 | } 38 | } else { 39 | Err(ByteVecError::BadSizeDecodeError { 40 | expected: BVExpectedSize::MoreThan(Size::get_size_of().as_usize()), 41 | actual: $byte_vec.len() 42 | }) 43 | } 44 | }}; 45 | } 46 | 47 | impl ByteEncodable for str { 48 | fn get_size(&self) -> Option 49 | where Size: BVSize + ByteEncodable 50 | { 51 | if self.len() <= Size::max_value().as_usize() { 52 | Some(Size::from_usize(self.len())) 53 | } else { 54 | None 55 | } 56 | } 57 | 58 | fn encode(&self) -> BVEncodeResult> 59 | where Size: BVSize + ByteEncodable 60 | { 61 | if self.get_size::().is_some() { 62 | let mut bytes = Vec::new(); 63 | bytes.extend_from_slice(&self.as_bytes().to_vec()); 64 | Ok(bytes) 65 | } else { 66 | Err(ByteVecError::OverflowError) 67 | } 68 | } 69 | } 70 | 71 | impl<'a> ByteEncodable for &'a str { 72 | fn get_size(&self) -> Option 73 | where Size: BVSize + ByteEncodable 74 | { 75 | (**self).get_size::() 76 | } 77 | 78 | fn encode(&self) -> BVEncodeResult> 79 | where Size: BVSize + ByteEncodable 80 | { 81 | (**self).encode::() 82 | } 83 | } 84 | 85 | impl ByteEncodable for String { 86 | fn get_size(&self) -> Option 87 | where Size: BVSize + ByteEncodable 88 | { 89 | (**self).get_size::() 90 | } 91 | 92 | fn encode(&self) -> BVEncodeResult> 93 | where Size: BVSize + ByteEncodable 94 | { 95 | (**self).encode::() 96 | } 97 | } 98 | 99 | impl ByteDecodable for String { 100 | fn decode(bytes: &[u8]) -> BVDecodeResult 101 | where Size: BVSize + ByteDecodable 102 | { 103 | Ok(try!(::std::str::from_utf8(bytes)).to_string()) 104 | } 105 | } 106 | 107 | macro_rules! collection_encode_impl { 108 | () => { 109 | fn get_size(&self) -> Option where Size: BVSize + ByteEncodable { 110 | self.iter() 111 | .fold(Some(Size::from_usize(0)), |acc, elem| { 112 | acc.and_then(|acc: Size| { 113 | (&elem) 114 | .get_size::() 115 | .and_then(|size| { 116 | acc.checked_add(size).and_then(|acc_size| 117 | acc_size.checked_add(Size::get_size_of()) 118 | ) 119 | }) 120 | }) 121 | }) 122 | .and_then(|total: Size| total.checked_add(Size::get_size_of())) 123 | } 124 | 125 | fn encode(&self) -> BVEncodeResult> where Size: BVSize + ByteEncodable { 126 | if self.get_size::().is_some() { 127 | let mut bytes = Vec::new(); 128 | bytes.extend_from_slice(&try!((Size::from_usize(self.len())).encode::())); 129 | for elem in self { 130 | bytes.extend_from_slice(&try!( 131 | (&elem).get_size::().unwrap().encode::())); 132 | } 133 | for elem in self { 134 | bytes.extend_from_slice(&try!((&elem).encode::())); 135 | } 136 | Ok(bytes) 137 | } else { 138 | Err(ByteVecError::OverflowError) 139 | } 140 | } 141 | } 142 | } 143 | 144 | impl ByteEncodable for Vec 145 | where T: ByteEncodable 146 | { 147 | collection_encode_impl!(); 148 | } 149 | 150 | impl ByteDecodable for Vec 151 | where T: ByteDecodable 152 | { 153 | fn decode(bytes: &[u8]) -> BVDecodeResult> 154 | where Size: BVSize + ByteDecodable 155 | { 156 | let len; 157 | let mut index; 158 | let mut sizes; 159 | validate_collection!(bytes, index, len, sizes, { 160 | let mut vec = Vec::with_capacity(len); 161 | for size in sizes.into_iter() { 162 | vec.push(try!(T::decode::(&bytes[index..index + size.as_usize()]))); 163 | index += size.as_usize(); 164 | } 165 | Ok(vec) 166 | }) 167 | } 168 | } 169 | 170 | impl ByteEncodable for [T] 171 | where T: ByteEncodable 172 | { 173 | collection_encode_impl!(); 174 | } 175 | 176 | impl ByteEncodable for HashSet 177 | where T: ByteEncodable + Eq + Hash 178 | { 179 | collection_encode_impl!(); 180 | } 181 | 182 | impl ByteDecodable for HashSet 183 | where T: ByteDecodable + Eq + Hash 184 | { 185 | fn decode(bytes: &[u8]) -> BVDecodeResult> 186 | where Size: BVSize + ByteDecodable 187 | { 188 | let len; 189 | let mut index; 190 | let mut sizes; 191 | validate_collection!(bytes, index, len, sizes, { 192 | let mut set = HashSet::with_capacity(len); 193 | for size in sizes.into_iter() { 194 | set.insert(try!(T::decode::(&bytes[index..index + size.as_usize()]))); 195 | index += size.as_usize(); 196 | } 197 | Ok(set) 198 | }) 199 | } 200 | } 201 | 202 | impl ByteEncodable for HashMap 203 | where K: ByteEncodable + Hash + Eq, 204 | V: ByteEncodable 205 | { 206 | collection_encode_impl!(); 207 | } 208 | 209 | impl ByteDecodable for HashMap 210 | where K: ByteDecodable + Hash + Eq, 211 | V: ByteDecodable 212 | { 213 | fn decode(bytes: &[u8]) -> BVDecodeResult> 214 | where Size: BVSize + ByteDecodable 215 | { 216 | let len; 217 | let mut index; 218 | let mut sizes; 219 | validate_collection!(bytes, index, len, sizes, { 220 | let mut map = HashMap::with_capacity(len); 221 | for size in sizes.into_iter() { 222 | let (key, value) = try!(<(K, V)>::decode::(&bytes[index..index + 223 | size.as_usize()])); 224 | map.insert(key, value); 225 | index += size.as_usize(); 226 | } 227 | Ok(map) 228 | }) 229 | } 230 | } 231 | 232 | macro_rules! tuple_impls { 233 | ($t:ident: $elem:ident) => { 234 | impl<$t,> ByteEncodable for ($t,) 235 | where $t: ByteEncodable 236 | { 237 | fn get_size(&self) -> Option where Size: BVSize + ByteEncodable { 238 | (&(&self.0)).get_size::() 239 | } 240 | 241 | fn encode(&self) -> BVEncodeResult> where Size: BVSize + ByteEncodable { 242 | (&(&self.0)).encode::() 243 | } 244 | } 245 | 246 | impl<'a, $t,> ByteEncodable for &'a (&'a $t,) 247 | where $t: ByteEncodable 248 | { 249 | fn get_size(&self) -> Option where Size: BVSize + ByteEncodable { 250 | self.0.get_size::().and_then(|elem_size| 251 | elem_size.checked_add(Size::get_size_of())) 252 | } 253 | 254 | fn encode(&self) -> BVEncodeResult> where Size: BVSize + ByteEncodable { 255 | if self.get_size::().is_some() { 256 | let mut bytes = Vec::new(); 257 | bytes.extend_from_slice(&try!( 258 | self.0.get_size::().unwrap().encode::())); 259 | bytes.extend_from_slice(&try!(self.0.encode::())); 260 | Ok(bytes) 261 | } else { 262 | Err(ByteVecError::OverflowError) 263 | } 264 | } 265 | } 266 | 267 | impl<$t,> ByteDecodable for ($t,) 268 | where $t: ByteDecodable 269 | { 270 | fn decode(bytes: &[u8]) -> BVDecodeResult<($t,)> 271 | where Size: BVSize + ByteDecodable 272 | { 273 | let size; 274 | 275 | if bytes.len() >= Size::get_size_of().as_usize() { 276 | size = try!(Size::decode::(&bytes[..Size::get_size_of().as_usize()])); 277 | } 278 | else { 279 | return Err(ByteVecError::BadSizeDecodeError { 280 | expected: BVExpectedSize::MoreThan(Size::get_size_of().as_usize()), 281 | actual: bytes.len() 282 | }); 283 | } 284 | if size.as_usize() == bytes[Size::get_size_of().as_usize()..].len() { 285 | Ok((try!($t::decode::(&bytes[Size::get_size_of().as_usize()..])),)) 286 | } else { 287 | Err(ByteVecError::BadSizeDecodeError { 288 | expected: BVExpectedSize::EqualTo( 289 | Size::get_size_of().as_usize() + size.as_usize()), 290 | actual: bytes.len() 291 | }) 292 | } 293 | } 294 | } 295 | }; 296 | 297 | // Lots of doubled code to implement recursion by dropping the first element each iteration, 298 | // so the first operation has to be done outside the macro loop, repeating the code 299 | ($t:ident: $elem:ident, $($_t:ident: $_elem:ident),*) => { 300 | impl<$t, $($_t,)*> ByteEncodable for ($t, $($_t),*) 301 | where $t: ByteEncodable, $($_t: ByteEncodable),* 302 | { 303 | fn get_size(&self) -> Option where Size: BVSize + ByteEncodable { 304 | let &(ref $elem, $(ref $_elem),*) = self; 305 | (&($elem, $($_elem),*)).get_size::() 306 | } 307 | 308 | fn encode(&self) -> BVEncodeResult> where Size: BVSize + ByteEncodable { 309 | let &(ref $elem, $(ref $_elem),*) = self; 310 | (&($elem, $($_elem),*)).encode::() 311 | } 312 | } 313 | 314 | impl<'a, $t, $($_t,)*> ByteEncodable for &'a (&'a $t, $(&'a $_t),*) 315 | where $t: ByteEncodable, $($_t: ByteEncodable),* 316 | { 317 | fn get_size(&self) -> Option where Size: BVSize + ByteEncodable { 318 | let &&($elem, $($_elem),*) = self; 319 | let mut size = Some(Size::from_usize(0)); 320 | 321 | size = size.and_then(|size: Size| 322 | $elem.get_size::().and_then(|elem_size| 323 | size.checked_add(elem_size).and_then( 324 | |acc_size| acc_size.checked_add(Size::get_size_of()) 325 | ) 326 | ) 327 | ); 328 | $( 329 | size = size.and_then(|size: Size| 330 | $_elem.get_size::().and_then(|elem_size| 331 | size.checked_add(elem_size).and_then( 332 | |acc_size| acc_size.checked_add(Size::get_size_of()) 333 | ) 334 | ) 335 | ); 336 | )* 337 | size 338 | } 339 | 340 | fn encode(&self) -> BVEncodeResult> where Size: BVSize + ByteEncodable { 341 | if self.get_size::().is_some() { 342 | let &&($elem, $($_elem),*) = self; 343 | let mut bytes = Vec::new(); 344 | bytes.extend_from_slice(&try!( 345 | $elem.get_size::().unwrap().encode::())); 346 | $( 347 | bytes.extend_from_slice(&try!( 348 | $_elem.get_size::().unwrap().encode::())); 349 | )* 350 | bytes.extend_from_slice(&try!($elem.encode::())); 351 | $( 352 | bytes.extend_from_slice(&try!($_elem.encode::())); 353 | )* 354 | Ok(bytes) 355 | } else { 356 | Err(ByteVecError::OverflowError) 357 | } 358 | } 359 | } 360 | 361 | #[allow(unused_assignments)] 362 | impl<$t, $($_t,)*> ByteDecodable for ($t, $($_t),*) 363 | where $t: ByteDecodable, $($_t: ByteDecodable),* 364 | { 365 | fn decode(bytes: &[u8]) -> BVDecodeResult<($t, $($_t),*)> 366 | where Size: BVSize + ByteDecodable 367 | { 368 | let mut index = 0; 369 | let mut sizes = ::std::collections::HashMap::new(); 370 | 371 | if bytes.len() >= Size::get_size_of().as_usize() { 372 | sizes.insert(stringify!($elem), 373 | try!(Size::decode::(&bytes[..Size::get_size_of().as_usize()]))); 374 | index += Size::get_size_of().as_usize(); 375 | } 376 | else { 377 | return Err(ByteVecError::BadSizeDecodeError { 378 | expected: BVExpectedSize::MoreThan(Size::get_size_of().as_usize() + index), 379 | actual: bytes.len() 380 | }); 381 | } 382 | $( 383 | if bytes[index..].len() >= Size::get_size_of().as_usize() { 384 | sizes.insert(stringify!($_elem), 385 | try!(Size::decode::( 386 | &bytes[index..index + Size::get_size_of().as_usize()]))); 387 | index += Size::get_size_of().as_usize(); 388 | } 389 | else { 390 | return Err(ByteVecError::BadSizeDecodeError { 391 | expected: BVExpectedSize::MoreThan(Size::get_size_of().as_usize() + index), 392 | actual: bytes.len() 393 | }); 394 | } 395 | )* 396 | 397 | let body_size = sizes.values().fold(0, |acc, ref size| acc + size.as_usize()); 398 | if body_size == bytes[index..].len() { 399 | Ok(( 400 | { 401 | let elem = try!($t::decode::( 402 | &bytes[index..index + sizes[stringify!($elem)].as_usize()])); 403 | index += sizes[stringify!($elem)].as_usize(); 404 | elem 405 | }, 406 | $({ 407 | let elem = try!($_t::decode::( 408 | &bytes[index..index + sizes[stringify!($_elem)].as_usize()])); 409 | index += sizes[stringify!($_elem)].as_usize(); 410 | elem 411 | }),* 412 | )) 413 | } else { 414 | Err(ByteVecError::BadSizeDecodeError { 415 | expected: BVExpectedSize::EqualTo( 416 | Size::get_size_of().as_usize() * sizes.len() + body_size), 417 | actual: bytes.len() 418 | }) 419 | } 420 | } 421 | } 422 | 423 | tuple_impls!($($_t: $_elem),*); 424 | } 425 | } 426 | 427 | tuple_impls! { 428 | A: a, 429 | B: b, 430 | C: c, 431 | D: d, 432 | E: e, 433 | F: f, 434 | G: g, 435 | H: h, 436 | I: i, 437 | J: j, 438 | K: k, 439 | L: l 440 | } 441 | 442 | impl ByteEncodable for () { 443 | fn get_size(&self) -> Option 444 | where Size: BVSize + ByteEncodable 445 | { 446 | Some(Size::from_usize(0)) 447 | } 448 | 449 | fn encode(&self) -> BVEncodeResult> 450 | where Size: BVSize + ByteEncodable 451 | { 452 | // Send only size of 0 453 | Size::from_usize(0).encode::() 454 | } 455 | } 456 | 457 | impl ByteDecodable for () { 458 | fn decode(_: &[u8]) -> BVDecodeResult<()> 459 | where Size: BVSize + ByteDecodable 460 | { 461 | Ok(()) 462 | } 463 | } 464 | --------------------------------------------------------------------------------