├── msgpacker ├── README.md ├── LICENSE-MIT ├── LICENSE-APACHE ├── src │ ├── pack │ │ ├── mod.rs │ │ ├── float.rs │ │ ├── binary.rs │ │ ├── collections.rs │ │ ├── common.rs │ │ └── int.rs │ ├── unpack │ │ ├── mod.rs │ │ ├── float.rs │ │ ├── binary.rs │ │ ├── common.rs │ │ ├── collections.rs │ │ └── int.rs │ ├── error.rs │ ├── format.rs │ ├── helpers.rs │ ├── lib.rs │ └── extension.rs ├── tests │ ├── float.rs │ ├── utils │ │ └── mod.rs │ ├── common.rs │ ├── int.rs │ ├── binary.rs │ └── collections.rs └── Cargo.toml ├── .gitignore ├── msgpacker-derive ├── README.md ├── LICENSE-MIT ├── LICENSE-APACHE ├── Cargo.toml └── src │ └── lib.rs ├── Cargo.toml ├── msgpacker-bench ├── Cargo.toml ├── src │ └── lib.rs └── benches │ └── msgpacker.rs ├── .github └── workflows │ └── ci.yml ├── LICENSE-MIT ├── README.md └── LICENSE-APACHE /msgpacker/README.md: -------------------------------------------------------------------------------- 1 | ../README.md -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | Cargo.lock 3 | -------------------------------------------------------------------------------- /msgpacker-derive/README.md: -------------------------------------------------------------------------------- 1 | ../README.md -------------------------------------------------------------------------------- /msgpacker/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | ../LICENSE-MIT -------------------------------------------------------------------------------- /msgpacker-derive/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | ../LICENSE-MIT -------------------------------------------------------------------------------- /msgpacker/LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | ../LICENSE-APACHE -------------------------------------------------------------------------------- /msgpacker-derive/LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | ../LICENSE-APACHE -------------------------------------------------------------------------------- /msgpacker/src/pack/mod.rs: -------------------------------------------------------------------------------- 1 | use super::{Format, Packable}; 2 | 3 | mod binary; 4 | mod collections; 5 | mod common; 6 | mod float; 7 | mod int; 8 | 9 | pub use collections::{pack_array, pack_map}; 10 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | resolver = "2" 3 | members = [ 4 | "msgpacker", 5 | "msgpacker-bench", 6 | "msgpacker-derive" 7 | ] 8 | 9 | [profile.bench] 10 | lto = true 11 | incremental = false 12 | codegen-units = 1 13 | -------------------------------------------------------------------------------- /msgpacker/tests/float.rs: -------------------------------------------------------------------------------- 1 | use proptest::prelude::*; 2 | 3 | mod utils; 4 | 5 | proptest! { 6 | #[test] 7 | fn f32(x: f32) { 8 | utils::case(x); 9 | } 10 | 11 | #[test] 12 | fn f64(x: f64) { 13 | utils::case(x); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /msgpacker/src/unpack/mod.rs: -------------------------------------------------------------------------------- 1 | use super::{helpers, Error, Format, Unpackable}; 2 | 3 | #[cfg(feature = "alloc")] 4 | mod binary; 5 | mod collections; 6 | mod common; 7 | mod float; 8 | mod int; 9 | 10 | pub use collections::{unpack_array, unpack_array_iter, unpack_map, unpack_map_iter}; 11 | -------------------------------------------------------------------------------- /msgpacker/tests/utils/mod.rs: -------------------------------------------------------------------------------- 1 | use msgpacker::prelude::*; 2 | 3 | #[allow(unused)] 4 | pub fn case(x: T) 5 | where 6 | T: Packable + Unpackable + PartialEq + core::fmt::Debug, 7 | ::Error: core::fmt::Debug, 8 | { 9 | let mut bytes = vec![]; 10 | let n = x.pack(&mut bytes); 11 | assert_eq!(n, bytes.len()); 12 | let (o, y) = T::unpack(&bytes).unwrap(); 13 | let (p, z) = T::unpack_iter(bytes).unwrap(); 14 | assert_eq!(n, o); 15 | assert_eq!(n, p); 16 | assert_eq!(x, y); 17 | assert_eq!(x, z); 18 | } 19 | -------------------------------------------------------------------------------- /msgpacker/src/pack/float.rs: -------------------------------------------------------------------------------- 1 | use super::{Format, Packable}; 2 | use core::iter; 3 | 4 | impl Packable for f32 { 5 | fn pack(&self, buf: &mut T) -> usize 6 | where 7 | T: Extend, 8 | { 9 | buf.extend(iter::once(Format::FLOAT32).chain(self.to_be_bytes())); 10 | 5 11 | } 12 | } 13 | 14 | impl Packable for f64 { 15 | fn pack(&self, buf: &mut T) -> usize 16 | where 17 | T: Extend, 18 | { 19 | buf.extend(iter::once(Format::FLOAT64).chain(self.to_be_bytes())); 20 | 9 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /msgpacker-bench/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "msgpacker-bench" 3 | version = "0.0.0" 4 | authors = ["Victor Lopez "] 5 | edition = "2021" 6 | repository = "https://github.com/codx-dev/msgpacker" 7 | description = "Benchmarks for msgpacker." 8 | publish = false 9 | 10 | [dependencies] 11 | msgpacker = { path = "../msgpacker" } 12 | rmp-serde = "1.1" 13 | serde = { version = "1.0", features = ["derive"] } 14 | rand = "0.8" 15 | 16 | [dev-dependencies] 17 | criterion = { version = "0.5", features = ["html_reports"] } 18 | 19 | [[bench]] 20 | name = "msgpacker" 21 | harness = false 22 | -------------------------------------------------------------------------------- /msgpacker-derive/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "msgpacker-derive" 3 | version = "0.3.2" 4 | authors = ["Victor Lopez "] 5 | categories = ["compression", "encoding", "parser-implementations"] 6 | edition = "2021" 7 | keywords = ["messagepack", "msgpack"] 8 | license = "MIT/Apache-2.0" 9 | readme = "README.md" 10 | repository = "https://github.com/codx-dev/msgpacker" 11 | description = "Derive macros for the MessagePack protocol implementation for Rust." 12 | 13 | [lib] 14 | proc-macro = true 15 | 16 | [dependencies] 17 | quote = "1.0" 18 | syn = { version = "2.0", features = ["full"] } 19 | -------------------------------------------------------------------------------- /msgpacker/tests/common.rs: -------------------------------------------------------------------------------- 1 | use msgpacker::prelude::*; 2 | use proptest::prelude::*; 3 | 4 | mod utils; 5 | 6 | #[test] 7 | fn nil() { 8 | utils::case(()); 9 | } 10 | 11 | #[test] 12 | fn bool() { 13 | utils::case(true); 14 | utils::case(false); 15 | } 16 | 17 | #[derive(Debug, Clone, PartialEq, Eq, Hash, MsgPacker, proptest_derive::Arbitrary)] 18 | pub enum Foo { 19 | Bar, 20 | Baz(u32, String), 21 | Qux { a: Vec, b: u64 }, 22 | } 23 | 24 | proptest! { 25 | #[test] 26 | fn array(a: [i32; 4]) { 27 | utils::case(a); 28 | } 29 | 30 | #[test] 31 | fn tuple(a: (i32, String, bool, usize)) { 32 | utils::case(a); 33 | } 34 | 35 | #[test] 36 | fn enum_foo(a: Foo) { 37 | utils::case(a); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /msgpacker/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "msgpacker" 3 | version = "0.4.8" 4 | authors = ["Victor Lopez "] 5 | categories = ["compression", "encoding", "parser-implementations"] 6 | edition = "2021" 7 | keywords = ["messagepack", "msgpack"] 8 | license = "MIT/Apache-2.0" 9 | readme = "README.md" 10 | repository = "https://github.com/codx-dev/msgpacker" 11 | description = "MessagePack protocol implementation for Rust." 12 | 13 | [dependencies] 14 | msgpacker-derive = { version = "0.3", optional = true } 15 | 16 | [dev-dependencies] 17 | proptest = "1.2" 18 | proptest-derive = "0.3" 19 | 20 | [features] 21 | default = ["std", "derive"] 22 | alloc = [] 23 | derive = ["msgpacker-derive"] 24 | strict = [] 25 | std = ["alloc"] 26 | 27 | [[test]] 28 | name = "collections" 29 | required-features = ["derive"] 30 | -------------------------------------------------------------------------------- /msgpacker/src/error.rs: -------------------------------------------------------------------------------- 1 | use core::fmt; 2 | 3 | /// Deserialization errors for the protocol implementation. 4 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 5 | pub enum Error { 6 | /// The provided buffer is too short and yielded an unexpected EOF. 7 | BufferTooShort, 8 | /// The enum variant is not valid for the static type. 9 | InvalidEnumVariant, 10 | /// The extension is not in accordance to the protocol definition. 11 | InvalidExtension, 12 | /// The string is not a valid UTF-8. 13 | InvalidUtf8, 14 | /// The protocol format tag is not valid. 15 | UnexpectedFormatTag, 16 | /// The provided bin length is not valid. 17 | UnexpectedBinLength, 18 | } 19 | 20 | impl fmt::Display for Error { 21 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 22 | fmt::Debug::fmt(self, f) 23 | } 24 | } 25 | 26 | impl core::error::Error for Error {} 27 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: Test nightly 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | tags: 8 | - v* 9 | pull_request: 10 | 11 | jobs: 12 | build: 13 | runs-on: ubuntu-latest 14 | 15 | steps: 16 | - name: Checkout repository 17 | uses: actions/checkout@v2 18 | 19 | - name: Install toolchain 20 | uses: actions-rs/toolchain@v1 21 | with: 22 | profile: minimal 23 | toolchain: nightly 24 | override: true 25 | 26 | - name: Install rustfmt 27 | run: rustup component add rustfmt 28 | 29 | - name: Check formatting 30 | uses: actions-rs/cargo@v1 31 | with: 32 | command: fmt 33 | args: --all --verbose -- --check 34 | 35 | - name: Run tests 36 | uses: actions-rs/cargo@v1 37 | with: 38 | command: test 39 | args: --verbose 40 | 41 | - name: Docs 42 | uses: actions-rs/cargo@v1 43 | with: 44 | command: doc 45 | args: --no-deps 46 | -------------------------------------------------------------------------------- /msgpacker/tests/int.rs: -------------------------------------------------------------------------------- 1 | use proptest::prelude::*; 2 | 3 | mod utils; 4 | 5 | proptest! { 6 | #[test] 7 | fn u8(x: u8) { 8 | utils::case(x); 9 | } 10 | 11 | #[test] 12 | fn u16(x: u16) { 13 | utils::case(x); 14 | } 15 | 16 | #[test] 17 | fn u32(x: u32) { 18 | utils::case(x); 19 | } 20 | 21 | #[test] 22 | fn u64(x: u64) { 23 | utils::case(x); 24 | } 25 | 26 | #[test] 27 | fn u128(x: u128) { 28 | utils::case(x); 29 | } 30 | 31 | #[test] 32 | fn usize(x: usize) { 33 | utils::case(x); 34 | } 35 | 36 | #[test] 37 | fn i8(x: i8) { 38 | utils::case(x); 39 | } 40 | 41 | #[test] 42 | fn i16(x: i16) { 43 | utils::case(x); 44 | } 45 | 46 | #[test] 47 | fn i32(x: i32) { 48 | utils::case(x); 49 | } 50 | 51 | #[test] 52 | fn i64(x: i64) { 53 | utils::case(x); 54 | } 55 | 56 | #[test] 57 | fn i128(x: i128) { 58 | utils::case(x); 59 | } 60 | 61 | #[test] 62 | fn isize(x: isize) { 63 | utils::case(x); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016 Maciej Hirsz 2 | 3 | The MIT License (MIT) 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 | -------------------------------------------------------------------------------- /msgpacker/src/format.rs: -------------------------------------------------------------------------------- 1 | pub struct Format {} 2 | 3 | impl Format { 4 | pub const NIL: u8 = 0xc0; 5 | pub const TRUE: u8 = 0xc3; 6 | pub const FALSE: u8 = 0xc2; 7 | pub const POSITIVE_FIXINT: u8 = 0x7f; 8 | pub const UINT8: u8 = 0xcc; 9 | pub const UINT16: u8 = 0xcd; 10 | pub const UINT32: u8 = 0xce; 11 | pub const UINT64: u8 = 0xcf; 12 | pub const INT8: u8 = 0xd0; 13 | pub const INT16: u8 = 0xd1; 14 | pub const INT32: u8 = 0xd2; 15 | pub const INT64: u8 = 0xd3; 16 | pub const FLOAT32: u8 = 0xca; 17 | pub const FLOAT64: u8 = 0xcb; 18 | pub const BIN8: u8 = 0xc4; 19 | pub const BIN16: u8 = 0xc5; 20 | pub const BIN32: u8 = 0xc6; 21 | pub const STR8: u8 = 0xd9; 22 | pub const STR16: u8 = 0xda; 23 | pub const STR32: u8 = 0xdb; 24 | pub const ARRAY16: u8 = 0xdc; 25 | pub const ARRAY32: u8 = 0xdd; 26 | pub const MAP16: u8 = 0xde; 27 | pub const MAP32: u8 = 0xdf; 28 | } 29 | 30 | #[cfg(feature = "alloc")] 31 | impl Format { 32 | pub const FIXEXT1: u8 = 0xd4; 33 | pub const FIXEXT2: u8 = 0xd5; 34 | pub const FIXEXT4: u8 = 0xd6; 35 | pub const FIXEXT8: u8 = 0xd7; 36 | pub const FIXEXT16: u8 = 0xd8; 37 | pub const EXT8: u8 = 0xc7; 38 | pub const EXT16: u8 = 0xc8; 39 | pub const EXT32: u8 = 0xc9; 40 | } 41 | -------------------------------------------------------------------------------- /msgpacker/tests/binary.rs: -------------------------------------------------------------------------------- 1 | use msgpacker::prelude::*; 2 | use proptest::prelude::*; 3 | 4 | mod utils; 5 | 6 | #[test] 7 | fn empty_vec() { 8 | let v = vec![]; 9 | let mut bytes = vec![]; 10 | let n = v.pack(&mut bytes); 11 | let (o, x) = Vec::::unpack(&bytes).unwrap(); 12 | let (p, y) = Vec::::unpack_iter(bytes).unwrap(); 13 | assert_eq!(o, n); 14 | assert_eq!(p, n); 15 | assert_eq!(v, x); 16 | assert_eq!(v, y); 17 | } 18 | 19 | #[test] 20 | fn empty_str() { 21 | let s = ""; 22 | let mut bytes = vec![]; 23 | let n = s.pack(&mut bytes); 24 | let (o, x) = String::unpack(&bytes).unwrap(); 25 | let (p, y) = String::unpack_iter(bytes).unwrap(); 26 | assert_eq!(o, n); 27 | assert_eq!(p, n); 28 | assert_eq!(s, x); 29 | assert_eq!(s, y); 30 | } 31 | 32 | proptest! { 33 | #[test] 34 | fn vec(v: Vec) { 35 | utils::case(v); 36 | } 37 | 38 | #[test] 39 | fn str(s: String) { 40 | utils::case(s); 41 | } 42 | 43 | #[test] 44 | #[ignore] 45 | fn large_vec(v in prop::collection::vec(any::(), 0..=u16::MAX as usize * 2)) { 46 | utils::case(v); 47 | } 48 | 49 | #[test] 50 | #[ignore] 51 | fn large_str(v in prop::collection::vec(any::(), 0..=u16::MAX as usize * 2)) { 52 | utils::case(v.into_iter().collect::()); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /msgpacker/src/helpers.rs: -------------------------------------------------------------------------------- 1 | use super::Error; 2 | 3 | pub fn take_byte_iter(mut bytes: I) -> Result 4 | where 5 | I: Iterator, 6 | { 7 | bytes.next().ok_or(Error::BufferTooShort) 8 | } 9 | 10 | pub fn take_byte(buf: &mut &[u8]) -> Result { 11 | if buf.is_empty() { 12 | return Err(Error::BufferTooShort); 13 | } 14 | let (l, r) = buf.split_at(1); 15 | *buf = r; 16 | Ok(l[0]) 17 | } 18 | 19 | pub fn take_num(buf: &mut &[u8], f: fn([u8; N]) -> V) -> Result { 20 | if buf.len() < N { 21 | return Err(Error::BufferTooShort); 22 | } 23 | let (l, r) = buf.split_at(N); 24 | *buf = r; 25 | // Safety: l.len() == N 26 | let val = unsafe { <[u8; N]>::try_from(l).unwrap_unchecked() }; 27 | Ok(f(val)) 28 | } 29 | 30 | #[cfg(feature = "alloc")] 31 | pub fn take_buffer<'a>(buf: &mut &'a [u8], len: usize) -> Result<&'a [u8], Error> { 32 | if buf.len() < len { 33 | return Err(Error::BufferTooShort); 34 | } 35 | let (l, r) = buf.split_at(len); 36 | *buf = r; 37 | Ok(l) 38 | } 39 | 40 | pub fn take_num_iter(bytes: I, f: fn([u8; N]) -> V) -> Result 41 | where 42 | I: Iterator, 43 | { 44 | let mut array = [0u8; N]; 45 | let mut i = 0; 46 | 47 | for b in bytes { 48 | array[i] = b; 49 | i += 1; 50 | 51 | if i == N { 52 | break; 53 | } 54 | } 55 | 56 | if i < N { 57 | return Err(Error::BufferTooShort); 58 | } 59 | 60 | Ok(f(array)) 61 | } 62 | 63 | #[cfg(feature = "alloc")] 64 | pub fn take_buffer_iter(bytes: I, len: usize) -> Result, Error> 65 | where 66 | I: Iterator, 67 | { 68 | let v: alloc::vec::Vec<_> = bytes.take(len).collect(); 69 | if v.len() < len { 70 | return Err(Error::BufferTooShort); 71 | } 72 | Ok(v) 73 | } 74 | -------------------------------------------------------------------------------- /msgpacker/tests/collections.rs: -------------------------------------------------------------------------------- 1 | use core::marker::PhantomData; 2 | use msgpacker::prelude::*; 3 | use proptest::prelude::*; 4 | use std::collections::HashMap; 5 | 6 | mod utils; 7 | 8 | #[derive( 9 | Debug, 10 | Default, 11 | Clone, 12 | PartialEq, 13 | Eq, 14 | PartialOrd, 15 | Ord, 16 | Hash, 17 | MsgPacker, 18 | proptest_derive::Arbitrary, 19 | )] 20 | struct Value { 21 | pub t00: Option, 22 | pub t01: Option, 23 | pub t02: Option, 24 | pub t03: Option, 25 | pub t04: Option, 26 | pub t05: Option, 27 | pub t06: Option, 28 | pub t07: Option, 29 | pub t08: Option, 30 | pub t09: Option, 31 | pub t10: (), 32 | pub t11: PhantomData, 33 | pub t12: Option, 34 | pub t13: Option>, 35 | pub t14: Option, 36 | } 37 | 38 | proptest! { 39 | #[test] 40 | fn array(value: Vec) { 41 | let mut bytes = Vec::new(); 42 | let n = msgpacker::pack_array(&mut bytes, &value); 43 | assert_eq!(n, bytes.len()); 44 | let (o, x): (usize, Vec) = msgpacker::unpack_array(&bytes).unwrap(); 45 | let (p, y): (usize, Vec) = msgpacker::unpack_array_iter(bytes).unwrap(); 46 | assert_eq!(n, o); 47 | assert_eq!(n, p); 48 | assert_eq!(value, x); 49 | assert_eq!(value, y); 50 | } 51 | 52 | #[test] 53 | fn map(map: HashMap) { 54 | let mut bytes = Vec::new(); 55 | let n = msgpacker::pack_map(&mut bytes, &map); 56 | assert_eq!(n, bytes.len()); 57 | let (o, x): (usize, HashMap) = msgpacker::unpack_map(&bytes).unwrap(); 58 | let (p, y): (usize, HashMap) = msgpacker::unpack_map_iter(bytes).unwrap(); 59 | assert_eq!(n, o); 60 | assert_eq!(n, p); 61 | assert_eq!(map, x); 62 | assert_eq!(map, y); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /msgpacker/src/unpack/float.rs: -------------------------------------------------------------------------------- 1 | use super::{ 2 | helpers::{take_byte, take_byte_iter, take_num, take_num_iter}, 3 | Error, Format, Unpackable, 4 | }; 5 | 6 | impl Unpackable for f32 { 7 | type Error = Error; 8 | 9 | fn unpack(mut buf: &[u8]) -> Result<(usize, Self), Self::Error> { 10 | let format = take_byte(&mut buf)?; 11 | if format != Format::FLOAT32 { 12 | return Err(Error::UnexpectedFormatTag); 13 | } 14 | Ok((5, take_num(&mut buf, f32::from_be_bytes)?)) 15 | } 16 | 17 | fn unpack_iter(bytes: I) -> Result<(usize, Self), Self::Error> 18 | where 19 | I: IntoIterator, 20 | { 21 | let mut bytes = bytes.into_iter(); 22 | let format = take_byte_iter(bytes.by_ref())?; 23 | if format != Format::FLOAT32 { 24 | return Err(Error::UnexpectedFormatTag); 25 | } 26 | Ok((5, take_num_iter(bytes.by_ref(), f32::from_be_bytes)?)) 27 | } 28 | } 29 | 30 | impl Unpackable for f64 { 31 | type Error = Error; 32 | 33 | fn unpack(mut buf: &[u8]) -> Result<(usize, Self), Self::Error> { 34 | let format = take_byte(&mut buf)?; 35 | match format { 36 | Format::FLOAT32 => Ok((5, take_num(&mut buf, f32::from_be_bytes)? as f64)), 37 | Format::FLOAT64 => Ok((9, take_num(&mut buf, f64::from_be_bytes)?)), 38 | _ => Err(Error::UnexpectedFormatTag), 39 | } 40 | } 41 | 42 | fn unpack_iter(bytes: I) -> Result<(usize, Self), Self::Error> 43 | where 44 | I: IntoIterator, 45 | { 46 | let mut bytes = bytes.into_iter(); 47 | let format = take_byte_iter(bytes.by_ref())?; 48 | match format { 49 | Format::FLOAT32 => Ok((5, take_num_iter(bytes.by_ref(), f32::from_be_bytes)? as f64)), 50 | Format::FLOAT64 => Ok((9, take_num_iter(bytes.by_ref(), f64::from_be_bytes)?)), 51 | _ => Err(Error::UnexpectedFormatTag), 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /msgpacker-bench/src/lib.rs: -------------------------------------------------------------------------------- 1 | use core::marker::PhantomData; 2 | use rand::{ 3 | distributions::{Alphanumeric, Standard}, 4 | prelude::*, 5 | }; 6 | use serde::{Deserialize, Serialize}; 7 | 8 | #[derive( 9 | Debug, 10 | Default, 11 | Clone, 12 | PartialEq, 13 | Eq, 14 | PartialOrd, 15 | Ord, 16 | Hash, 17 | msgpacker::MsgPacker, 18 | Serialize, 19 | Deserialize, 20 | )] 21 | pub struct Value { 22 | pub t00: Option, 23 | pub t01: Option, 24 | pub t02: Option, 25 | pub t03: Option, 26 | pub t04: Option, 27 | pub t05: Option, 28 | pub t06: Option, 29 | pub t07: Option, 30 | pub t08: Option, 31 | pub t09: Option, 32 | pub t10: (), 33 | pub t11: PhantomData, 34 | pub t12: Option, 35 | pub t13: Option>, 36 | pub t14: Option, 37 | } 38 | 39 | impl Distribution for Standard { 40 | fn sample(&self, rng: &mut R) -> Value { 41 | let max = u16::MAX as usize + 1024; 42 | let len_bin = rng.gen_range(0..max); 43 | let len_txt = rng.gen_range(0..max); 44 | Value { 45 | t00: rng.gen(), 46 | t01: rng.gen(), 47 | t02: rng.gen(), 48 | t03: rng.gen(), 49 | t04: rng.gen(), 50 | t05: rng.gen(), 51 | t06: rng.gen(), 52 | t07: rng.gen(), 53 | t08: rng.gen(), 54 | t09: rng.gen(), 55 | t10: (), 56 | t11: PhantomData, 57 | t12: rng.gen(), 58 | t13: rng 59 | .gen::() 60 | .then(|| rng.sample_iter(&Standard).take(len_bin).collect()), 61 | t14: rng.gen::().then(|| { 62 | rng.sample_iter(&Alphanumeric) 63 | .map(char::from) 64 | .take(len_txt) 65 | .collect() 66 | }), 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /msgpacker/src/pack/binary.rs: -------------------------------------------------------------------------------- 1 | use super::{Format, Packable}; 2 | use core::iter; 3 | 4 | impl Packable for [u8] { 5 | #[allow(unreachable_code)] 6 | fn pack(&self, buf: &mut T) -> usize 7 | where 8 | T: Extend, 9 | { 10 | let n = if self.len() <= u8::MAX as usize { 11 | buf.extend(iter::once(Format::BIN8).chain(iter::once(self.len() as u8))); 12 | 2 13 | } else if self.len() <= u16::MAX as usize { 14 | buf.extend(iter::once(Format::BIN16).chain((self.len() as u16).to_be_bytes())); 15 | 3 16 | } else if self.len() <= u32::MAX as usize { 17 | buf.extend(iter::once(Format::BIN32).chain((self.len() as u32).to_be_bytes())); 18 | 5 19 | } else { 20 | #[cfg(feature = "strict")] 21 | panic!("strict serialization enabled; the buffer is too large"); 22 | return 0; 23 | }; 24 | buf.extend(self.iter().copied()); 25 | n + self.len() 26 | } 27 | } 28 | 29 | #[allow(unreachable_code)] 30 | impl Packable for str { 31 | fn pack(&self, buf: &mut T) -> usize 32 | where 33 | T: Extend, 34 | { 35 | let n = if self.len() <= 31 { 36 | buf.extend(iter::once((self.len() as u8 & 0x1f) | 0xa0)); 37 | 1 38 | } else if self.len() <= u8::MAX as usize { 39 | buf.extend(iter::once(Format::STR8).chain(iter::once(self.len() as u8))); 40 | 2 41 | } else if self.len() <= u16::MAX as usize { 42 | buf.extend(iter::once(Format::STR16).chain((self.len() as u16).to_be_bytes())); 43 | 3 44 | } else if self.len() <= u32::MAX as usize { 45 | buf.extend(iter::once(Format::STR32).chain((self.len() as u32).to_be_bytes())); 46 | 5 47 | } else { 48 | #[cfg(feature = "strict")] 49 | panic!("strict serialization enabled; the buffer is too large"); 50 | return 0; 51 | }; 52 | buf.extend(self.as_bytes().iter().copied()); 53 | n + self.len() 54 | } 55 | } 56 | 57 | #[cfg(feature = "alloc")] 58 | mod alloc { 59 | use super::*; 60 | use ::alloc::{string::String, vec::Vec}; 61 | 62 | impl Packable for Vec { 63 | fn pack(&self, buf: &mut T) -> usize 64 | where 65 | T: Extend, 66 | { 67 | self.as_slice().pack(buf) 68 | } 69 | } 70 | 71 | impl Packable for String { 72 | fn pack(&self, buf: &mut T) -> usize 73 | where 74 | T: Extend, 75 | { 76 | self.as_str().pack(buf) 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /msgpacker-bench/benches/msgpacker.rs: -------------------------------------------------------------------------------- 1 | use criterion::{black_box, criterion_group, criterion_main, BatchSize, Criterion}; 2 | use msgpacker_bench::Value; 3 | use rand::{distributions::Standard, prelude::*}; 4 | use rmp_serde::{decode::Deserializer, encode::Serializer}; 5 | use serde::{Deserialize, Serialize}; 6 | 7 | pub fn pack(c: &mut Criterion) { 8 | let values: Vec = StdRng::from_seed([0xfa; 32]) 9 | .sample_iter(&Standard) 10 | .take(1000) 11 | .collect(); 12 | 13 | let counts = [1, 10, 100, 1000]; 14 | 15 | // preallocate the required bytes 16 | let mut bufs_msgpacker = Vec::new(); 17 | let mut bufs_rmps = Vec::new(); 18 | for count in counts { 19 | let mut buf = Vec::new(); 20 | msgpacker::pack_array(&mut buf, values.iter().take(count)); 21 | bufs_msgpacker.push(buf); 22 | 23 | let mut buf = Vec::new(); 24 | let mut serializer = Serializer::new(&mut buf); 25 | (&values[..count]).serialize(&mut serializer).unwrap(); 26 | bufs_rmps.push(buf); 27 | } 28 | 29 | let mut group = c.benchmark_group("pack"); 30 | 31 | for (i, count) in counts.iter().enumerate() { 32 | group.bench_with_input( 33 | format!("msgpacker {count}"), 34 | &(&values[..*count], bufs_msgpacker[i].capacity()), 35 | |b, (val, buf)| { 36 | b.iter_batched( 37 | || Vec::with_capacity(*buf), 38 | |mut buf| msgpacker::pack_array(black_box(&mut buf), black_box(val.iter())), 39 | BatchSize::LargeInput, 40 | ); 41 | }, 42 | ); 43 | 44 | group.bench_with_input( 45 | format!("rmps {count}"), 46 | &(&values[..*count], bufs_rmps[i].capacity()), 47 | |b, (val, buf)| { 48 | b.iter_batched( 49 | || Vec::with_capacity(*buf), 50 | |mut buf| { 51 | black_box(val) 52 | .serialize(black_box(&mut Serializer::new(&mut buf))) 53 | .unwrap() 54 | }, 55 | BatchSize::LargeInput, 56 | ); 57 | }, 58 | ); 59 | } 60 | 61 | group.finish(); 62 | 63 | let mut group = c.benchmark_group("unpack"); 64 | 65 | for (i, count) in counts.iter().enumerate() { 66 | group.bench_with_input( 67 | format!("msgpacker {count}"), 68 | &bufs_msgpacker[i], 69 | |b, buf| { 70 | b.iter(|| msgpacker::unpack_array::>(black_box(buf))); 71 | }, 72 | ); 73 | 74 | group.bench_with_input(format!("rmps {count}"), &bufs_rmps[i], |b, buf| { 75 | b.iter(|| { 76 | >::deserialize(&mut Deserializer::new(black_box(&buf[..]))).unwrap() 77 | }); 78 | }); 79 | } 80 | 81 | group.finish(); 82 | } 83 | 84 | criterion_group!(benches, pack); 85 | criterion_main!(benches); 86 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MessagePacker - a no-std msgpack implementation 2 | 3 | [![crates.io](https://img.shields.io/crates/v/msgpacker?label=latest)](https://crates.io/crates/msgpacker) 4 | [![Documentation](https://docs.rs/msgpacker/badge.svg)](https://docs.rs/msgpacker/) 5 | [![License](https://img.shields.io/crates/l/msgpacker.svg)]() 6 | 7 | The protocol specification can be found [here](https://github.com/msgpack/msgpack/blob/master/spec.md). 8 | 9 | This crate targets simplicity and performance. No dependencies are used, just the standard Rust library. 10 | 11 | It will implement `Packable` and `Unpackable` for Rust atomic types. The traits can also be implemented manually. 12 | 13 | ## Features 14 | 15 | - alloc: Implements the functionality for `Vec`, `String`, and unlocks custom extensions. 16 | - derive: Enables `MsgPacker` derive convenience macro. 17 | - strict: Will panic if there is a protocol violation of the size of a buffer; the maximum allowed size is `u32::MAX`. 18 | - std: Will implement the `Packable` and `Unpackable` for `std` collections. 19 | 20 | ## Example 21 | 22 | ```rust 23 | use msgpacker::prelude::*; 24 | use std::collections::HashMap; 25 | 26 | // boilerplate derives - those aren't required 27 | #[derive(Debug, PartialEq, Eq)] 28 | // this convenience derive macro will implement `Packable` and `Unpackable` 29 | #[derive(MsgPacker)] 30 | pub struct City { 31 | name: String, 32 | 33 | // The traits are implemented for stdlib collections. If you have a custom map, you can use the 34 | // directive `#[msgpacker(map)]` so the traits will be automatically implemented through the 35 | // iterators of the map. 36 | inhabitants_per_street: HashMap, 37 | 38 | // This is also automatically implemented. The manual implementation is via `#[msgpacker(array)]`. 39 | zones: Vec, 40 | } 41 | 42 | // create an instance of a city. 43 | let city = City { 44 | name: "Kuala Lumpur".to_string(), 45 | inhabitants_per_street: HashMap::from([ 46 | ("Street 1".to_string(), 10), 47 | ("Street 2".to_string(), 20), 48 | ]), 49 | zones: vec!["Zone 1".to_string(), "Zone 2".to_string()], 50 | }; 51 | 52 | // serialize the city into bytes 53 | let mut buf = Vec::new(); 54 | let n = city.pack(&mut buf); 55 | println!("serialized {} bytes", n); 56 | 57 | // deserialize the city and assert correctness 58 | let (n, deserialized) = City::unpack(&buf).unwrap(); 59 | println!("deserialized {} bytes", n); 60 | assert_eq!(city, deserialized); 61 | ``` 62 | 63 | ## Benchmarks 64 | 65 | Results obtained with `Intel(R) Core(TM) i9-9900X CPU @ 3.50GHz`. 66 | 67 | The simplicity of the implementation unlocks a performance more than ~10x better than [rmp-serde](https://crates.io/crates/rmp-serde). 68 | 69 | 70 | #### Pack 1.000 elements 71 | 72 | ![image](https://github.com/codx-dev/msgpacker/assets/8730839/ef69622d-0e2f-4bb1-b47c-6412d89fc19a) 73 | ![image](https://github.com/codx-dev/msgpacker/assets/8730839/ce2de037-252a-4c90-b429-430d131ccf7e) 74 | 75 | #### Unpack 1.000 elements 76 | 77 | ![image](https://github.com/codx-dev/msgpacker/assets/8730839/5576f99d-6f37-4907-89db-5d666b13f9d5) 78 | ![image](https://github.com/codx-dev/msgpacker/assets/8730839/234c31d2-f319-414b-9418-4103e97d0a9c) 79 | -------------------------------------------------------------------------------- /msgpacker/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![cfg_attr(not(feature = "std"), no_std)] 2 | #![warn(missing_docs)] 3 | #![doc = include_str!("../README.md")] 4 | 5 | #[cfg(feature = "alloc")] 6 | extern crate alloc; 7 | 8 | #[cfg(feature = "alloc")] 9 | mod extension; 10 | 11 | mod error; 12 | mod format; 13 | mod helpers; 14 | mod pack; 15 | mod unpack; 16 | 17 | pub use error::Error; 18 | use format::Format; 19 | pub use pack::{pack_array, pack_map}; 20 | pub use unpack::{unpack_array, unpack_array_iter, unpack_map, unpack_map_iter}; 21 | 22 | #[cfg(feature = "alloc")] 23 | pub use extension::Extension; 24 | 25 | #[cfg(feature = "alloc")] 26 | use alloc::vec::Vec; 27 | 28 | #[cfg(feature = "derive")] 29 | pub use msgpacker_derive::MsgPacker; 30 | 31 | /// Packs the provided packable value into a vector. 32 | #[cfg(feature = "alloc")] 33 | pub fn pack_to_vec(value: &T) -> Vec 34 | where 35 | T: Packable, 36 | { 37 | value.pack_to_vec() 38 | } 39 | 40 | /// A packable type. 41 | pub trait Packable { 42 | /// Pack a value into the extendable buffer, returning the amount of written bytes. 43 | fn pack(&self, buf: &mut T) -> usize 44 | where 45 | T: Extend; 46 | 47 | /// Packs the value into a vector of bytes. 48 | #[cfg(feature = "alloc")] 49 | fn pack_to_vec(&self) -> Vec { 50 | let mut bytes = Vec::new(); 51 | 52 | self.pack(&mut bytes); 53 | 54 | bytes 55 | } 56 | } 57 | 58 | impl Packable for &X 59 | where 60 | X: Packable, 61 | { 62 | fn pack(&self, buf: &mut T) -> usize 63 | where 64 | T: Extend, 65 | { 66 | X::pack(self, buf) 67 | } 68 | } 69 | 70 | impl Packable for &mut X 71 | where 72 | X: Packable, 73 | { 74 | fn pack(&self, buf: &mut T) -> usize 75 | where 76 | T: Extend, 77 | { 78 | X::pack(self, buf) 79 | } 80 | } 81 | 82 | /// An unpackable type. 83 | /// 84 | /// It provides two methods of deserialization: via slices of bytes and iterators. 85 | /// 86 | /// Slices of bytes are more performant than iterators, but they require the bytes to be eagerly 87 | /// loaded. If a lazy load deserialization is needed, then use `unpack_iter`. 88 | pub trait Unpackable: Sized { 89 | /// Concrete error implementation for the serialization. 90 | /// 91 | /// Must interop with [Error]. 92 | type Error: From; 93 | 94 | /// Unpacks a value from the buffer, returning the deserialized value and the amount of read 95 | /// bytes. 96 | fn unpack(buf: &[u8]) -> Result<(usize, Self), Self::Error>; 97 | 98 | /// Unpacks a value from an iterator of bytes, returning the deserialized value and the amount 99 | /// of read bytes. 100 | /// 101 | /// This should be used only if lazy load is required. [Unpackable::unpack] outperforms 102 | /// iterators with a large margin. 103 | fn unpack_iter(bytes: I) -> Result<(usize, Self), Self::Error> 104 | where 105 | I: IntoIterator; 106 | } 107 | 108 | /// Required types for the library. 109 | pub mod prelude { 110 | pub use super::{Error, Packable, Unpackable}; 111 | 112 | #[cfg(feature = "derive")] 113 | pub use super::MsgPacker; 114 | 115 | #[cfg(feature = "alloc")] 116 | pub use super::Extension; 117 | } 118 | -------------------------------------------------------------------------------- /msgpacker/src/unpack/binary.rs: -------------------------------------------------------------------------------- 1 | use crate::{ 2 | helpers::{take_byte_iter, take_num_iter}, 3 | Unpackable, 4 | }; 5 | 6 | use super::{ 7 | helpers::{take_byte, take_num}, 8 | Error, Format, 9 | }; 10 | use alloc::{string::String, vec::Vec}; 11 | use core::str; 12 | 13 | pub fn unpack_bytes(mut buf: &[u8]) -> Result<(usize, &[u8]), Error> { 14 | let format = take_byte(&mut buf)?; 15 | let (n, len) = match format { 16 | Format::BIN8 => (2, take_byte(&mut buf)? as usize), 17 | Format::BIN16 => (3, take_num(&mut buf, u16::from_be_bytes)? as usize), 18 | Format::BIN32 => (5, take_num(&mut buf, u32::from_be_bytes)? as usize), 19 | _ => return Err(Error::UnexpectedFormatTag), 20 | }; 21 | if buf.len() < len { 22 | return Err(Error::BufferTooShort); 23 | } 24 | Ok((n + len, &buf[..len])) 25 | } 26 | 27 | pub fn unpack_str(mut buf: &[u8]) -> Result<(usize, &str), Error> { 28 | let format = take_byte(&mut buf)?; 29 | let (n, len) = match format { 30 | 0xa0..=0xbf => (1, format as usize & 0x1f), 31 | Format::STR8 => (2, take_byte(&mut buf)? as usize), 32 | Format::STR16 => (3, take_num(&mut buf, u16::from_be_bytes)? as usize), 33 | Format::STR32 => (5, take_num(&mut buf, u32::from_be_bytes)? as usize), 34 | _ => return Err(Error::UnexpectedFormatTag), 35 | }; 36 | if buf.len() < len { 37 | return Err(Error::BufferTooShort); 38 | } 39 | let str = str::from_utf8(&buf[..len]).map_err(|_| Error::InvalidUtf8)?; 40 | Ok((n + len, str)) 41 | } 42 | 43 | impl Unpackable for Vec { 44 | type Error = Error; 45 | 46 | fn unpack(buf: &[u8]) -> Result<(usize, Self), Self::Error> { 47 | unpack_bytes(buf).map(|(n, b)| (n, b.to_vec())) 48 | } 49 | 50 | fn unpack_iter(bytes: I) -> Result<(usize, Self), Self::Error> 51 | where 52 | I: IntoIterator, 53 | { 54 | let mut bytes = bytes.into_iter(); 55 | let format = take_byte_iter(bytes.by_ref())?; 56 | let (n, len) = match format { 57 | Format::BIN8 => (2, take_byte_iter(bytes.by_ref())? as usize), 58 | Format::BIN16 => ( 59 | 3, 60 | take_num_iter(bytes.by_ref(), u16::from_be_bytes)? as usize, 61 | ), 62 | Format::BIN32 => ( 63 | 5, 64 | take_num_iter(bytes.by_ref(), u32::from_be_bytes)? as usize, 65 | ), 66 | _ => return Err(Error::UnexpectedFormatTag), 67 | }; 68 | let v: Vec<_> = bytes.take(len).collect(); 69 | if v.len() < len { 70 | return Err(Error::BufferTooShort); 71 | } 72 | Ok((n + len, v)) 73 | } 74 | } 75 | 76 | impl Unpackable for String { 77 | type Error = Error; 78 | 79 | fn unpack(buf: &[u8]) -> Result<(usize, Self), Self::Error> { 80 | unpack_str(buf).map(|(n, s)| (n, s.into())) 81 | } 82 | 83 | fn unpack_iter(bytes: I) -> Result<(usize, Self), Self::Error> 84 | where 85 | I: IntoIterator, 86 | { 87 | let mut bytes = bytes.into_iter(); 88 | let format = take_byte_iter(bytes.by_ref())?; 89 | let (n, len) = match format { 90 | 0xa0..=0xbf => (1, format as usize & 0x1f), 91 | Format::STR8 => (2, take_byte_iter(bytes.by_ref())? as usize), 92 | Format::STR16 => ( 93 | 3, 94 | take_num_iter(bytes.by_ref(), u16::from_be_bytes)? as usize, 95 | ), 96 | Format::STR32 => ( 97 | 5, 98 | take_num_iter(bytes.by_ref(), u32::from_be_bytes)? as usize, 99 | ), 100 | _ => return Err(Error::UnexpectedFormatTag), 101 | }; 102 | let v: Vec<_> = bytes.take(len).collect(); 103 | if v.len() < len { 104 | return Err(Error::BufferTooShort); 105 | } 106 | let s = String::from_utf8(v).map_err(|_| Error::InvalidUtf8)?; 107 | Ok((n + len, s)) 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /msgpacker/src/pack/collections.rs: -------------------------------------------------------------------------------- 1 | use super::{Format, Packable}; 2 | use core::{borrow::Borrow, iter}; 3 | 4 | /// Packs an array into the extendable buffer, returning the amount of written bytes. 5 | #[allow(unreachable_code)] 6 | pub fn pack_array(buf: &mut T, iter: A) -> usize 7 | where 8 | T: Extend, 9 | A: IntoIterator, 10 | I: Iterator + ExactSizeIterator, 11 | V: Packable, 12 | { 13 | let values = iter.into_iter(); 14 | let len = values.len(); 15 | let n = if len <= 15 { 16 | buf.extend(iter::once(((len & 0x0f) as u8) | 0x90)); 17 | 1 18 | } else if len <= u16::MAX as usize { 19 | buf.extend(iter::once(Format::ARRAY16).chain((len as u16).to_be_bytes())); 20 | 3 21 | } else if len <= u32::MAX as usize { 22 | buf.extend(iter::once(Format::ARRAY32).chain((len as u32).to_be_bytes())); 23 | 5 24 | } else { 25 | #[cfg(feature = "strict")] 26 | panic!("strict serialization enabled; the buffer is too large"); 27 | return 0; 28 | }; 29 | n + values.map(|v| v.pack(buf)).sum::() 30 | } 31 | 32 | /// Packs a map into the extendable buffer, returning the amount of written bytes. 33 | #[allow(unreachable_code)] 34 | pub fn pack_map(buf: &mut T, iter: A) -> usize 35 | where 36 | T: Extend, 37 | A: IntoIterator, 38 | B: Borrow<(K, V)>, 39 | I: Iterator + ExactSizeIterator, 40 | K: Packable, 41 | V: Packable, 42 | { 43 | let map = iter.into_iter(); 44 | let len = map.len(); 45 | let n = if len <= 15 { 46 | buf.extend(iter::once(((len & 0x0f) as u8) | 0x80)); 47 | 1 48 | } else if len <= u16::MAX as usize { 49 | buf.extend(iter::once(Format::MAP16).chain((len as u16).to_be_bytes())); 50 | 3 51 | } else if len <= u32::MAX as usize { 52 | buf.extend(iter::once(Format::MAP32).chain((len as u32).to_be_bytes())); 53 | 5 54 | } else { 55 | #[cfg(feature = "strict")] 56 | panic!("strict serialization enabled; the buffer is too large"); 57 | return 0; 58 | }; 59 | n + map 60 | .map(|b| { 61 | let (k, v) = b.borrow(); 62 | k.pack(buf) + v.pack(buf) 63 | }) 64 | .sum::() 65 | } 66 | 67 | #[cfg(feature = "alloc")] 68 | mod alloc { 69 | use super::*; 70 | use ::alloc::collections::{BTreeMap, BTreeSet, BinaryHeap, LinkedList, VecDeque}; 71 | 72 | impl Packable for BTreeSet 73 | where 74 | X: Packable, 75 | { 76 | fn pack(&self, buf: &mut T) -> usize 77 | where 78 | T: Extend, 79 | { 80 | pack_array(buf, self) 81 | } 82 | } 83 | 84 | impl Packable for BinaryHeap 85 | where 86 | X: Packable, 87 | { 88 | fn pack(&self, buf: &mut T) -> usize 89 | where 90 | T: Extend, 91 | { 92 | pack_array(buf, self) 93 | } 94 | } 95 | 96 | impl Packable for LinkedList 97 | where 98 | X: Packable, 99 | { 100 | fn pack(&self, buf: &mut T) -> usize 101 | where 102 | T: Extend, 103 | { 104 | pack_array(buf, self) 105 | } 106 | } 107 | 108 | impl Packable for VecDeque 109 | where 110 | X: Packable, 111 | { 112 | fn pack(&self, buf: &mut T) -> usize 113 | where 114 | T: Extend, 115 | { 116 | pack_array(buf, self) 117 | } 118 | } 119 | 120 | impl Packable for BTreeMap 121 | where 122 | K: Packable, 123 | V: Packable, 124 | { 125 | fn pack(&self, buf: &mut T) -> usize 126 | where 127 | T: Extend, 128 | { 129 | pack_map(buf, self) 130 | } 131 | } 132 | } 133 | 134 | #[cfg(feature = "std")] 135 | mod std { 136 | use super::*; 137 | use ::std::collections::{HashMap, HashSet}; 138 | 139 | impl Packable for HashSet 140 | where 141 | X: Packable, 142 | { 143 | fn pack(&self, buf: &mut T) -> usize 144 | where 145 | T: Extend, 146 | { 147 | pack_array(buf, self) 148 | } 149 | } 150 | 151 | impl Packable for HashMap 152 | where 153 | K: Packable, 154 | V: Packable, 155 | { 156 | fn pack(&self, buf: &mut T) -> usize 157 | where 158 | T: Extend, 159 | { 160 | pack_map(buf, self) 161 | } 162 | } 163 | } 164 | -------------------------------------------------------------------------------- /msgpacker/src/pack/common.rs: -------------------------------------------------------------------------------- 1 | use super::{Format, Packable}; 2 | use core::{iter, marker::PhantomData}; 3 | 4 | impl Packable for () { 5 | fn pack(&self, _buf: &mut T) -> usize 6 | where 7 | T: Extend, 8 | { 9 | 0 10 | } 11 | } 12 | 13 | impl Packable for PhantomData { 14 | fn pack(&self, _buf: &mut T) -> usize 15 | where 16 | T: Extend, 17 | { 18 | 0 19 | } 20 | } 21 | 22 | impl Packable for bool { 23 | fn pack(&self, buf: &mut T) -> usize 24 | where 25 | T: Extend, 26 | { 27 | if *self { 28 | buf.extend(iter::once(Format::TRUE)); 29 | } else { 30 | buf.extend(iter::once(Format::FALSE)); 31 | } 32 | 1 33 | } 34 | } 35 | 36 | impl Packable for Option 37 | where 38 | X: Packable, 39 | { 40 | fn pack(&self, buf: &mut T) -> usize 41 | where 42 | T: Extend, 43 | { 44 | match self { 45 | Some(t) => t.pack(buf), 46 | None => { 47 | buf.extend(iter::once(Format::NIL)); 48 | 1 49 | } 50 | } 51 | } 52 | } 53 | 54 | macro_rules! array { 55 | ($n:expr) => { 56 | impl Packable for [X; $n] 57 | where 58 | X: Packable, 59 | { 60 | fn pack(&self, buf: &mut T) -> usize 61 | where 62 | T: Extend, 63 | { 64 | self.iter().map(|t| t.pack(buf)).sum() 65 | } 66 | } 67 | }; 68 | } 69 | 70 | array!(0); 71 | array!(1); 72 | array!(2); 73 | array!(3); 74 | array!(4); 75 | array!(5); 76 | array!(6); 77 | array!(7); 78 | array!(8); 79 | array!(9); 80 | array!(10); 81 | array!(11); 82 | array!(12); 83 | array!(13); 84 | array!(14); 85 | array!(15); 86 | array!(16); 87 | array!(17); 88 | array!(18); 89 | array!(19); 90 | array!(20); 91 | array!(21); 92 | array!(22); 93 | array!(23); 94 | array!(24); 95 | array!(25); 96 | array!(26); 97 | array!(27); 98 | array!(28); 99 | array!(29); 100 | array!(30); 101 | array!(31); 102 | array!(32); 103 | array!(33); 104 | array!(34); 105 | array!(35); 106 | array!(36); 107 | array!(37); 108 | array!(38); 109 | array!(39); 110 | array!(40); 111 | array!(41); 112 | array!(42); 113 | array!(43); 114 | array!(44); 115 | array!(45); 116 | array!(46); 117 | array!(47); 118 | array!(48); 119 | array!(49); 120 | array!(50); 121 | array!(51); 122 | array!(52); 123 | array!(53); 124 | array!(54); 125 | array!(55); 126 | array!(56); 127 | array!(57); 128 | array!(58); 129 | array!(59); 130 | array!(60); 131 | array!(61); 132 | array!(62); 133 | array!(63); 134 | array!(64); 135 | 136 | macro_rules! tuple { 137 | ( $($name:ident)+) => ( 138 | impl<$($name,)+> Packable for ($($name,)+) 139 | where $($name: Packable,)+ 140 | { 141 | #[allow(non_snake_case)] 142 | fn pack(&self, buf: &mut TT) -> usize 143 | where 144 | TT: Extend, 145 | { 146 | let ($(ref $name,)+) = *self; 147 | 148 | 0 $( + $name.pack(buf))+ 149 | } 150 | } 151 | ); 152 | } 153 | 154 | tuple! { 155 | A 156 | } 157 | tuple! { 158 | A B 159 | } 160 | tuple! { 161 | A B C 162 | } 163 | tuple! { 164 | A B C D 165 | } 166 | tuple! { 167 | A B C D E 168 | } 169 | tuple! { 170 | A B C D E F 171 | } 172 | tuple! { 173 | A B C D E F G 174 | } 175 | tuple! { 176 | A B C D E F G H 177 | } 178 | tuple! { 179 | A B C D E F G H I 180 | } 181 | tuple! { 182 | A B C D E F G H I J 183 | } 184 | tuple! { 185 | A B C D E F G H I J K 186 | } 187 | tuple! { 188 | A B C D E F G H I J K L 189 | } 190 | tuple! { 191 | A B C D E F G H I J K L M 192 | } 193 | tuple! { 194 | A B C D E F G H I J K L M N 195 | } 196 | tuple! { 197 | A B C D E F G H I J K L M N O 198 | } 199 | tuple! { 200 | A B C D E F G H I J K L M N O P 201 | } 202 | tuple! { 203 | A B C D E F G H I J K L M N O P Q 204 | } 205 | tuple! { 206 | A B C D E F G H I J K L M N O P Q R 207 | } 208 | tuple! { 209 | A B C D E F G H I J K L M N O P Q R S 210 | } 211 | tuple! { 212 | A B C D E F G H I J K L M N O P Q R S T 213 | } 214 | tuple! { 215 | A B C D E F G H I J K L M N O P Q R S T U 216 | } 217 | tuple! { 218 | A B C D E F G H I J K L M N O P Q R S T U V 219 | } 220 | tuple! { 221 | A B C D E F G H I J K L M N O P Q R S T U V W 222 | } 223 | tuple! { 224 | A B C D E F G H I J K L M N O P Q R S T U V W X 225 | } 226 | tuple! { 227 | A B C D E F G H I J K L M N O P Q R S T U V W X Y 228 | } 229 | tuple! { 230 | A B C D E F G H I J K L M N O P Q R S T U V W X Y Z 231 | } 232 | -------------------------------------------------------------------------------- /msgpacker/src/unpack/common.rs: -------------------------------------------------------------------------------- 1 | use super::{ 2 | helpers::{take_byte, take_byte_iter}, 3 | Error, Format, Unpackable, 4 | }; 5 | use core::{marker::PhantomData, mem::MaybeUninit}; 6 | 7 | impl Unpackable for () { 8 | type Error = Error; 9 | 10 | fn unpack(_buf: &[u8]) -> Result<(usize, Self), Self::Error> { 11 | Ok((0, ())) 12 | } 13 | 14 | fn unpack_iter(_buf: I) -> Result<(usize, Self), Self::Error> 15 | where 16 | I: IntoIterator, 17 | { 18 | Ok((0, ())) 19 | } 20 | } 21 | 22 | impl Unpackable for PhantomData { 23 | type Error = Error; 24 | 25 | fn unpack(_buf: &[u8]) -> Result<(usize, Self), Self::Error> { 26 | Ok((0, PhantomData)) 27 | } 28 | 29 | fn unpack_iter(_buf: I) -> Result<(usize, Self), Self::Error> 30 | where 31 | I: IntoIterator, 32 | { 33 | Ok((0, PhantomData)) 34 | } 35 | } 36 | 37 | impl Unpackable for bool { 38 | type Error = Error; 39 | 40 | fn unpack(mut buf: &[u8]) -> Result<(usize, Self), Self::Error> { 41 | let format = take_byte(&mut buf)?; 42 | if format != Format::TRUE && format != Format::FALSE { 43 | return Err(Error::UnexpectedFormatTag); 44 | } 45 | Ok((1, format != Format::FALSE)) 46 | } 47 | 48 | fn unpack_iter(bytes: I) -> Result<(usize, Self), Self::Error> 49 | where 50 | I: IntoIterator, 51 | { 52 | let mut bytes = bytes.into_iter(); 53 | let format = take_byte_iter(bytes.by_ref())?; 54 | if format != Format::TRUE && format != Format::FALSE { 55 | return Err(Error::UnexpectedFormatTag); 56 | } 57 | Ok((1, format != Format::FALSE)) 58 | } 59 | } 60 | 61 | impl Unpackable for Option 62 | where 63 | X: Unpackable, 64 | { 65 | type Error = ::Error; 66 | 67 | fn unpack(buf: &[u8]) -> Result<(usize, Self), Self::Error> { 68 | if buf.is_empty() { 69 | return Err(Error::BufferTooShort.into()); 70 | } 71 | if buf[0] == Format::NIL { 72 | return Ok((1, None)); 73 | } 74 | X::unpack(buf).map(|(n, x)| (n, Some(x))) 75 | } 76 | 77 | fn unpack_iter(bytes: I) -> Result<(usize, Self), Self::Error> 78 | where 79 | I: IntoIterator, 80 | { 81 | let mut bytes = bytes.into_iter().peekable(); 82 | let format = *bytes.peek().ok_or(Error::BufferTooShort)?; 83 | if format == Format::NIL { 84 | bytes.next(); 85 | return Ok((1, None)); 86 | } 87 | X::unpack_iter(bytes).map(|(n, x)| (n, Some(x))) 88 | } 89 | } 90 | 91 | macro_rules! array { 92 | ($n:expr) => { 93 | impl Unpackable for [X; $n] 94 | where 95 | X: Unpackable, 96 | { 97 | type Error = ::Error; 98 | 99 | fn unpack(mut buf: &[u8]) -> Result<(usize, Self), Self::Error> { 100 | let mut array = [const { MaybeUninit::uninit() }; $n]; 101 | let n = 102 | array 103 | .iter_mut() 104 | .try_fold::<_, _, Result<_, Self::Error>>(0, |count, a| { 105 | let (n, x) = X::unpack(buf)?; 106 | buf = &buf[n..]; 107 | a.write(x); 108 | Ok(count + n) 109 | })?; 110 | // Safety: array is initialized 111 | let array = ::core::array::from_fn(|i| { 112 | let mut x = MaybeUninit::zeroed(); 113 | ::core::mem::swap(&mut array[i], &mut x); 114 | unsafe { MaybeUninit::assume_init(x) } 115 | }); 116 | Ok((n, array)) 117 | } 118 | 119 | fn unpack_iter(bytes: I) -> Result<(usize, Self), Self::Error> 120 | where 121 | I: IntoIterator, 122 | { 123 | let mut bytes = bytes.into_iter(); 124 | let mut array = [const { MaybeUninit::uninit() }; $n]; 125 | let n = 126 | array 127 | .iter_mut() 128 | .try_fold::<_, _, Result<_, Self::Error>>(0, |count, a| { 129 | let (n, x) = X::unpack_iter(bytes.by_ref())?; 130 | a.write(x); 131 | Ok(count + n) 132 | })?; 133 | // Safety: array is initialized 134 | let array = ::core::array::from_fn(|i| { 135 | let mut x = MaybeUninit::zeroed(); 136 | ::core::mem::swap(&mut array[i], &mut x); 137 | unsafe { MaybeUninit::assume_init(x) } 138 | }); 139 | Ok((n, array)) 140 | } 141 | } 142 | }; 143 | } 144 | 145 | array!(0); 146 | array!(1); 147 | array!(2); 148 | array!(3); 149 | array!(4); 150 | array!(5); 151 | array!(6); 152 | array!(7); 153 | array!(8); 154 | array!(9); 155 | array!(10); 156 | array!(11); 157 | array!(12); 158 | array!(13); 159 | array!(14); 160 | array!(15); 161 | array!(16); 162 | array!(17); 163 | array!(18); 164 | array!(19); 165 | array!(20); 166 | array!(21); 167 | array!(22); 168 | array!(23); 169 | array!(24); 170 | array!(25); 171 | array!(26); 172 | array!(27); 173 | array!(28); 174 | array!(29); 175 | array!(30); 176 | array!(31); 177 | array!(32); 178 | array!(33); 179 | array!(34); 180 | array!(35); 181 | array!(36); 182 | array!(37); 183 | array!(38); 184 | array!(39); 185 | array!(40); 186 | array!(41); 187 | array!(42); 188 | array!(43); 189 | array!(44); 190 | array!(45); 191 | array!(46); 192 | array!(47); 193 | array!(48); 194 | array!(49); 195 | array!(50); 196 | array!(51); 197 | array!(52); 198 | array!(53); 199 | array!(54); 200 | array!(55); 201 | array!(56); 202 | array!(57); 203 | array!(58); 204 | array!(59); 205 | array!(60); 206 | array!(61); 207 | array!(62); 208 | array!(63); 209 | array!(64); 210 | 211 | macro_rules! tuple { 212 | ($err:ident, $($name:ident)+) => ( 213 | impl<$($name,)+> Unpackable for ($($name,)+) 214 | where 215 | $($name: Unpackable,)+ 216 | $($err::Error: From<<$name as Unpackable>::Error>,)+ 217 | { 218 | type Error = <$err as Unpackable>::Error; 219 | 220 | #[allow(non_snake_case)] 221 | fn unpack(mut buf: &[u8]) -> Result<(usize, Self), Self::Error> { 222 | let mut n = 0; 223 | 224 | $(let (c, $name) = $name::unpack(buf)?; n += c; buf = &buf[c..];)+ 225 | let _ = buf; 226 | 227 | Ok((n, ($($name, )+))) 228 | } 229 | 230 | #[allow(non_snake_case)] 231 | fn unpack_iter(bytes: II) -> Result<(usize, Self), Self::Error> 232 | where 233 | II: IntoIterator, 234 | { 235 | let mut n = 0; 236 | let mut bytes = bytes.into_iter(); 237 | 238 | $(let (c, $name) = $name::unpack_iter(bytes.by_ref())?; n += c;)+ 239 | 240 | Ok((n, ($($name, )+))) 241 | } 242 | } 243 | ); 244 | } 245 | 246 | tuple! { 247 | A, A 248 | } 249 | tuple! { 250 | A, A B 251 | } 252 | tuple! { 253 | A, A B C 254 | } 255 | tuple! { 256 | A, A B C D 257 | } 258 | tuple! { 259 | A, A B C D E 260 | } 261 | tuple! { 262 | A, A B C D E F 263 | } 264 | tuple! { 265 | A, A B C D E F G 266 | } 267 | tuple! { 268 | A, A B C D E F G H 269 | } 270 | tuple! { 271 | A, A B C D E F G H I 272 | } 273 | tuple! { 274 | A, A B C D E F G H I J 275 | } 276 | tuple! { 277 | A, A B C D E F G H I J K 278 | } 279 | tuple! { 280 | A, A B C D E F G H I J K L 281 | } 282 | tuple! { 283 | A, A B C D E F G H I J K L M 284 | } 285 | tuple! { 286 | A, A B C D E F G H I J K L M N 287 | } 288 | tuple! { 289 | A, A B C D E F G H I J K L M N O 290 | } 291 | tuple! { 292 | A, A B C D E F G H I J K L M N O P 293 | } 294 | tuple! { 295 | A, A B C D E F G H I J K L M N O P Q 296 | } 297 | tuple! { 298 | A, A B C D E F G H I J K L M N O P Q R 299 | } 300 | tuple! { 301 | A, A B C D E F G H I J K L M N O P Q R S 302 | } 303 | tuple! { 304 | A, A B C D E F G H I J K L M N O P Q R S T 305 | } 306 | tuple! { 307 | A, A B C D E F G H I J K L M N O P Q R S T U 308 | } 309 | tuple! { 310 | A, A B C D E F G H I J K L M N O P Q R S T U V 311 | } 312 | tuple! { 313 | A, A B C D E F G H I J K L M N O P Q R S T U V W 314 | } 315 | tuple! { 316 | A, A B C D E F G H I J K L M N O P Q R S T U V W X 317 | } 318 | tuple! { 319 | A, A B C D E F G H I J K L M N O P Q R S T U V W X Y 320 | } 321 | tuple! { 322 | A, A B C D E F G H I J K L M N O P Q R S T U V W X Y Z 323 | } 324 | -------------------------------------------------------------------------------- /msgpacker/src/unpack/collections.rs: -------------------------------------------------------------------------------- 1 | use super::{ 2 | helpers::{take_byte, take_byte_iter, take_num, take_num_iter}, 3 | Error, Format, Unpackable, 4 | }; 5 | 6 | /// Unpacks an array from the buffer, returning a collectable type and the amount of read bytes. 7 | pub fn unpack_array(mut buf: &[u8]) -> Result<(usize, C), ::Error> 8 | where 9 | V: Unpackable, 10 | C: FromIterator, 11 | { 12 | let format = take_byte(&mut buf)?; 13 | let (mut n, len) = match format { 14 | 0x90..=0x9f => (1, (format & 0x0f) as usize), 15 | Format::ARRAY16 => ( 16 | 3, 17 | take_num(&mut buf, u16::from_be_bytes).map(|v| v as usize)?, 18 | ), 19 | Format::ARRAY32 => ( 20 | 5, 21 | take_num(&mut buf, u32::from_be_bytes).map(|v| v as usize)?, 22 | ), 23 | _ => return Err(Error::UnexpectedFormatTag.into()), 24 | }; 25 | let array: C = (0..len) 26 | .map(|_| { 27 | let (count, v) = V::unpack(buf)?; 28 | buf = &buf[count..]; 29 | n += count; 30 | Ok(v) 31 | }) 32 | .collect::::Error>>()?; 33 | Ok((n, array)) 34 | } 35 | 36 | /// Unpacks an array from the iterator, returning a collectable type and the amount of read bytes. 37 | pub fn unpack_array_iter(iter: I) -> Result<(usize, C), ::Error> 38 | where 39 | I: IntoIterator, 40 | V: Unpackable, 41 | C: FromIterator, 42 | { 43 | let mut bytes = iter.into_iter(); 44 | let format = take_byte_iter(bytes.by_ref())?; 45 | let (mut n, len) = match format { 46 | 0x90..=0x9f => (1, (format & 0x0f) as usize), 47 | Format::ARRAY16 => ( 48 | 3, 49 | take_num_iter(bytes.by_ref(), u16::from_be_bytes).map(|v| v as usize)?, 50 | ), 51 | Format::ARRAY32 => ( 52 | 5, 53 | take_num_iter(bytes.by_ref(), u32::from_be_bytes).map(|v| v as usize)?, 54 | ), 55 | _ => return Err(Error::UnexpectedFormatTag.into()), 56 | }; 57 | let array: C = (0..len) 58 | .map(|_| { 59 | let (count, v) = V::unpack_iter(bytes.by_ref())?; 60 | n += count; 61 | Ok(v) 62 | }) 63 | .collect::::Error>>()?; 64 | Ok((n, array)) 65 | } 66 | 67 | /// Unpacks a map from the buffer, returning a collectable type and the amount of read bytes. 68 | pub fn unpack_map(mut buf: &[u8]) -> Result<(usize, C), ::Error> 69 | where 70 | K: Unpackable, 71 | V: Unpackable, 72 | ::Error: From<::Error>, 73 | C: FromIterator<(K, V)>, 74 | { 75 | let format = take_byte(&mut buf)?; 76 | let (mut n, len) = match format { 77 | 0x80..=0x8f => (1, (format & 0x0f) as usize), 78 | Format::MAP16 => ( 79 | 3, 80 | take_num(&mut buf, u16::from_be_bytes).map(|v| v as usize)?, 81 | ), 82 | Format::MAP32 => ( 83 | 5, 84 | take_num(&mut buf, u32::from_be_bytes).map(|v| v as usize)?, 85 | ), 86 | _ => return Err(Error::UnexpectedFormatTag.into()), 87 | }; 88 | let map: C = (0..len) 89 | .map(|_| { 90 | let (count, k) = K::unpack(buf)?; 91 | buf = &buf[count..]; 92 | n += count; 93 | let (count, v) = V::unpack(buf)?; 94 | buf = &buf[count..]; 95 | n += count; 96 | Ok((k, v)) 97 | }) 98 | .collect::::Error>>()?; 99 | Ok((n, map)) 100 | } 101 | 102 | /// Unpacks a map from the iterator, returning a collectable type and the amount of read bytes. 103 | pub fn unpack_map_iter(iter: I) -> Result<(usize, C), ::Error> 104 | where 105 | I: IntoIterator, 106 | K: Unpackable, 107 | V: Unpackable, 108 | ::Error: From<::Error>, 109 | C: FromIterator<(K, V)>, 110 | { 111 | let mut bytes = iter.into_iter(); 112 | let format = take_byte_iter(bytes.by_ref())?; 113 | let (mut n, len) = match format { 114 | 0x80..=0x8f => (1, (format & 0x0f) as usize), 115 | Format::MAP16 => ( 116 | 3, 117 | take_num_iter(bytes.by_ref(), u16::from_be_bytes).map(|v| v as usize)?, 118 | ), 119 | Format::MAP32 => ( 120 | 5, 121 | take_num_iter(bytes.by_ref(), u32::from_be_bytes).map(|v| v as usize)?, 122 | ), 123 | _ => return Err(Error::UnexpectedFormatTag.into()), 124 | }; 125 | let map: C = (0..len) 126 | .map(|_| { 127 | let (count, k) = K::unpack_iter(bytes.by_ref())?; 128 | n += count; 129 | let (count, v) = V::unpack_iter(bytes.by_ref())?; 130 | n += count; 131 | Ok((k, v)) 132 | }) 133 | .collect::::Error>>()?; 134 | Ok((n, map)) 135 | } 136 | 137 | #[cfg(feature = "alloc")] 138 | mod alloc { 139 | use super::*; 140 | use ::alloc::collections::{BTreeMap, BTreeSet, BinaryHeap, LinkedList, VecDeque}; 141 | 142 | impl Unpackable for BTreeSet 143 | where 144 | X: Unpackable + Ord, 145 | { 146 | type Error = ::Error; 147 | 148 | fn unpack(buf: &[u8]) -> Result<(usize, Self), Self::Error> { 149 | unpack_array(buf) 150 | } 151 | 152 | fn unpack_iter(bytes: I) -> Result<(usize, Self), Self::Error> 153 | where 154 | I: IntoIterator, 155 | { 156 | unpack_array_iter(bytes) 157 | } 158 | } 159 | 160 | impl Unpackable for BinaryHeap 161 | where 162 | X: Unpackable + Ord, 163 | { 164 | type Error = ::Error; 165 | 166 | fn unpack(buf: &[u8]) -> Result<(usize, Self), Self::Error> { 167 | unpack_array(buf) 168 | } 169 | 170 | fn unpack_iter(bytes: I) -> Result<(usize, Self), Self::Error> 171 | where 172 | I: IntoIterator, 173 | { 174 | unpack_array_iter(bytes) 175 | } 176 | } 177 | 178 | impl Unpackable for LinkedList 179 | where 180 | X: Unpackable, 181 | { 182 | type Error = ::Error; 183 | 184 | fn unpack(buf: &[u8]) -> Result<(usize, Self), Self::Error> { 185 | unpack_array(buf) 186 | } 187 | 188 | fn unpack_iter(bytes: I) -> Result<(usize, Self), Self::Error> 189 | where 190 | I: IntoIterator, 191 | { 192 | unpack_array_iter(bytes) 193 | } 194 | } 195 | 196 | impl Unpackable for VecDeque 197 | where 198 | X: Unpackable, 199 | { 200 | type Error = ::Error; 201 | 202 | fn unpack(buf: &[u8]) -> Result<(usize, Self), Self::Error> { 203 | unpack_array(buf) 204 | } 205 | 206 | fn unpack_iter(bytes: I) -> Result<(usize, Self), Self::Error> 207 | where 208 | I: IntoIterator, 209 | { 210 | unpack_array_iter(bytes) 211 | } 212 | } 213 | 214 | impl Unpackable for BTreeMap 215 | where 216 | K: Unpackable + Ord, 217 | V: Unpackable, 218 | ::Error: From<::Error>, 219 | { 220 | type Error = ::Error; 221 | 222 | fn unpack(buf: &[u8]) -> Result<(usize, Self), Self::Error> { 223 | unpack_map(buf) 224 | } 225 | 226 | fn unpack_iter(bytes: I) -> Result<(usize, Self), Self::Error> 227 | where 228 | I: IntoIterator, 229 | { 230 | unpack_map_iter(bytes) 231 | } 232 | } 233 | } 234 | 235 | #[cfg(feature = "std")] 236 | mod std { 237 | use super::*; 238 | use ::std::{ 239 | collections::{HashMap, HashSet}, 240 | hash::Hash, 241 | }; 242 | 243 | impl Unpackable for HashSet 244 | where 245 | X: Unpackable + Hash + Eq, 246 | { 247 | type Error = ::Error; 248 | 249 | fn unpack(buf: &[u8]) -> Result<(usize, Self), Self::Error> { 250 | unpack_array(buf) 251 | } 252 | 253 | fn unpack_iter(bytes: I) -> Result<(usize, Self), Self::Error> 254 | where 255 | I: IntoIterator, 256 | { 257 | unpack_array_iter(bytes) 258 | } 259 | } 260 | 261 | impl Unpackable for HashMap 262 | where 263 | K: Unpackable + Hash + Eq, 264 | V: Unpackable, 265 | ::Error: From<::Error>, 266 | { 267 | type Error = ::Error; 268 | 269 | fn unpack(buf: &[u8]) -> Result<(usize, Self), Self::Error> { 270 | unpack_map(buf) 271 | } 272 | 273 | fn unpack_iter(bytes: I) -> Result<(usize, Self), Self::Error> 274 | where 275 | I: IntoIterator, 276 | { 277 | unpack_map_iter(bytes) 278 | } 279 | } 280 | } 281 | -------------------------------------------------------------------------------- /LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright 2016 Maciej Hirsz 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /msgpacker/src/pack/int.rs: -------------------------------------------------------------------------------- 1 | use super::{Format, Packable}; 2 | use core::iter; 3 | 4 | impl Packable for u8 { 5 | fn pack(&self, buf: &mut T) -> usize 6 | where 7 | T: Extend, 8 | { 9 | if *self <= 127 { 10 | buf.extend(iter::once(self & Format::POSITIVE_FIXINT)); 11 | 1 12 | } else { 13 | buf.extend(iter::once(Format::UINT8).chain(iter::once(*self))); 14 | 2 15 | } 16 | } 17 | } 18 | 19 | impl Packable for u16 { 20 | fn pack(&self, buf: &mut T) -> usize 21 | where 22 | T: Extend, 23 | { 24 | if *self <= 127 { 25 | buf.extend(iter::once(*self as u8 & Format::POSITIVE_FIXINT)); 26 | 1 27 | } else if *self <= u8::MAX as u16 { 28 | buf.extend(iter::once(Format::UINT8).chain(iter::once(*self as u8))); 29 | 2 30 | } else { 31 | buf.extend(iter::once(Format::UINT16).chain(self.to_be_bytes())); 32 | 3 33 | } 34 | } 35 | } 36 | 37 | impl Packable for u32 { 38 | fn pack(&self, buf: &mut T) -> usize 39 | where 40 | T: Extend, 41 | { 42 | if *self <= 127 { 43 | buf.extend(iter::once(*self as u8 & Format::POSITIVE_FIXINT)); 44 | 1 45 | } else if *self <= u8::MAX as u32 { 46 | buf.extend(iter::once(Format::UINT8).chain(iter::once(*self as u8))); 47 | 2 48 | } else if *self <= u16::MAX as u32 { 49 | buf.extend(iter::once(Format::UINT16).chain((*self as u16).to_be_bytes())); 50 | 3 51 | } else { 52 | buf.extend(iter::once(Format::UINT32).chain(self.to_be_bytes())); 53 | 5 54 | } 55 | } 56 | } 57 | 58 | impl Packable for u64 { 59 | fn pack(&self, buf: &mut T) -> usize 60 | where 61 | T: Extend, 62 | { 63 | if *self <= 127 { 64 | buf.extend(iter::once(*self as u8 & Format::POSITIVE_FIXINT)); 65 | 1 66 | } else if *self <= u8::MAX as u64 { 67 | buf.extend(iter::once(Format::UINT8).chain(iter::once(*self as u8))); 68 | 2 69 | } else if *self <= u16::MAX as u64 { 70 | buf.extend(iter::once(Format::UINT16).chain((*self as u16).to_be_bytes())); 71 | 3 72 | } else if *self <= u32::MAX as u64 { 73 | buf.extend(iter::once(Format::UINT32).chain((*self as u32).to_be_bytes())); 74 | 5 75 | } else { 76 | buf.extend(iter::once(Format::UINT64).chain(self.to_be_bytes())); 77 | 9 78 | } 79 | } 80 | } 81 | 82 | impl Packable for u128 { 83 | fn pack(&self, buf: &mut T) -> usize 84 | where 85 | T: Extend, 86 | { 87 | if *self <= 127 { 88 | buf.extend(iter::once(*self as u8 & Format::POSITIVE_FIXINT)); 89 | 1 90 | } else if *self <= u8::MAX as u128 { 91 | buf.extend(iter::once(Format::UINT8).chain(iter::once(*self as u8))); 92 | 2 93 | } else if *self <= u16::MAX as u128 { 94 | buf.extend(iter::once(Format::UINT16).chain((*self as u16).to_be_bytes())); 95 | 3 96 | } else if *self <= u32::MAX as u128 { 97 | buf.extend(iter::once(Format::UINT32).chain((*self as u32).to_be_bytes())); 98 | 5 99 | } else if *self <= u64::MAX as u128 { 100 | buf.extend(iter::once(Format::UINT64).chain((*self as u64).to_be_bytes())); 101 | 9 102 | } else { 103 | buf.extend( 104 | iter::once(Format::BIN8) 105 | .chain(iter::once(16)) 106 | .chain(self.to_be_bytes()), 107 | ); 108 | 18 109 | } 110 | } 111 | } 112 | 113 | impl Packable for usize { 114 | fn pack(&self, buf: &mut T) -> usize 115 | where 116 | T: Extend, 117 | { 118 | if *self <= 127 { 119 | buf.extend(iter::once(*self as u8 & Format::POSITIVE_FIXINT)); 120 | 1 121 | } else if *self <= u8::MAX as usize { 122 | buf.extend(iter::once(Format::UINT8).chain(iter::once(*self as u8))); 123 | 2 124 | } else if *self <= u16::MAX as usize { 125 | buf.extend(iter::once(Format::UINT16).chain((*self as u16).to_be_bytes())); 126 | 3 127 | } else if *self <= u32::MAX as usize { 128 | buf.extend(iter::once(Format::UINT32).chain((*self as u32).to_be_bytes())); 129 | 5 130 | } else { 131 | buf.extend(iter::once(Format::UINT64).chain(self.to_be_bytes())); 132 | 9 133 | } 134 | } 135 | } 136 | 137 | impl Packable for i8 { 138 | fn pack(&self, buf: &mut T) -> usize 139 | where 140 | T: Extend, 141 | { 142 | if *self <= -33 { 143 | buf.extend(iter::once(Format::INT8).chain(iter::once(*self as u8))); 144 | 2 145 | } else if *self <= -1 { 146 | buf.extend(iter::once((*self | -32i8) as u8)); 147 | 1 148 | } else { 149 | buf.extend(iter::once(*self as u8 & Format::POSITIVE_FIXINT)); 150 | 1 151 | } 152 | } 153 | } 154 | 155 | impl Packable for i16 { 156 | fn pack(&self, buf: &mut T) -> usize 157 | where 158 | T: Extend, 159 | { 160 | if *self < i8::MIN as i16 { 161 | buf.extend(iter::once(Format::INT16).chain(self.to_be_bytes())); 162 | 3 163 | } else if *self <= -33 { 164 | buf.extend(iter::once(Format::INT8).chain(iter::once((*self as i8) as u8))); 165 | 2 166 | } else if *self <= -1 { 167 | buf.extend(iter::once((*self as i8 | -32i8) as u8)); 168 | 1 169 | } else if *self <= i8::MAX as i16 { 170 | buf.extend(iter::once(*self as u8 & Format::POSITIVE_FIXINT)); 171 | 1 172 | } else { 173 | buf.extend(iter::once(Format::INT16).chain(self.to_be_bytes())); 174 | 3 175 | } 176 | } 177 | } 178 | 179 | impl Packable for i32 { 180 | fn pack(&self, buf: &mut T) -> usize 181 | where 182 | T: Extend, 183 | { 184 | if *self < i16::MIN as i32 { 185 | buf.extend(iter::once(Format::INT32).chain(self.to_be_bytes())); 186 | 5 187 | } else if *self < i8::MIN as i32 { 188 | buf.extend(iter::once(Format::INT16).chain((*self as i16).to_be_bytes())); 189 | 3 190 | } else if *self <= -33 { 191 | buf.extend(iter::once(Format::INT8).chain(iter::once((*self as i8) as u8))); 192 | 2 193 | } else if *self <= -1 { 194 | buf.extend(iter::once((*self | -32i32) as u8)); 195 | 1 196 | } else if *self <= i8::MAX as i32 { 197 | buf.extend(iter::once(*self as u8 & Format::POSITIVE_FIXINT)); 198 | 1 199 | } else if *self <= i16::MAX as i32 { 200 | buf.extend(iter::once(Format::INT16).chain((*self as i16).to_be_bytes())); 201 | 3 202 | } else { 203 | buf.extend(iter::once(Format::INT32).chain(self.to_be_bytes())); 204 | 5 205 | } 206 | } 207 | } 208 | 209 | impl Packable for i64 { 210 | fn pack(&self, buf: &mut T) -> usize 211 | where 212 | T: Extend, 213 | { 214 | if *self < i32::MIN as i64 { 215 | buf.extend(iter::once(Format::INT64).chain(self.to_be_bytes())); 216 | 9 217 | } else if *self < i16::MIN as i64 { 218 | buf.extend(iter::once(Format::INT32).chain((*self as i32).to_be_bytes())); 219 | 5 220 | } else if *self < i8::MIN as i64 { 221 | buf.extend(iter::once(Format::INT16).chain((*self as i16).to_be_bytes())); 222 | 3 223 | } else if *self <= -33 { 224 | buf.extend(iter::once(Format::INT8).chain(iter::once((*self as i8) as u8))); 225 | 2 226 | } else if *self <= -1 { 227 | buf.extend(iter::once((*self | -32i64) as u8)); 228 | 1 229 | } else if *self <= i8::MAX as i64 { 230 | buf.extend(iter::once(*self as u8 & Format::POSITIVE_FIXINT)); 231 | 1 232 | } else if *self <= i16::MAX as i64 { 233 | buf.extend(iter::once(Format::INT16).chain((*self as i16).to_be_bytes())); 234 | 3 235 | } else if *self <= i32::MAX as i64 { 236 | buf.extend(iter::once(Format::INT32).chain((*self as i32).to_be_bytes())); 237 | 5 238 | } else { 239 | buf.extend(iter::once(Format::INT64).chain(self.to_be_bytes())); 240 | 9 241 | } 242 | } 243 | } 244 | 245 | impl Packable for i128 { 246 | fn pack(&self, buf: &mut T) -> usize 247 | where 248 | T: Extend, 249 | { 250 | if *self < i64::MIN as i128 { 251 | buf.extend( 252 | iter::once(Format::BIN8) 253 | .chain(iter::once(16)) 254 | .chain(self.to_be_bytes()), 255 | ); 256 | 18 257 | } else if *self < i32::MIN as i128 { 258 | buf.extend(iter::once(Format::INT64).chain((*self as i64).to_be_bytes())); 259 | 9 260 | } else if *self < i16::MIN as i128 { 261 | buf.extend(iter::once(Format::INT32).chain((*self as i32).to_be_bytes())); 262 | 5 263 | } else if *self < i8::MIN as i128 { 264 | buf.extend(iter::once(Format::INT16).chain((*self as i16).to_be_bytes())); 265 | 3 266 | } else if *self <= -33 { 267 | buf.extend(iter::once(Format::INT8).chain(iter::once((*self as i8) as u8))); 268 | 2 269 | } else if *self <= -1 { 270 | buf.extend(iter::once((*self | -32i128) as u8)); 271 | 1 272 | } else if *self <= i8::MAX as i128 { 273 | buf.extend(iter::once(*self as u8 & Format::POSITIVE_FIXINT)); 274 | 1 275 | } else if *self <= i16::MAX as i128 { 276 | buf.extend(iter::once(Format::INT16).chain((*self as i16).to_be_bytes())); 277 | 3 278 | } else if *self <= i32::MAX as i128 { 279 | buf.extend(iter::once(Format::INT32).chain((*self as i32).to_be_bytes())); 280 | 5 281 | } else if *self <= i64::MAX as i128 { 282 | buf.extend(iter::once(Format::INT64).chain((*self as i64).to_be_bytes())); 283 | 9 284 | } else { 285 | buf.extend( 286 | iter::once(Format::BIN8) 287 | .chain(iter::once(16)) 288 | .chain(self.to_be_bytes()), 289 | ); 290 | 18 291 | } 292 | } 293 | } 294 | 295 | impl Packable for isize { 296 | fn pack(&self, buf: &mut T) -> usize 297 | where 298 | T: Extend, 299 | { 300 | if *self < i32::MIN as isize { 301 | buf.extend(iter::once(Format::INT64).chain(self.to_be_bytes())); 302 | 9 303 | } else if *self < i16::MIN as isize { 304 | buf.extend(iter::once(Format::INT32).chain((*self as i32).to_be_bytes())); 305 | 5 306 | } else if *self < i8::MIN as isize { 307 | buf.extend(iter::once(Format::INT16).chain((*self as i16).to_be_bytes())); 308 | 3 309 | } else if *self <= -33 { 310 | buf.extend(iter::once(Format::INT8).chain(iter::once((*self as i8) as u8))); 311 | 2 312 | } else if *self <= -1 { 313 | buf.extend(iter::once((*self | -32isize) as u8)); 314 | 1 315 | } else if *self <= i8::MAX as isize { 316 | buf.extend(iter::once(*self as u8 & Format::POSITIVE_FIXINT)); 317 | 1 318 | } else if *self <= i16::MAX as isize { 319 | buf.extend(iter::once(Format::INT16).chain((*self as i16).to_be_bytes())); 320 | 3 321 | } else if *self <= i32::MAX as isize { 322 | buf.extend(iter::once(Format::INT32).chain((*self as i32).to_be_bytes())); 323 | 5 324 | } else { 325 | buf.extend(iter::once(Format::INT64).chain(self.to_be_bytes())); 326 | 9 327 | } 328 | } 329 | } 330 | -------------------------------------------------------------------------------- /msgpacker/src/extension.rs: -------------------------------------------------------------------------------- 1 | use super::{ 2 | error::Error, 3 | helpers::{take_buffer, take_buffer_iter, take_byte, take_byte_iter, take_num, take_num_iter}, 4 | Format, Packable, Unpackable, 5 | }; 6 | use alloc::{vec, vec::Vec}; 7 | use core::{iter, time::Duration}; 8 | 9 | /// Custom extension definition as reference to a bytes source. 10 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] 11 | pub enum Extension { 12 | /// n-bytes custom extension 13 | Ext(i8, Vec), 14 | /// Protocol reserved extension to represent timestamps 15 | Timestamp(Duration), 16 | } 17 | 18 | impl Extension { 19 | /// Protocol constant for a timestamp extension 20 | pub const TIMESTAMP: i8 = -1; 21 | } 22 | 23 | impl Packable for Extension { 24 | #[allow(unreachable_code)] 25 | fn pack(&self, buf: &mut T) -> usize 26 | where 27 | T: Extend, 28 | { 29 | match self { 30 | Extension::Ext(t, b) if b.len() == 1 => { 31 | buf.extend( 32 | iter::once(Format::FIXEXT1) 33 | .chain(iter::once(*t as u8)) 34 | .chain(iter::once(b[0])), 35 | ); 36 | 3 37 | } 38 | 39 | Extension::Ext(t, b) if b.len() == 2 => { 40 | buf.extend( 41 | iter::once(Format::FIXEXT2) 42 | .chain(iter::once(*t as u8)) 43 | .chain(b.iter().copied()), 44 | ); 45 | 4 46 | } 47 | 48 | Extension::Ext(t, b) if b.len() == 4 => { 49 | buf.extend( 50 | iter::once(Format::FIXEXT4) 51 | .chain(iter::once(*t as u8)) 52 | .chain(b.iter().copied()), 53 | ); 54 | 6 55 | } 56 | 57 | Extension::Ext(t, b) if b.len() == 8 => { 58 | buf.extend( 59 | iter::once(Format::FIXEXT8) 60 | .chain(iter::once(*t as u8)) 61 | .chain(b.iter().copied()), 62 | ); 63 | 10 64 | } 65 | 66 | Extension::Ext(t, b) if b.len() == 16 => { 67 | buf.extend( 68 | iter::once(Format::FIXEXT16) 69 | .chain(iter::once(*t as u8)) 70 | .chain(b.iter().copied()), 71 | ); 72 | 18 73 | } 74 | 75 | Extension::Ext(t, b) if b.len() <= u8::MAX as usize => { 76 | buf.extend( 77 | iter::once(Format::EXT8) 78 | .chain(iter::once(b.len() as u8)) 79 | .chain(iter::once(*t as u8)) 80 | .chain(b.iter().copied()), 81 | ); 82 | 3 + b.len() 83 | } 84 | 85 | Extension::Ext(t, b) if b.len() <= u16::MAX as usize => { 86 | buf.extend( 87 | iter::once(Format::EXT16) 88 | .chain((b.len() as u16).to_be_bytes().iter().copied()) 89 | .chain(iter::once(*t as u8)) 90 | .chain(b.iter().copied()), 91 | ); 92 | 4 + b.len() 93 | } 94 | 95 | Extension::Ext(t, b) if b.len() <= u32::MAX as usize => { 96 | buf.extend( 97 | iter::once(Format::EXT32) 98 | .chain((b.len() as u32).to_be_bytes().iter().copied()) 99 | .chain(iter::once(*t as u8)) 100 | .chain(b.iter().copied()), 101 | ); 102 | 6 + b.len() 103 | } 104 | 105 | Extension::Ext(_, _) => { 106 | #[cfg(feature = "strict")] 107 | panic!("strict serialization enabled; the buffer is too large"); 108 | 0 109 | } 110 | 111 | Extension::Timestamp(d) if d.as_secs() <= u32::MAX as u64 && d.subsec_nanos() == 0 => { 112 | buf.extend( 113 | iter::once(Format::FIXEXT4) 114 | .chain(iter::once(Self::TIMESTAMP as u8)) 115 | .chain((d.as_secs() as u32).to_be_bytes().iter().copied()), 116 | ); 117 | 6 118 | } 119 | 120 | Extension::Timestamp(d) 121 | if d.as_secs() < 1u64 << 34 && d.subsec_nanos() < 1u32 << 30 => 122 | { 123 | let secs = d.as_secs(); 124 | let secs_nanos = ((secs >> 32) & 0b11) as u32; 125 | let secs = secs as u32; 126 | 127 | let nanos = d.subsec_nanos() << 2; 128 | let nanos = nanos | secs_nanos; 129 | 130 | buf.extend( 131 | iter::once(Format::FIXEXT8) 132 | .chain(iter::once(Self::TIMESTAMP as u8)) 133 | .chain(nanos.to_be_bytes().iter().copied()) 134 | .chain(secs.to_be_bytes().iter().copied()), 135 | ); 136 | 10 137 | } 138 | 139 | Extension::Timestamp(d) => { 140 | buf.extend( 141 | iter::once(Format::EXT8) 142 | .chain(iter::once(12)) 143 | .chain(iter::once(Self::TIMESTAMP as u8)) 144 | .chain(d.subsec_nanos().to_be_bytes().iter().copied()) 145 | .chain(d.as_secs().to_be_bytes().iter().copied()), 146 | ); 147 | 15 148 | } 149 | } 150 | } 151 | } 152 | 153 | impl Unpackable for Extension { 154 | type Error = Error; 155 | 156 | fn unpack(mut buf: &[u8]) -> Result<(usize, Self), Self::Error> { 157 | let format = take_byte(&mut buf)?; 158 | match format { 159 | Format::FIXEXT1 => { 160 | let t = take_byte(&mut buf)? as i8; 161 | let x = take_byte(&mut buf)?; 162 | Ok((3, Extension::Ext(t, vec![x]))) 163 | } 164 | Format::FIXEXT2 => { 165 | let t = take_byte(&mut buf)? as i8; 166 | let b = take_buffer(&mut buf, 2)?; 167 | Ok((4, Extension::Ext(t, b.to_vec()))) 168 | } 169 | Format::FIXEXT4 => { 170 | let t = take_byte(&mut buf)? as i8; 171 | if t == Self::TIMESTAMP { 172 | let secs = take_num(&mut buf, u32::from_be_bytes)?; 173 | Ok((6, Extension::Timestamp(Duration::from_secs(secs as u64)))) 174 | } else { 175 | let b = take_buffer(&mut buf, 4)?; 176 | Ok((6, Extension::Ext(t, b.to_vec()))) 177 | } 178 | } 179 | Format::FIXEXT8 => { 180 | let t = take_byte(&mut buf)? as i8; 181 | if t == Self::TIMESTAMP { 182 | let data = take_num(&mut buf, u64::from_be_bytes)?; 183 | 184 | let nanos = (data >> 34) as u32; 185 | let secs = data & ((1u64 << 34) - 1); 186 | 187 | Ok((10, Extension::Timestamp(Duration::new(secs, nanos)))) 188 | } else { 189 | let b = take_buffer(&mut buf, 8)?; 190 | Ok((10, Extension::Ext(t, b.to_vec()))) 191 | } 192 | } 193 | Format::FIXEXT16 => { 194 | let t = take_byte(&mut buf)? as i8; 195 | let b = take_buffer(&mut buf, 16)?; 196 | Ok((18, Extension::Ext(t, b.to_vec()))) 197 | } 198 | Format::EXT8 => { 199 | let len = take_byte(&mut buf)? as usize; 200 | let t = take_byte(&mut buf)? as i8; 201 | if len == 12 && t == Self::TIMESTAMP { 202 | let nanos = take_num(&mut buf, u32::from_be_bytes)?; 203 | let secs = take_num(&mut buf, u64::from_be_bytes)?; 204 | Ok((15, Extension::Timestamp(Duration::new(secs, nanos)))) 205 | } else { 206 | let b = take_buffer(&mut buf, len)?; 207 | Ok((3 + len, Extension::Ext(t, b.to_vec()))) 208 | } 209 | } 210 | Format::EXT16 => { 211 | let len = take_num(&mut buf, u16::from_be_bytes)? as usize; 212 | let t = take_byte(&mut buf)? as i8; 213 | let b = take_buffer(&mut buf, len)?; 214 | Ok((4 + len, Extension::Ext(t, b.to_vec()))) 215 | } 216 | Format::EXT32 => { 217 | let len = take_num(&mut buf, u32::from_be_bytes)? as usize; 218 | let t = take_byte(&mut buf)? as i8; 219 | let b = take_buffer(&mut buf, len)?; 220 | Ok((6 + len, Extension::Ext(t, b.to_vec()))) 221 | } 222 | _ => Err(Error::InvalidExtension), 223 | } 224 | } 225 | 226 | fn unpack_iter(bytes: I) -> Result<(usize, Self), Self::Error> 227 | where 228 | I: IntoIterator, 229 | { 230 | let mut bytes = bytes.into_iter(); 231 | let format = take_byte_iter(bytes.by_ref())?; 232 | match format { 233 | Format::FIXEXT1 => { 234 | let t = take_byte_iter(bytes.by_ref())? as i8; 235 | let x = take_byte_iter(bytes.by_ref())?; 236 | Ok((3, Extension::Ext(t, vec![x]))) 237 | } 238 | Format::FIXEXT2 => { 239 | let t = take_byte_iter(bytes.by_ref())? as i8; 240 | let b = take_buffer_iter(bytes.by_ref(), 2)?; 241 | Ok((4, Extension::Ext(t, b))) 242 | } 243 | Format::FIXEXT4 => { 244 | let t = take_byte_iter(bytes.by_ref())? as i8; 245 | if t == Self::TIMESTAMP { 246 | let secs = take_num_iter(bytes.by_ref(), u32::from_be_bytes)?; 247 | Ok((6, Extension::Timestamp(Duration::from_secs(secs as u64)))) 248 | } else { 249 | let b = take_buffer_iter(bytes.by_ref(), 4)?; 250 | Ok((6, Extension::Ext(t, b))) 251 | } 252 | } 253 | Format::FIXEXT8 => { 254 | let t = take_byte_iter(bytes.by_ref())? as i8; 255 | if t == Self::TIMESTAMP { 256 | let data = take_num_iter(bytes.by_ref(), u64::from_be_bytes)?; 257 | 258 | let nanos = (data >> 34) as u32; 259 | let secs = data & ((1u64 << 34) - 1); 260 | 261 | Ok((10, Extension::Timestamp(Duration::new(secs, nanos)))) 262 | } else { 263 | let b = take_buffer_iter(bytes.by_ref(), 8)?; 264 | Ok((10, Extension::Ext(t, b))) 265 | } 266 | } 267 | Format::FIXEXT16 => { 268 | let t = take_byte_iter(bytes.by_ref())? as i8; 269 | let b = take_buffer_iter(bytes.by_ref(), 16)?; 270 | Ok((18, Extension::Ext(t, b))) 271 | } 272 | Format::EXT8 => { 273 | let len = take_byte_iter(bytes.by_ref())? as usize; 274 | let t = take_byte_iter(bytes.by_ref())? as i8; 275 | if len == 12 && t == Self::TIMESTAMP { 276 | let nanos = take_num_iter(bytes.by_ref(), u32::from_be_bytes)?; 277 | let secs = take_num_iter(bytes.by_ref(), u64::from_be_bytes)?; 278 | Ok((15, Extension::Timestamp(Duration::new(secs, nanos)))) 279 | } else { 280 | let b = take_buffer_iter(bytes.by_ref(), len)?; 281 | Ok((3 + len, Extension::Ext(t, b))) 282 | } 283 | } 284 | Format::EXT16 => { 285 | let len = take_num_iter(bytes.by_ref(), u16::from_be_bytes)? as usize; 286 | let t = take_byte_iter(bytes.by_ref())? as i8; 287 | let b = take_buffer_iter(bytes.by_ref(), len)?; 288 | Ok((4 + len, Extension::Ext(t, b))) 289 | } 290 | Format::EXT32 => { 291 | let len = take_num_iter(bytes.by_ref(), u32::from_be_bytes)? as usize; 292 | let t = take_byte_iter(bytes.by_ref())? as i8; 293 | let b = take_buffer_iter(bytes.by_ref(), len)?; 294 | Ok((6 + len, Extension::Ext(t, b))) 295 | } 296 | _ => Err(Error::InvalidExtension), 297 | } 298 | } 299 | } 300 | 301 | #[cfg(test)] 302 | mod tests { 303 | use super::*; 304 | use proptest::prelude::*; 305 | 306 | proptest! { 307 | #[test] 308 | fn extension_bytes(mut t: i8, b: Vec) { 309 | if t == Extension::TIMESTAMP { 310 | t -= 1; 311 | } 312 | let x = Extension::Ext(t, b); 313 | let mut bytes = vec![]; 314 | x.pack(&mut bytes); 315 | let (_, y) = Extension::unpack(&bytes).unwrap(); 316 | assert_eq!(x, y); 317 | } 318 | 319 | #[test] 320 | fn extension_duration(d: Duration) { 321 | let x = Extension::Timestamp(d); 322 | let mut bytes = vec![]; 323 | x.pack(&mut bytes); 324 | let (_, y) = Extension::unpack(&bytes).unwrap(); 325 | assert_eq!(x, y); 326 | } 327 | } 328 | } 329 | -------------------------------------------------------------------------------- /msgpacker/src/unpack/int.rs: -------------------------------------------------------------------------------- 1 | use super::{ 2 | helpers::{take_byte, take_byte_iter, take_num, take_num_iter}, 3 | Error, Format, Unpackable, 4 | }; 5 | 6 | impl Unpackable for u8 { 7 | type Error = Error; 8 | 9 | fn unpack(mut buf: &[u8]) -> Result<(usize, Self), Self::Error> { 10 | let format = take_byte(&mut buf)?; 11 | match format { 12 | 0x00..=Format::POSITIVE_FIXINT => Ok((1, format)), 13 | Format::UINT8 => take_byte(&mut buf).map(|v| (2, v)), 14 | _ => Err(Error::UnexpectedFormatTag), 15 | } 16 | } 17 | 18 | fn unpack_iter(bytes: I) -> Result<(usize, Self), Self::Error> 19 | where 20 | I: IntoIterator, 21 | { 22 | let mut bytes = bytes.into_iter(); 23 | let format = take_byte_iter(bytes.by_ref())?; 24 | match format { 25 | 0x00..=Format::POSITIVE_FIXINT => Ok((1, format)), 26 | Format::UINT8 => take_byte_iter(bytes).map(|v| (2, v)), 27 | _ => Err(Error::UnexpectedFormatTag), 28 | } 29 | } 30 | } 31 | 32 | impl Unpackable for u16 { 33 | type Error = Error; 34 | 35 | fn unpack(mut buf: &[u8]) -> Result<(usize, Self), Self::Error> { 36 | let format = take_byte(&mut buf)?; 37 | match format { 38 | 0x00..=Format::POSITIVE_FIXINT => Ok((1, format as u16)), 39 | Format::UINT8 => take_byte(&mut buf).map(|v| (2, v as u16)), 40 | Format::UINT16 => take_num(&mut buf, u16::from_be_bytes).map(|v| (3, v)), 41 | _ => Err(Error::UnexpectedFormatTag), 42 | } 43 | } 44 | 45 | fn unpack_iter(bytes: I) -> Result<(usize, Self), Self::Error> 46 | where 47 | I: IntoIterator, 48 | { 49 | let mut bytes = bytes.into_iter(); 50 | let format = take_byte_iter(bytes.by_ref())?; 51 | match format { 52 | 0x00..=Format::POSITIVE_FIXINT => Ok((1, format as u16)), 53 | Format::UINT8 => take_byte_iter(bytes).map(|v| (2, v as u16)), 54 | Format::UINT16 => take_num_iter(bytes, u16::from_be_bytes).map(|v| (3, v)), 55 | _ => Err(Error::UnexpectedFormatTag), 56 | } 57 | } 58 | } 59 | 60 | impl Unpackable for u32 { 61 | type Error = Error; 62 | 63 | fn unpack(mut buf: &[u8]) -> Result<(usize, Self), Self::Error> { 64 | let format = take_byte(&mut buf)?; 65 | match format { 66 | 0x00..=Format::POSITIVE_FIXINT => Ok((1, format as u32)), 67 | Format::UINT8 => take_byte(&mut buf).map(|v| (2, v as u32)), 68 | Format::UINT16 => take_num(&mut buf, u16::from_be_bytes).map(|v| (3, v as u32)), 69 | Format::UINT32 => take_num(&mut buf, u32::from_be_bytes).map(|v| (5, v)), 70 | _ => Err(Error::UnexpectedFormatTag), 71 | } 72 | } 73 | 74 | fn unpack_iter(bytes: I) -> Result<(usize, Self), Self::Error> 75 | where 76 | I: IntoIterator, 77 | { 78 | let mut bytes = bytes.into_iter(); 79 | let format = take_byte_iter(bytes.by_ref())?; 80 | match format { 81 | 0x00..=Format::POSITIVE_FIXINT => Ok((1, format as u32)), 82 | Format::UINT8 => take_byte_iter(bytes).map(|v| (2, v as u32)), 83 | Format::UINT16 => take_num_iter(bytes, u16::from_be_bytes).map(|v| (3, v as u32)), 84 | Format::UINT32 => take_num_iter(bytes, u32::from_be_bytes).map(|v| (5, v)), 85 | _ => Err(Error::UnexpectedFormatTag), 86 | } 87 | } 88 | } 89 | 90 | impl Unpackable for u64 { 91 | type Error = Error; 92 | 93 | fn unpack(mut buf: &[u8]) -> Result<(usize, Self), Self::Error> { 94 | let format = take_byte(&mut buf)?; 95 | match format { 96 | 0x00..=Format::POSITIVE_FIXINT => Ok((1, format as u64)), 97 | Format::UINT8 => take_byte(&mut buf).map(|v| (2, v as u64)), 98 | Format::UINT16 => take_num(&mut buf, u16::from_be_bytes).map(|v| (3, v as u64)), 99 | Format::UINT32 => take_num(&mut buf, u32::from_be_bytes).map(|v| (5, v as u64)), 100 | Format::UINT64 => take_num(&mut buf, u64::from_be_bytes).map(|v| (9, v)), 101 | _ => Err(Error::UnexpectedFormatTag), 102 | } 103 | } 104 | 105 | fn unpack_iter(bytes: I) -> Result<(usize, Self), Self::Error> 106 | where 107 | I: IntoIterator, 108 | { 109 | let mut bytes = bytes.into_iter(); 110 | let format = take_byte_iter(bytes.by_ref())?; 111 | match format { 112 | 0x00..=Format::POSITIVE_FIXINT => Ok((1, format as u64)), 113 | Format::UINT8 => take_byte_iter(bytes).map(|v| (2, v as u64)), 114 | Format::UINT16 => take_num_iter(bytes, u16::from_be_bytes).map(|v| (3, v as u64)), 115 | Format::UINT32 => take_num_iter(bytes, u32::from_be_bytes).map(|v| (5, v as u64)), 116 | Format::UINT64 => take_num_iter(bytes, u64::from_be_bytes).map(|v| (9, v)), 117 | _ => Err(Error::UnexpectedFormatTag), 118 | } 119 | } 120 | } 121 | 122 | impl Unpackable for u128 { 123 | type Error = Error; 124 | 125 | fn unpack(mut buf: &[u8]) -> Result<(usize, Self), Self::Error> { 126 | let format = take_byte(&mut buf)?; 127 | match format { 128 | 0x00..=Format::POSITIVE_FIXINT => Ok((1, format as u128)), 129 | Format::UINT8 => take_byte(&mut buf).map(|v| (2, v as u128)), 130 | Format::UINT16 => take_num(&mut buf, u16::from_be_bytes).map(|v| (3, v as u128)), 131 | Format::UINT32 => take_num(&mut buf, u32::from_be_bytes).map(|v| (5, v as u128)), 132 | Format::UINT64 => take_num(&mut buf, u64::from_be_bytes).map(|v| (9, v as u128)), 133 | Format::BIN8 => { 134 | if take_byte(&mut buf)? != 16 { 135 | return Err(Error::UnexpectedBinLength); 136 | } 137 | take_num(&mut buf, u128::from_be_bytes).map(|v| (18, v)) 138 | } 139 | _ => Err(Error::UnexpectedFormatTag), 140 | } 141 | } 142 | 143 | fn unpack_iter(bytes: I) -> Result<(usize, Self), Self::Error> 144 | where 145 | I: IntoIterator, 146 | { 147 | let mut bytes = bytes.into_iter(); 148 | let format = take_byte_iter(bytes.by_ref())?; 149 | match format { 150 | 0x00..=Format::POSITIVE_FIXINT => Ok((1, format as u128)), 151 | Format::UINT8 => take_byte_iter(bytes).map(|v| (2, v as u128)), 152 | Format::UINT16 => take_num_iter(bytes, u16::from_be_bytes).map(|v| (3, v as u128)), 153 | Format::UINT32 => take_num_iter(bytes, u32::from_be_bytes).map(|v| (5, v as u128)), 154 | Format::UINT64 => take_num_iter(bytes, u64::from_be_bytes).map(|v| (9, v as u128)), 155 | Format::BIN8 => { 156 | if take_byte_iter(bytes.by_ref())? != 16 { 157 | return Err(Error::UnexpectedBinLength); 158 | } 159 | take_num_iter(bytes, u128::from_be_bytes).map(|v| (18, v)) 160 | } 161 | _ => Err(Error::UnexpectedFormatTag), 162 | } 163 | } 164 | } 165 | 166 | impl Unpackable for usize { 167 | type Error = Error; 168 | 169 | fn unpack(mut buf: &[u8]) -> Result<(usize, Self), Self::Error> { 170 | let format = take_byte(&mut buf)?; 171 | match format { 172 | 0x00..=Format::POSITIVE_FIXINT => Ok((1, format as usize)), 173 | Format::UINT8 => take_byte(&mut buf).map(|v| (2, v as usize)), 174 | Format::UINT16 => take_num(&mut buf, u16::from_be_bytes).map(|v| (3, v as usize)), 175 | Format::UINT32 => take_num(&mut buf, u32::from_be_bytes).map(|v| (5, v as usize)), 176 | Format::UINT64 => take_num(&mut buf, u64::from_be_bytes).map(|v| (9, v as usize)), 177 | _ => Err(Error::UnexpectedFormatTag), 178 | } 179 | } 180 | 181 | fn unpack_iter(bytes: I) -> Result<(usize, Self), Self::Error> 182 | where 183 | I: IntoIterator, 184 | { 185 | let mut bytes = bytes.into_iter(); 186 | let format = take_byte_iter(bytes.by_ref())?; 187 | match format { 188 | 0x00..=Format::POSITIVE_FIXINT => Ok((1, format as usize)), 189 | Format::UINT8 => take_byte_iter(bytes).map(|v| (2, v as usize)), 190 | Format::UINT16 => take_num_iter(bytes, u16::from_be_bytes).map(|v| (3, v as usize)), 191 | Format::UINT32 => take_num_iter(bytes, u32::from_be_bytes).map(|v| (5, v as usize)), 192 | Format::UINT64 => take_num_iter(bytes, usize::from_be_bytes).map(|v| (9, v)), 193 | _ => Err(Error::UnexpectedFormatTag), 194 | } 195 | } 196 | } 197 | 198 | impl Unpackable for i8 { 199 | type Error = Error; 200 | 201 | fn unpack(mut buf: &[u8]) -> Result<(usize, Self), Self::Error> { 202 | let format = take_byte(&mut buf)?; 203 | match format { 204 | 0x00..=Format::POSITIVE_FIXINT => Ok((1, format as i8)), 205 | 0xe0.. => Ok((1, format as i8)), 206 | Format::INT8 => take_byte(&mut buf).map(|v| (2, v as i8)), 207 | _ => Err(Error::UnexpectedFormatTag), 208 | } 209 | } 210 | 211 | fn unpack_iter(bytes: I) -> Result<(usize, Self), Self::Error> 212 | where 213 | I: IntoIterator, 214 | { 215 | let mut bytes = bytes.into_iter(); 216 | let format = take_byte_iter(bytes.by_ref())?; 217 | match format { 218 | 0x00..=Format::POSITIVE_FIXINT => Ok((1, format as i8)), 219 | 0xe0.. => Ok((1, format as i8)), 220 | Format::INT8 => take_byte_iter(bytes).map(|v| (2, v as i8)), 221 | _ => Err(Error::UnexpectedFormatTag), 222 | } 223 | } 224 | } 225 | 226 | impl Unpackable for i16 { 227 | type Error = Error; 228 | 229 | fn unpack(mut buf: &[u8]) -> Result<(usize, Self), Self::Error> { 230 | let format = take_byte(&mut buf)?; 231 | match format { 232 | 0x00..=Format::POSITIVE_FIXINT => Ok((1, (format as i8) as i16)), 233 | 0xe0.. => Ok((1, (format as i8) as i16)), 234 | Format::INT8 => take_byte(&mut buf).map(|v| (2, v as i8 as i16)), 235 | Format::INT16 => take_num(&mut buf, i16::from_be_bytes).map(|v| (3, v)), 236 | _ => Err(Error::UnexpectedFormatTag), 237 | } 238 | } 239 | 240 | fn unpack_iter(bytes: I) -> Result<(usize, Self), Self::Error> 241 | where 242 | I: IntoIterator, 243 | { 244 | let mut bytes = bytes.into_iter(); 245 | let format = take_byte_iter(bytes.by_ref())?; 246 | match format { 247 | 0x00..=Format::POSITIVE_FIXINT => Ok((1, (format as i8) as i16)), 248 | 0xe0.. => Ok((1, (format as i8) as i16)), 249 | Format::INT8 => take_byte_iter(bytes).map(|v| (2, v as i8 as i16)), 250 | Format::INT16 => take_num_iter(bytes, i16::from_be_bytes).map(|v| (3, v)), 251 | _ => Err(Error::UnexpectedFormatTag), 252 | } 253 | } 254 | } 255 | 256 | impl Unpackable for i32 { 257 | type Error = Error; 258 | 259 | fn unpack(mut buf: &[u8]) -> Result<(usize, Self), Self::Error> { 260 | let format = take_byte(&mut buf)?; 261 | match format { 262 | 0x00..=Format::POSITIVE_FIXINT => Ok((1, (format as i8) as i32)), 263 | 0xe0.. => Ok((1, (format as i8) as i32)), 264 | Format::INT8 => take_byte(&mut buf).map(|v| (2, v as i8 as i32)), 265 | Format::INT16 => take_num(&mut buf, i16::from_be_bytes).map(|v| (3, v as i32)), 266 | Format::INT32 => take_num(&mut buf, i32::from_be_bytes).map(|v| (5, v)), 267 | _ => Err(Error::UnexpectedFormatTag), 268 | } 269 | } 270 | 271 | fn unpack_iter(bytes: I) -> Result<(usize, Self), Self::Error> 272 | where 273 | I: IntoIterator, 274 | { 275 | let mut bytes = bytes.into_iter(); 276 | let format = take_byte_iter(bytes.by_ref())?; 277 | match format { 278 | 0x00..=Format::POSITIVE_FIXINT => Ok((1, (format as i8) as i32)), 279 | 0xe0.. => Ok((1, (format as i8) as i32)), 280 | Format::INT8 => take_byte_iter(bytes).map(|v| (2, v as i8 as i32)), 281 | Format::INT16 => take_num_iter(bytes, i16::from_be_bytes).map(|v| (3, v as i32)), 282 | Format::INT32 => take_num_iter(bytes, i32::from_be_bytes).map(|v| (5, v)), 283 | _ => Err(Error::UnexpectedFormatTag), 284 | } 285 | } 286 | } 287 | 288 | impl Unpackable for i64 { 289 | type Error = Error; 290 | 291 | fn unpack(mut buf: &[u8]) -> Result<(usize, Self), Self::Error> { 292 | let format = take_byte(&mut buf)?; 293 | match format { 294 | 0x00..=Format::POSITIVE_FIXINT => Ok((1, (format as i8) as i64)), 295 | 0xe0.. => Ok((1, (format as i8) as i64)), 296 | Format::INT8 => take_byte(&mut buf).map(|v| (2, v as i8 as i64)), 297 | Format::INT16 => take_num(&mut buf, i16::from_be_bytes).map(|v| (3, v as i64)), 298 | Format::INT32 => take_num(&mut buf, i32::from_be_bytes).map(|v| (5, v as i64)), 299 | Format::INT64 => take_num(&mut buf, i64::from_be_bytes).map(|v| (9, v)), 300 | _ => Err(Error::UnexpectedFormatTag), 301 | } 302 | } 303 | 304 | fn unpack_iter(bytes: I) -> Result<(usize, Self), Self::Error> 305 | where 306 | I: IntoIterator, 307 | { 308 | let mut bytes = bytes.into_iter(); 309 | let format = take_byte_iter(bytes.by_ref())?; 310 | match format { 311 | 0x00..=Format::POSITIVE_FIXINT => Ok((1, (format as i8) as i64)), 312 | 0xe0.. => Ok((1, (format as i8) as i64)), 313 | Format::INT8 => take_byte_iter(bytes).map(|v| (2, v as i8 as i64)), 314 | Format::INT16 => take_num_iter(bytes, i16::from_be_bytes).map(|v| (3, v as i64)), 315 | Format::INT32 => take_num_iter(bytes, i32::from_be_bytes).map(|v| (5, v as i64)), 316 | Format::INT64 => take_num_iter(bytes, i64::from_be_bytes).map(|v| (9, v)), 317 | _ => Err(Error::UnexpectedFormatTag), 318 | } 319 | } 320 | } 321 | 322 | impl Unpackable for i128 { 323 | type Error = Error; 324 | 325 | fn unpack(mut buf: &[u8]) -> Result<(usize, Self), Self::Error> { 326 | let format = take_byte(&mut buf)?; 327 | match format { 328 | 0x00..=Format::POSITIVE_FIXINT => Ok((1, (format as i8) as i128)), 329 | 0xe0.. => Ok((1, (format as i8) as i128)), 330 | Format::INT8 => take_byte(&mut buf).map(|v| (2, v as i8 as i128)), 331 | Format::INT16 => take_num(&mut buf, i16::from_be_bytes).map(|v| (3, v as i128)), 332 | Format::INT32 => take_num(&mut buf, i32::from_be_bytes).map(|v| (5, v as i128)), 333 | Format::INT64 => take_num(&mut buf, i64::from_be_bytes).map(|v| (9, v as i128)), 334 | Format::BIN8 => { 335 | if take_byte(&mut buf)? != 16 { 336 | return Err(Error::UnexpectedBinLength); 337 | } 338 | take_num(&mut buf, i128::from_be_bytes).map(|v| (18, v)) 339 | } 340 | _ => Err(Error::UnexpectedFormatTag), 341 | } 342 | } 343 | 344 | fn unpack_iter(bytes: I) -> Result<(usize, Self), Self::Error> 345 | where 346 | I: IntoIterator, 347 | { 348 | let mut bytes = bytes.into_iter(); 349 | let format = take_byte_iter(bytes.by_ref())?; 350 | match format { 351 | 0x00..=Format::POSITIVE_FIXINT => Ok((1, (format as i8) as i128)), 352 | 0xe0.. => Ok((1, (format as i8) as i128)), 353 | Format::INT8 => take_byte_iter(bytes).map(|v| (2, v as i8 as i128)), 354 | Format::INT16 => take_num_iter(bytes, i16::from_be_bytes).map(|v| (3, v as i128)), 355 | Format::INT32 => take_num_iter(bytes, i32::from_be_bytes).map(|v| (5, v as i128)), 356 | Format::INT64 => take_num_iter(bytes, i64::from_be_bytes).map(|v| (9, v as i128)), 357 | Format::BIN8 => { 358 | if take_byte_iter(bytes.by_ref())? != 16 { 359 | return Err(Error::UnexpectedBinLength); 360 | } 361 | take_num_iter(bytes, i128::from_be_bytes).map(|v| (18, v)) 362 | } 363 | _ => Err(Error::UnexpectedFormatTag), 364 | } 365 | } 366 | } 367 | 368 | impl Unpackable for isize { 369 | type Error = Error; 370 | 371 | fn unpack(mut buf: &[u8]) -> Result<(usize, Self), Self::Error> { 372 | let format = take_byte(&mut buf)?; 373 | match format { 374 | 0x00..=Format::POSITIVE_FIXINT => Ok((1, (format as i8) as isize)), 375 | 0xe0.. => Ok((1, (format as i8) as isize)), 376 | Format::INT8 => take_byte(&mut buf).map(|v| (2, v as i8 as isize)), 377 | Format::INT16 => take_num(&mut buf, i16::from_be_bytes).map(|v| (3, v as isize)), 378 | Format::INT32 => take_num(&mut buf, i32::from_be_bytes).map(|v| (5, v as isize)), 379 | Format::INT64 => take_num(&mut buf, i64::from_be_bytes).map(|v| (9, v as isize)), 380 | _ => Err(Error::UnexpectedFormatTag), 381 | } 382 | } 383 | 384 | fn unpack_iter(bytes: I) -> Result<(usize, Self), Self::Error> 385 | where 386 | I: IntoIterator, 387 | { 388 | let mut bytes = bytes.into_iter(); 389 | let format = take_byte_iter(bytes.by_ref())?; 390 | match format { 391 | 0x00..=Format::POSITIVE_FIXINT => Ok((1, (format as i8) as isize)), 392 | 0xe0.. => Ok((1, (format as i8) as isize)), 393 | Format::INT8 => take_byte_iter(bytes).map(|v| (2, v as i8 as isize)), 394 | Format::INT16 => take_num_iter(bytes, i16::from_be_bytes).map(|v| (3, v as isize)), 395 | Format::INT32 => take_num_iter(bytes, i32::from_be_bytes).map(|v| (5, v as isize)), 396 | Format::INT64 => take_num_iter(bytes, i64::from_be_bytes).map(|v| (9, v as isize)), 397 | _ => Err(Error::UnexpectedFormatTag), 398 | } 399 | } 400 | } 401 | -------------------------------------------------------------------------------- /msgpacker-derive/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![crate_type = "proc-macro"] 2 | extern crate proc_macro; 3 | 4 | // This code is bad and should be refactored into something cleaner. Maybe some syn-based 5 | // framework? 6 | 7 | use proc_macro::TokenStream; 8 | use quote::quote; 9 | use syn::punctuated::Punctuated; 10 | use syn::{ 11 | parse_macro_input, parse_quote, parse_str, Block, Data, DataEnum, DataStruct, DataUnion, 12 | DeriveInput, Expr, ExprMatch, ExprTuple, Field, FieldPat, FieldValue, Fields, FieldsNamed, 13 | FieldsUnnamed, GenericArgument, Ident, Member, Meta, Pat, PatIdent, PathArguments, Token, Type, 14 | Variant, 15 | }; 16 | 17 | fn contains_attribute(field: &Field, name: &str) -> bool { 18 | let name = name.to_string(); 19 | if let Some(attr) = field.attrs.first() { 20 | if let Meta::List(list) = &attr.meta { 21 | if list.path.is_ident("msgpacker") { 22 | if list 23 | .tokens 24 | .clone() 25 | .into_iter() 26 | .find(|a| a.to_string() == name) 27 | .is_some() 28 | { 29 | return true; 30 | } 31 | } 32 | } 33 | } 34 | false 35 | } 36 | 37 | fn impl_fields_named(name: Ident, f: FieldsNamed) -> impl Into { 38 | let mut values: Punctuated = Punctuated::new(); 39 | let block_packable: Block = parse_quote! { 40 | { 41 | let mut n = 0; 42 | } 43 | }; 44 | let block_unpackable: Block = parse_quote! { 45 | { 46 | let mut n = 0; 47 | } 48 | }; 49 | let block_unpackable_iter: Block = parse_quote! { 50 | { 51 | let mut bytes = bytes.into_iter(); 52 | let mut n = 0; 53 | } 54 | }; 55 | 56 | let ( 57 | mut block_packable, 58 | mut block_unpackable, 59 | mut block_unpackable_iter 60 | ) = f.named.into_pairs().map(|p| p.into_value()).fold( 61 | (block_packable, block_unpackable, block_unpackable_iter), 62 | |(mut block_packable, mut block_unpackable, mut block_unpackable_iter), field| { 63 | let ident = field.ident.as_ref().cloned().unwrap(); 64 | let ty = field.ty.clone(); 65 | 66 | let mut is_vec = false; 67 | let mut is_vec_u8 = false; 68 | 69 | match &ty { 70 | Type::Path(p) if p.path.segments.last().filter(|p| p.ident.to_string() == "Vec").is_some() => { 71 | is_vec = true; 72 | match &p.path.segments.last().unwrap().arguments { 73 | PathArguments::AngleBracketed(a) if a.args.len() == 1 => { 74 | if let Some(GenericArgument::Type(Type::Path(p))) = a.args.first() { 75 | if p.path.segments.last().filter(|p| p.ident.to_string() == "u8").is_some() { 76 | is_vec_u8 = true; 77 | } 78 | } 79 | } 80 | _ => (), 81 | } 82 | } 83 | 84 | _ => (), 85 | } 86 | 87 | if contains_attribute(&field, "map") { 88 | block_packable.stmts.push(parse_quote! { 89 | n += ::msgpacker::pack_map(buf, &self.#ident); 90 | }); 91 | 92 | block_unpackable.stmts.push(parse_quote! { 93 | let #ident = ::msgpacker::unpack_map(buf).map(|(nv, t)| { 94 | n += nv; 95 | buf = &buf[nv..]; 96 | t 97 | })?; 98 | }); 99 | 100 | block_unpackable_iter.stmts.push(parse_quote! { 101 | let #ident = ::msgpacker::unpack_map_iter(bytes.by_ref()).map(|(nv, t)| { 102 | n += nv; 103 | t 104 | })?; 105 | }); 106 | } else if contains_attribute(&field, "array") || is_vec && !is_vec_u8 { 107 | block_packable.stmts.push(parse_quote! { 108 | n += ::msgpacker::pack_array(buf, &self.#ident); 109 | }); 110 | 111 | block_unpackable.stmts.push(parse_quote! { 112 | let #ident = ::msgpacker::unpack_array(buf).map(|(nv, t)| { 113 | n += nv; 114 | buf = &buf[nv..]; 115 | t 116 | })?; 117 | }); 118 | 119 | block_unpackable_iter.stmts.push(parse_quote! { 120 | let #ident = ::msgpacker::unpack_array_iter(bytes.by_ref()).map(|(nv, t)| { 121 | n += nv; 122 | t 123 | })?; 124 | }); 125 | } else { 126 | block_packable.stmts.push(parse_quote! { 127 | n += <#ty as ::msgpacker::Packable>::pack(&self.#ident, buf); 128 | }); 129 | 130 | block_unpackable.stmts.push(parse_quote! { 131 | let #ident = ::msgpacker::Unpackable::unpack(buf).map(|(nv, t)| { 132 | n += nv; 133 | buf = &buf[nv..]; 134 | t 135 | })?; 136 | }); 137 | 138 | block_unpackable_iter.stmts.push(parse_quote! { 139 | let #ident = ::msgpacker::Unpackable::unpack_iter(bytes.by_ref()).map(|(nv, t)| { 140 | n += nv; 141 | t 142 | })?; 143 | }); 144 | } 145 | 146 | 147 | values.push(FieldValue { 148 | attrs: vec![], 149 | member: Member::Named(ident.clone()), 150 | colon_token: Some(::default()), 151 | expr: parse_quote! { #ident }, 152 | }); 153 | 154 | (block_packable, block_unpackable, block_unpackable_iter) 155 | }, 156 | ); 157 | 158 | block_packable.stmts.push(parse_quote! { 159 | return n; 160 | }); 161 | 162 | block_unpackable.stmts.push(parse_quote! { 163 | return Ok(( 164 | n, 165 | Self { 166 | #values 167 | }, 168 | )); 169 | }); 170 | 171 | block_unpackable_iter.stmts.push(parse_quote! { 172 | return Ok(( 173 | n, 174 | Self { 175 | #values 176 | }, 177 | )); 178 | }); 179 | 180 | quote! { 181 | impl ::msgpacker::Packable for #name { 182 | fn pack(&self, buf: &mut T) -> usize 183 | where 184 | T: Extend, 185 | #block_packable 186 | } 187 | 188 | impl ::msgpacker::Unpackable for #name { 189 | type Error = ::msgpacker::Error; 190 | 191 | fn unpack(mut buf: &[u8]) -> Result<(usize, Self), Self::Error> 192 | #block_unpackable 193 | 194 | fn unpack_iter(bytes: I) -> Result<(usize, Self), Self::Error> 195 | where 196 | I: IntoIterator, 197 | #block_unpackable_iter 198 | } 199 | } 200 | } 201 | 202 | fn impl_fields_unnamed(name: Ident, f: FieldsUnnamed) -> impl Into { 203 | let mut values: Punctuated = Punctuated::new(); 204 | let block_packable: Block = parse_quote! { 205 | { 206 | let mut n = 0; 207 | } 208 | }; 209 | let block_unpackable: Block = parse_quote! { 210 | { 211 | let mut n = 0; 212 | } 213 | }; 214 | let block_unpackable_iter: Block = parse_quote! { 215 | { 216 | let mut bytes = bytes.into_iter(); 217 | let mut n = 0; 218 | } 219 | }; 220 | 221 | let (mut block_packable, mut block_unpackable, mut block_unpackable_iter) = f 222 | .unnamed 223 | .into_pairs() 224 | .map(|p| p.into_value()) 225 | .enumerate() 226 | .fold( 227 | (block_packable, block_unpackable, block_unpackable_iter), 228 | |(mut block_packable, mut block_unpackable, mut block_unpackable_iter), (i, field)| { 229 | let ty = field.ty.clone(); 230 | let var: Expr = parse_str(format!("v{}", i).as_str()).unwrap(); 231 | let slf: Expr = parse_str(format!("self.{}", i).as_str()).unwrap(); 232 | 233 | if contains_attribute(&field, "map") { 234 | todo!("unnamed map is not implemented for derive macro; implement the traits manually") 235 | } else if contains_attribute(&field, "array") { 236 | todo!("unnamed array is not implemented for derive macro; implement the traits manually") 237 | } else { 238 | block_packable.stmts.push(parse_quote! { 239 | n += <#ty as ::msgpacker::Packable>::pack(&#slf, buf); 240 | }); 241 | 242 | block_unpackable.stmts.push(parse_quote! { 243 | let #var = ::msgpacker::Unpackable::unpack(buf).map(|(nv, t)| { 244 | n += nv; 245 | buf = &buf[nv..]; 246 | t 247 | })?; 248 | }); 249 | 250 | block_unpackable_iter.stmts.push(parse_quote! { 251 | let #var = ::msgpacker::Unpackable::unpack_iter(bytes.by_ref()).map(|(nv, t)| { 252 | n += nv; 253 | t 254 | })?; 255 | }); 256 | } 257 | 258 | values.push(var); 259 | 260 | (block_packable, block_unpackable, block_unpackable_iter) 261 | }, 262 | ); 263 | 264 | block_packable.stmts.push(parse_quote! { 265 | return n; 266 | }); 267 | 268 | block_unpackable.stmts.push(parse_quote! { 269 | return Ok((n, Self(#values))); 270 | }); 271 | 272 | block_unpackable_iter.stmts.push(parse_quote! { 273 | return Ok((n, Self(#values))); 274 | }); 275 | 276 | quote! { 277 | impl ::msgpacker::Packable for #name { 278 | fn pack(&self, buf: &mut T) -> usize 279 | where 280 | T: Extend, 281 | #block_packable 282 | } 283 | 284 | impl ::msgpacker::Unpackable for #name { 285 | type Error = ::msgpacker::Error; 286 | 287 | fn unpack(mut buf: &[u8]) -> Result<(usize, Self), Self::Error> 288 | #block_unpackable 289 | 290 | fn unpack_iter(bytes: I) -> Result<(usize, Self), Self::Error> 291 | where 292 | I: IntoIterator, 293 | #block_unpackable_iter 294 | } 295 | } 296 | } 297 | 298 | fn impl_fields_unit(name: Ident) -> impl Into { 299 | quote! { 300 | impl ::msgpacker::Packable for #name { 301 | fn pack(&self, _buf: &mut T) -> usize 302 | where 303 | T: Extend, 304 | { 305 | 0 306 | } 307 | } 308 | 309 | impl ::msgpacker::Unpackable for #name { 310 | type Error = ::msgpacker::Error; 311 | 312 | fn unpack(mut buf: &[u8]) -> Result<(usize, Self), Self::Error> { 313 | Ok((0, Self)) 314 | } 315 | 316 | fn unpack_iter(bytes: I) -> Result<(usize, Self), Self::Error> 317 | where 318 | I: IntoIterator, 319 | { 320 | Ok((0, Self)) 321 | } 322 | } 323 | } 324 | } 325 | 326 | fn impl_fields_enum(name: Ident, v: Punctuated) -> impl Into { 327 | if v.is_empty() { 328 | todo!("empty enum is not implemented for derive macro; implement the traits manually"); 329 | } 330 | 331 | let mut block_packable: ExprMatch = parse_quote! { 332 | match self { 333 | } 334 | }; 335 | 336 | let mut block_unpackable: ExprMatch = parse_quote! { 337 | match discriminant { 338 | } 339 | }; 340 | 341 | let mut block_unpackable_iter: ExprMatch = parse_quote! { 342 | match discriminant { 343 | } 344 | }; 345 | 346 | v.into_iter().enumerate().for_each(|(i, v)| { 347 | let discriminant = v 348 | .discriminant 349 | .map(|(_, d)| d) 350 | .unwrap_or_else(|| parse_str(format!("{}", i).as_str()).unwrap()); 351 | 352 | // TODO check attributes of the field 353 | let ident = v.ident.clone(); 354 | match v.fields { 355 | Fields::Named(f) => { 356 | let mut blk: Block = parse_str("{}").unwrap(); 357 | let mut blk_unpack: Block = parse_str("{}").unwrap(); 358 | let mut blk_unpack_iter: Block = parse_str("{}").unwrap(); 359 | let mut blk_unpack_fields: Punctuated = Punctuated::new(); 360 | 361 | blk.stmts.push(parse_quote! { 362 | n += (#discriminant as u32).pack(buf); 363 | }); 364 | 365 | f.named 366 | .iter() 367 | .filter_map(|n| n.ident.as_ref()) 368 | .for_each(|field| { 369 | blk.stmts.push(parse_quote! { 370 | n += #field.pack(buf); 371 | }); 372 | 373 | blk_unpack_fields.push(parse_quote! { #field }); 374 | 375 | blk_unpack.stmts.push(parse_quote! { 376 | let #field =::msgpacker::Unpackable::unpack(buf).map(|(nv, t)| { 377 | n += nv; 378 | buf = &buf[nv..]; 379 | t 380 | })?; 381 | }); 382 | 383 | blk_unpack_iter.stmts.push(parse_quote! { 384 | let #field =::msgpacker::Unpackable::unpack_iter(bytes.by_ref()).map(|(nv, t)| { 385 | n += nv; 386 | t 387 | })?; 388 | }); 389 | }); 390 | 391 | let mut arm: syn::Arm = parse_quote! { 392 | #name::#ident {} => #blk, 393 | }; 394 | 395 | f.named 396 | .iter() 397 | .filter_map(|n| n.ident.as_ref()) 398 | .for_each(|field| { 399 | match &mut arm.pat { 400 | Pat::Struct(s) => { 401 | s.fields.push(FieldPat { 402 | attrs: vec![], 403 | member: Member::Named(field.clone()), 404 | colon_token: None, 405 | pat: Box::new(Pat::Ident(PatIdent { 406 | attrs: vec![], 407 | by_ref: None, 408 | mutability: None, 409 | ident: field.clone(), 410 | subpat: None, 411 | })), 412 | }); 413 | } 414 | _ => todo!( 415 | "enum variant is not implemented for derive macro; implement the traits manually" 416 | ), 417 | } 418 | }); 419 | 420 | block_packable.arms.push(arm); 421 | 422 | blk_unpack.stmts.push(parse_quote! { 423 | slf = #name::#ident { #blk_unpack_fields }; 424 | }); 425 | 426 | blk_unpack_iter.stmts.push(parse_quote! { 427 | slf = #name::#ident { #blk_unpack_fields }; 428 | }); 429 | 430 | block_unpackable.arms.push(parse_quote! { 431 | #discriminant => #blk_unpack, 432 | }); 433 | 434 | block_unpackable_iter.arms.push(parse_quote! { 435 | #discriminant => #blk_unpack_iter, 436 | }); 437 | } 438 | 439 | Fields::Unnamed(f) => { 440 | let mut blk: Block = parse_str("{}").unwrap(); 441 | let mut blk_unpack: Block = parse_str("{}").unwrap(); 442 | let mut blk_unpack_iter: Block = parse_str("{}").unwrap(); 443 | 444 | blk.stmts.push(parse_quote! { 445 | n += (#discriminant as u32).pack(buf); 446 | }); 447 | 448 | let mut tuple_arm: ExprTuple = parse_str("()").unwrap(); 449 | f.unnamed.iter().enumerate().for_each(|(ii, _field)| { 450 | let ti: Expr = parse_str(format!("t{}", ii).as_str()).unwrap(); 451 | tuple_arm.elems.push(ti.clone()); 452 | 453 | blk.stmts.push(parse_quote! { 454 | n += #ti.pack(buf); 455 | }); 456 | 457 | blk_unpack.stmts.push(parse_quote! { 458 | let #ti =::msgpacker::Unpackable::unpack(buf).map(|(nv, t)| { 459 | n += nv; 460 | buf = &buf[nv..]; 461 | t 462 | })?; 463 | }); 464 | 465 | blk_unpack_iter.stmts.push(parse_quote! { 466 | let #ti =::msgpacker::Unpackable::unpack_iter(bytes.by_ref()).map(|(nv, t)| { 467 | n += nv; 468 | t 469 | })?; 470 | }); 471 | }); 472 | 473 | blk_unpack.stmts.push(parse_quote! { 474 | slf = #name::#ident #tuple_arm; 475 | }); 476 | 477 | blk_unpack_iter.stmts.push(parse_quote! { 478 | slf = #name::#ident #tuple_arm; 479 | }); 480 | 481 | block_packable.arms.push(parse_quote! { 482 | #name::#ident #tuple_arm => #blk, 483 | }); 484 | 485 | block_unpackable.arms.push(parse_quote! { 486 | #discriminant => #blk_unpack, 487 | }); 488 | 489 | block_unpackable_iter.arms.push(parse_quote! { 490 | #discriminant => #blk_unpack_iter, 491 | }); 492 | } 493 | 494 | Fields::Unit => { 495 | block_packable.arms.push(parse_quote! { 496 | #name::#ident => { 497 | n += (#discriminant as u32).pack(buf); 498 | } 499 | }); 500 | 501 | block_unpackable.arms.push(parse_quote! { 502 | #discriminant => slf = #name::#ident, 503 | }); 504 | 505 | block_unpackable_iter.arms.push(parse_quote! { 506 | #discriminant => slf = #name::#ident, 507 | }); 508 | } 509 | } 510 | }); 511 | 512 | block_unpackable.arms.push(parse_quote! { 513 | _ => { 514 | return Err(::msgpacker::Error::InvalidEnumVariant); 515 | } 516 | }); 517 | 518 | block_unpackable_iter.arms.push(parse_quote! { 519 | _ => { 520 | return Err(::msgpacker::Error::InvalidEnumVariant); 521 | } 522 | }); 523 | 524 | quote! { 525 | impl ::msgpacker::Packable for #name { 526 | fn pack(&self, buf: &mut T) -> usize 527 | where 528 | T: Extend, 529 | { 530 | let mut n = 0; 531 | 532 | #block_packable; 533 | 534 | return n; 535 | } 536 | } 537 | 538 | impl ::msgpacker::Unpackable for #name { 539 | type Error = ::msgpacker::Error; 540 | 541 | #[allow(unused_mut)] 542 | fn unpack(mut buf: &[u8]) -> Result<(usize, Self), Self::Error> { 543 | let (mut n, discriminant) = u32::unpack(&mut buf)?; 544 | buf = &buf[n..]; 545 | let slf; 546 | 547 | #block_unpackable; 548 | 549 | Ok((n, slf)) 550 | } 551 | 552 | fn unpack_iter(bytes: I) -> Result<(usize, Self), Self::Error> 553 | where 554 | I: IntoIterator, 555 | { 556 | let mut bytes = bytes.into_iter(); 557 | let (mut n, discriminant) = u32::unpack_iter(bytes.by_ref())?; 558 | let slf; 559 | 560 | #block_unpackable_iter; 561 | 562 | Ok((n, slf)) 563 | } 564 | } 565 | } 566 | } 567 | 568 | #[proc_macro_derive(MsgPacker, attributes(msgpacker))] 569 | pub fn msg_packer(input: TokenStream) -> TokenStream { 570 | let input = parse_macro_input!(input as DeriveInput); 571 | 572 | let name = input.ident; 573 | let data = input.data; 574 | match data { 575 | Data::Struct(DataStruct { 576 | fields: Fields::Named(f), 577 | .. 578 | }) => impl_fields_named(name, f).into(), 579 | 580 | Data::Struct(DataStruct { 581 | fields: Fields::Unnamed(f), 582 | .. 583 | }) => impl_fields_unnamed(name, f).into(), 584 | 585 | Data::Struct(DataStruct { 586 | fields: Fields::Unit, 587 | .. 588 | }) => impl_fields_unit(name).into(), 589 | 590 | Data::Enum(DataEnum { variants, .. }) => impl_fields_enum(name, variants).into(), 591 | 592 | Data::Union(DataUnion { .. }) => { 593 | todo!( 594 | "union support is not implemented for derive macro; implement the traits manually" 595 | ) 596 | } 597 | } 598 | } 599 | --------------------------------------------------------------------------------