# A fast binary serialization framework [![Documentation](https://docs.rs/speedy/badge.svg)](https://docs.rs/speedy/*/speedy/) The goal of this crate is to provide fast, simple and easy binary serialization. ## Benchmarks See [rust_serialization_benchmark](https://github.com/djkoloski/rust_serialization_benchmark) for benchmarks. ## Example ```rust use std::borrow::Cow; use speedy::{Readable, Writable, Endianness}; #[derive(PartialEq, Debug, Readable, Writable)] enum Enum { A, B, C, } #[derive(PartialEq, Debug, Readable, Writable)] struct Struct< 'a > { number: u64, string: String, vector: Vec< u8 >, cow: Cow< 'a, [i64] >, float: f32, enumeration: Enum } fn main() { let original = Struct { number: 0x12345678ABCDEF00, string: "A totally pointless string".to_owned(), vector: vec![ 1, 2, 3 ], cow: Cow::Borrowed( &[ 4, 5, 6 ] ), float: 3.1415, enumeration: Enum::C }; let bytes = original.write_to_vec().unwrap(); let deserialized: Struct = Struct::read_from_buffer( &bytes ).unwrap(); assert_eq!( original, deserialized ); } ``` ## Supported types Out-of-box the following types are supported: | Type | Serialized as | | ----------------------- | ---------------------------------------- | | `u8` | as-is | | `u16` | as-is | | `u32` | as-is | | `u64` | as-is | | `usize` | `u64` | | `i8` | as-is | | `i16` | as-is | | `i32` | as-is | | `i64` | as-is | | `f32` | as-is | | `f64` | as-is | | `bool` | `u8`, either `0` or `1` | | `char` | `u32` | | `String` | `{length: u32, bytes: [u8]}` | | `Cow<'a, str>` | `{length: u32, bytes: [u8]}` | | `Vec` | `{length: u32, values: [T]}` | | `Cow<'a, [T]>` | `{length: u32, values: [T]}` | | `HashMap` | `{length: u32, values: [K, V]}` | | `BTreeMap` | `{length: u32, values: [K, V]}` | | `HashSet` | `{length: u32, values: [T]}` | | `BTreeSet` | `{length: u32, values: [T]}` | | `Range` | `(T, T)` | | `RangeInclusive` | `(T, T)` | | `Option` | `(1_u8, T)` or `0_u8` | | `Result` | `(1_u8, T)` or `(0_u8, E)` | | `()` | nothing | | `(T)` | as-is | | `(T, T)` | as-is | | `(T, .., T)` | as-is | | `enum`s | `{tag: u32, variant: T}` | | `AtomicU8` | `u8` | | `AtomicI8` | `i8` | | `AtomicU16` | `u16` | | `AtomicI16` | `i16` | | `AtomicU32` | `u32` | | `AtomicI32` | `i32` | | `AtomicU64` | `u64` | | `AtomicI64` | `i64` | | `NonZeroU32` | `u32` | | `std::net::Ipv4Addr` | `u32` | | `std::net::Ipv6Addr` | `u128` | | `std::net::IpAddr` | `{is_ipv4: u8, value: {u32 or u128}}` | | `std::time::Duration` | `{secs: u64, subsec_nanos: u32}` | | `std::time::SystemTime` | `std::time::Duration` since `UNIX_EPOCH` | | `uuid::Uuid` | `[u8; 16]` | These are stable and will not change in the future. ## Field attributes ### `#[speedy(length = $expr)]` Can be used on most standard containers to specify the field's length. Can refer to any of the previous fields. For example: ```rust use speedy::{Readable, Writable}; #[derive(Readable, Writable)] struct Struct { byte_count: u8, #[speedy(length = byte_count / 4)] data: Vec< u32 > } ``` Before serializing you need to make sure that whatever is set as `length` is equal to the `.len()` of the field; if it's not then you will get an error when trying to serialize it. Setting this attribute changes the serialization format as follows: | Type | Serialized as | | ---------------- | ---------------------------- | | `Vec` | `[T]` | | `Cow<'a, [T]>` | `[T]` | | `String` | `[u8]` | | `Cow<'a, str>` | `[u8]` | | `HashMap` | `[K, V]` | | `BTreeMap` | `[K, V]` | | `HashSet` | `[T]` | | `BTreeSet` | `[T]` | ### `#[speedy(length_type = $ty)]` Can be used to specify the exact size of the implicit length field of a container as it is read or written. Possible values: - `u7` (same as u8, but restricted to 7 bits for `u64_varint` compatibility) - `u8` - `u16` - `u32` (default) - `u64_varint` ### `#[speedy(varint)]` Can be used only on `u64` fields. Forces the field to be serialized as a varint. ### `#[speedy(skip)]` Skips a given field when reading and writing. ### `#[speedy(default_on_eof)]` If an EOF is encountered when reading this field its value will be set to the default value for its type and the EOF will be ignored. ### `#[speedy(constant_prefix = $expr)]` Specifies a static string of bytes which will be written or has to be present when reading before a given field. ## Enum attributes ### `#[speedy(tag_type = $ty)]` Can be used to specify the exact size of the enum's tag as it is read or written. Possible values: - `u7` (same as u8, but restricted to 7 bits for `u64_varint` compatibility) - `u8` - `u16` - `u32` (default) - `u64_varint` ### `#[speedy(peek_tag)]` An enum marked with this attribute will not consume its tag value when reading from a stream, nor will it write its own tag when writing. ## Enum variant attributes ### `#[speedy(tag = $expr)]` Specifies a preset tag value to be used for a given enum variant. ## License Licensed under either of * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) at your option. ### Contribution Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.