rmp-0.8.11/.cargo_vcs_info.json0000644000000001410000000000100117150ustar { "git": { "sha1": "36940d05eb4ebcafddd8141b864d3afea0142376" }, "path_in_vcs": "rmp" }rmp-0.8.11/CHANGELOG.md000064400000000000000000000163250072674642500123610ustar 00000000000000# Change Log All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). ## Unreleased (0.8.11) ### Added - Implemeneted support for `#![no_std]` in `rmpv` - Adds new `feature="std"` (on by default) - Introduces new `RmpRead` and `RmpWrite` traits. - Needed because `std::io::Read` (and Write) are missing on `#![no_std]` - Introduces new `Bytes` and `ByteBuf` wrappers, that implement RmpRead/RmpWrite for no\_std targets. ## 0.8.6 - 2017-04-23 ### Added - New `rmp::decode::read_str_from_slice` function for zero-copy reading strings from slices. ### Changed - Deprecate `rmp::decode::read_str_ref`, because it's useless and inconvenient. ## 0.8.5 - 2017-03-13 ### Fixed - Fix compilation on rustc 1.13.0. ## 0.8.4 - 2017-03-09 ### Added - Derive `Debug` for `MarkerReadError`. ## 0.8.3 - 2017-03-04 ### Fixed - Fixed `write_sint`, so it should mark positive values as unsigned integers. Before this change it marked signed integers larger than `4294967296` with I64 marker, which is not consistent with other MessagePack implementations. Now it should mark such integers with U64 marker. ## 0.8.2 - 2017-02-01 ### Added - Conversion from `ValueWriteError` into I/O error. ## 0.8.1 - 2017-01-05 ### Changed - Fixed docs link. ## 0.8.0 - 2017-01-05 ### Added - Marker now implements `From` and `Into` traits for `u8`. - Add `read_int` function, which allows to read integer values and automatically cast to the expected result type even if they aren't the same. An additional `OutOfRange` error will be returned in the case of failed numeric cast. - Add `NumValueReadError` enum with additional `OutOfRange` variant to be able to detect whether integer decoding failed because of out of range. ### Changed - Update `byteorder` dependency to 1.0. - Unexpected EOF variant has been merged with the default one in the I/O Error enum. - Function `write_sint` now encodes 64-bit signed integers using the most compact representation. - Function `write_uint` now encodes 64-bit unsigned integers using the most compact representation. - Rename `read_array_size` function to `read_array_len` for consistency. - Rename `read_map_size` function to `read_map_len` for consistency. - Make `FixedValueWriteError` struct private. All functions, that previously returned such kind of error now return the Standard I/O error. ### Removed - Move `Value` and `ValueRef` enums and associated functions into the separate `rmpv` crate. - Remove conversions from `byteorder` crate errors, because since 0.5 there are no such errors. - Remove `write_sint_eff` function - its functionality can now be done using `write_sint` instead. - Remove `write_uint_eff` function - its functionality can now be done using `write_uint` instead. - Integral functions like `read_*_loosely` and `read_*_fit` were removed in favor of generic `read_int` function, which allows to read integral values and cast them to the specified result type even if they aren't the same. - Remove `read_bin_borrow` function. ## 0.7.5 - 2016-07-24 ### Added - Add `is_*` methods for Value for checking its underlying value without explicit matching. - Add `as_*` methods for Value for borrowing its underlying value. - Value is now indexable by integer. ## 0.7.4 - 2016-07-18 ### Added - Value now can be initialized from primitive values using From trait. ## 0.7.3 - 2015-09-23 ### Changed - Restricted upper version limit for dependencies. ## 0.7.2 - 2015-09-23 ### Added - Implemented `Display` trait for `Value`. ## 0.7.1 - 2015-09-11 ### Changed - Use `to_owned` instead of `to_string` while converting `ValueRef` into `Value`. This change improves `ValueRef::to_owned()` method performance by approximately 10-20%.s Also after this change it's cheaper to decode directly into `ValueRef` with further converting to owned value rather than decoding directly into `Value`. ## 0.7.0 - 2015-08-24 ### Changed - The big single crate has been refactored, which results in three crates: `rmp`, `rmp-serialize` and `rmp-serde`. ## 0.6.0 - 2015-08-17 ### Added - Initial support for [Serde](https://github.com/serde-rs/serde) serializer and deserializer. - Efficient bytes serialization with Serde. - Efficient binaries deserialization with Serde using `ByteBuf`. - Rust serialize Decoder now can provide the underlying reader both by reference or by value, destroying itself in the last case. ### Changed - Update well-formness for `BigEndianRead` trait to be implemented only for sized types. - Renamed `PositiveFixnum` marker to `FixPos`. - Renamed `NegativeFixnum` marker to `FixNeg`. - Renamed `FixedString` marker to `FixStr`. - Renamed `FixedArray` marker to `FixArray`. - Renamed `FixedMap` to `FixMap`. - Minor documentation updates and markdown fixes. ## 0.5.1 - 2015-08-10 ### Changed - Now the `rustc_serialize::Encoder` should encode signed integers using the most effective underlying representation. - Now the `rustc_serialize::Decoder` should properly map integers to the result type if the decoded value fits in result type's range. ## 0.5.0 - 2015-08-01 ### Added - New `ValueRef` value struct represents MessagePack'ed value, but unlike an owning `Value` it owns nothing except its structure. It means that all strings and binaries it contains are borrowed from the byte array from which the value was created. - New `BorrowRead` trait, which looks like a standard `BufRead` but unlike the standard this has an explicit internal buffer lifetime, which allows to borrow from underlying buffer while mutating the type. - Encoding function for `ValueRef` with its own error category. - Decoding function for `ValueRef` with its own error category. - Conversion method from `ValueRef` to `Value`. - More benchmarks and tests. ### Changed - Derive `Copy` trait for `Integer` and `Float` enums. ## 0.4.0 - 2015-07-17 ### Added - Low level `write_str` function allows to serialize the UTF-8 encoded strings the most efficient way. - Low level `write_bin` function allows to serialize the binary array the most efficient way. - Implemented `std::error::Error` trait for error types. ## 0.3.2 - 2015-07-05 ### Changed - Encoder now should return proper error types. ## 0.3.1 - 2015-06-28 ### Changed - Stabilizing enum serialization/deserialization. Now every enum is serialized as [int, [args...]]. - Suppressed some warnings appeared on updated compiler. ## 0.3.0 - 2015-06-25 ### Added - Enum serialization/deserialization. ## 0.2.2 - 2015-06-15 ### Changed - Minor integer decoding performance tweaking. ## 0.2.1 - 2015-05-30 ### Added - Benchmarking module. ### Changed - Increased string decoding performance by ~30 times. - Exported `read_value` function to the `rmp::decode` module. - Exported `Value` struct to the root crate namespace. ## 0.2.0 - 2015-05-27 ### Added - Introducing a `Value` algebraic data type, which represents an owning MessagePack object. It can be found in `rmp::value` module. - The Value ADT encoding and decoding functions. - Low-level ext type decoders. ## 0.1.1 - 2015-05-18 ### Changed - Added documentation and repository site in Cargo.toml. - Added keywords to ease searching using crates.io. ## 0.1.0 - 2015-05-15 ### Added - Initial commit. - This CHANGELOG file to hopefully serve as an evolving example of a standardized open source project CHANGELOG. rmp-0.8.11/Cargo.toml0000644000000022760000000000100077260ustar # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] edition = "2018" name = "rmp" version = "0.8.11" authors = ["Evgeny Safronov "] description = "Pure Rust MessagePack serialization implementation" documentation = "https://docs.rs/rmp" readme = "README.md" keywords = [ "msgpack", "MessagePack", ] categories = ["encoding"] license = "MIT" repository = "https://github.com/3Hren/msgpack-rust" [dependencies.byteorder] version = "1.4.2" default-features = false [dependencies.num-traits] version = "0.2.14" default-features = false [dependencies.paste] version = "1.0" [dev-dependencies.quickcheck] version = "1.0.2" [features] default = ["std"] std = [ "byteorder/std", "num-traits/std", ] [badges.maintenance] status = "passively-maintained" rmp-0.8.11/Cargo.toml.orig000064400000000000000000000013220072674642500134260ustar 00000000000000[package] name = "rmp" version = "0.8.11" authors = ["Evgeny Safronov "] license = "MIT" description = "Pure Rust MessagePack serialization implementation" repository = "https://github.com/3Hren/msgpack-rust" documentation = "https://docs.rs/rmp" readme = "README.md" keywords = ["msgpack", "MessagePack"] categories = ["encoding"] edition = "2018" [dependencies] byteorder = { version = "1.4.2", default-features = false } num-traits = { version = "0.2.14", default-features = false } # This is macro_only ;) paste = "1.0" [features] default = ["std"] std = ["byteorder/std", "num-traits/std"] [dev-dependencies] quickcheck = "1.0.2" [badges] maintenance = { status = "passively-maintained" } rmp-0.8.11/LICENSE000064400000000000000000000020600072674642500115440ustar 00000000000000MIT License Copyright (c) 2017 Evgeny Safronov Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. rmp-0.8.11/README.md000064400000000000000000000117220072674642500120230ustar 00000000000000## The Rust MessagePack Library RMP is a pure Rust [MessagePack](http://msgpack.org) implementation of an efficient binary serialization format. This crate provides low-level core functionality, writers and readers for primitive values with direct mapping between binary MessagePack format. **Warning** this library is still in rapid development and everything may change until 1.0 comes. ### Usage To use `rmp`, first add this to your `Cargo.toml`: ```toml [dependencies.rmp] rmp = "^0.8" ``` ### Features - **Convenient API** RMP is designed to be lightweight and straightforward. There are low-level API, which gives you full control on data encoding/decoding process and makes no heap allocations. On the other hand there are high-level API, which provides you convenient interface using Rust standard library and compiler reflection, allowing to encode/decode structures using `derive` attribute. - **Zero-copy value decoding** RMP allows to decode bytes from a buffer in a zero-copy manner easily and blazingly fast, while Rust static checks guarantees that the data will be valid until buffer lives. - **Clear error handling** RMP's error system guarantees that you never receive an error enum with unreachable variant. - **Robust and tested** This project is developed using TDD and CI, so any found bugs will be fixed without breaking existing functionality. ### Detailed This crate represents the very basic functionality needed to work with MessagePack format. Ideologically it is developed as a basis for building high-level abstractions. Currently there are two large modules: encode and decode. More detail you can find in the corresponding sections. Formally every MessagePack message consists of some marker encapsulating a data type and the data itself. Sometimes there are no separate data chunk, for example for booleans. In these cases a marker contains the value. For example, the `true` value is encoded as `0xc3`. ```rust let mut buf = Vec::new(); rmp::encode::write_bool(&mut buf, true).unwrap(); assert_eq!([0xc3], buf[..]); ``` Sometimes a single value can be encoded in multiple ways. For example a value of `42` can be represented as: `[0x2a], [0xcc, 0x2a], [0xcd, 0x00, 0x2a]` and so on, and all of them are considered as valid representations. To allow fine-grained control over encoding such values the library provides direct mapping functions. ```rust let mut bufs = vec![vec![]; 5]; rmp::encode::write_pfix(&mut bufs[0], 42).unwrap(); rmp::encode::write_u8(&mut bufs[1], 42).unwrap(); rmp::encode::write_u16(&mut bufs[2], 42).unwrap(); rmp::encode::write_u32(&mut bufs[3], 42).unwrap(); rmp::encode::write_u64(&mut bufs[4], 42).unwrap(); assert_eq!([0x2a], bufs[0][..]); assert_eq!([0xcc, 0x2a], bufs[1][..]); assert_eq!([0xcd, 0x00, 0x2a], bufs[2][..]); assert_eq!([0xce, 0x00, 0x00, 0x00, 0x2a], bufs[3][..]); assert_eq!([0xcf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2a], bufs[4][..]); ``` But they aren't planned to be widely used. Instead we often need to encode bytes compactly to save space. In these cases RMP provides functions that guarantee that for encoding the most compact representation will be chosen. ```rust let mut buf = Vec::new(); rmp::encode::write_sint(&mut buf, 300).unwrap(); assert_eq!([0xcd, 0x1, 0x2c], buf[..]); ``` On the other hand for deserialization it is not matter in which representation the value is encoded - RMP deals with all of them. Sometimes you know the exact type representation and want to enforce the deserialization process to make it strongly type safe. ```rust let buf = [0xcd, 0x1, 0x2c]; assert_eq!(300, rmp::decode::read_u16(&mut &buf[..]).unwrap()); ``` However if you try to decode such bytearray as other integer type, for example `u32`, there will be type mismatch error. ```rust let buf = [0xcd, 0x1, 0x2c]; rmp::decode::read_u32(&mut &buf[..]).err().unwrap(); ``` But sometimes all you want is just to encode an integer that *must* fit in the specified type no matter how it was encoded. RMP provides [`such`][read_int] function to ease integration with other MessagePack libraries. ```rust let buf = [0xcd, 0x1, 0x2c]; assert_eq!(300i16, rmp::decode::read_int(&mut &buf[..]).unwrap()); assert_eq!(300i32, rmp::decode::read_int(&mut &buf[..]).unwrap()); assert_eq!(300i64, rmp::decode::read_int(&mut &buf[..]).unwrap()); assert_eq!(300u16, rmp::decode::read_int(&mut &buf[..]).unwrap()); assert_eq!(300u32, rmp::decode::read_int(&mut &buf[..]).unwrap()); assert_eq!(300u64, rmp::decode::read_int(&mut &buf[..]).unwrap()); ``` ### API Almost all API are represented as pure functions, which accepts a generic `Write` or `Read` and the value to be encoded/decoded. For example let's do a round trip for π number. ```rust let pi = std::f64::consts::PI; let mut buf = Vec::new(); rmp::encode::write_f64(&mut buf, pi).unwrap(); assert_eq!([0xcb, 0x40, 0x9, 0x21, 0xfb, 0x54, 0x44, 0x2d, 0x18], buf[..]); assert_eq!(pi, rmp::decode::read_f64(&mut &buf[..]).unwrap()); ``` [read_int]: decode/fn.read_int.html License: MIT rmp-0.8.11/benches/bench.rs000064400000000000000000000017450072674642500136040ustar 00000000000000#![feature(test)] extern crate test; use test::Bencher; use rmp::decode::*; #[bench] fn from_i64_read_i64(b: &mut Bencher) { let buf = [0xd3, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]; b.iter(|| { let res = read_i64(&mut &buf[..]).unwrap(); test::black_box(res); }); } #[bench] fn from_i64_read_int(b: &mut Bencher) { let buf = [0xd3, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]; b.iter(|| { let res: i64 = read_int(&mut &buf[..]).unwrap(); test::black_box(res); }); } #[bench] fn from_string_read_str(b: &mut Bencher) { // Lorem ipsum dolor sit amet. let buf = [ 0xbb, 0x4c, 0x6f, 0x72, 0x65, 0x6d, 0x20, 0x69, 0x70, 0x73, 0x75, 0x6d, 0x20, 0x64, 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x73, 0x69, 0x74, 0x20, 0x61, 0x6d, 0x65, 0x74, 0x2e ]; let mut out = [0u8; 32]; b.iter(|| { let res = read_str(&mut &buf[..], &mut out[..]).unwrap(); test::black_box(res); }); } rmp-0.8.11/clippy.toml000064400000000000000000000000430072674642500127330ustar 00000000000000doc-valid-idents = ["MessagePack"] rmp-0.8.11/src/decode/bytes.rs000064400000000000000000000112360072674642500142520ustar 00000000000000//! Implementation of the [Bytes] type use core::fmt::{Display, Formatter}; use crate::decode::RmpReadErr; use super::RmpRead; /// Indicates that an error occurred reading from [Bytes] #[derive(Debug)] #[non_exhaustive] // NOTE: We can't use thiserror because of no_std :( pub enum BytesReadError { /// Indicates that there were not enough bytes. InsufficientBytes { expected: usize, actual: usize, position: u64 } } impl Display for BytesReadError { fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { match *self { BytesReadError::InsufficientBytes { expected, actual, position } => { write!(f, "Expected at least bytes {}, but only got {} (pos {})", expected, actual, position) } } } } #[cfg(feature = "std")] impl std::error::Error for BytesReadError {} impl RmpReadErr for BytesReadError {} /// A wrapper around `&[u8]` to read more efficiently. /// /// This has a specialized implementation of `RmpWrite` /// and has error type [Infallible](core::convert::Infallible). /// /// This has the additional benefit of working on `#[no_std]` (unlike the builtin Read trait) /// /// See also [serde_bytes::Bytes](https://docs.rs/serde_bytes/0.11/serde_bytes/struct.Bytes.html) /// /// Unlike a plain `&[u8]` this also tracks an internal offset in the input (See [Self::position]). /// /// This is used for (limited) compatibility with [std::io::Cursor]. Unlike a [Cursor](std::io::Cursor) it does /// not support mark/reset. #[derive(Debug, Copy, Clone, Default, Eq, PartialEq, Hash, Ord, PartialOrd)] pub struct Bytes<'a> { /// The internal position of the input buffer. /// /// This is not required for correctness. /// It is only used for error reporting (and to implement [Self::position]) current_position: u64, bytes: &'a [u8], } impl<'a> Bytes<'a> { /// Wrap an existing bytes slice. /// /// This sets the internal position to zero. #[inline] pub fn new(bytes: &'a [u8]) -> Self { Bytes { bytes, current_position: 0 } } /// Get a reference to the remaining bytes in the buffer. #[inline] pub fn remaining_slice(&self) -> &'a [u8] { self.bytes } /// Return the position of the input buffer. /// /// This is not required for correctness, it only exists to help mimic /// [Cursor::position](std::io::Cursor::position) #[inline] pub fn position(&self) -> u64 { self.current_position } } impl<'a> From<&'a [u8]> for Bytes<'a> { #[inline] fn from(bytes: &'a [u8]) -> Self { Bytes { bytes, current_position: 0 } } } impl RmpRead for Bytes<'_> { type Error = BytesReadError; #[inline] fn read_u8(&mut self) -> Result { if let Some((&first, newly_remaining)) = self.bytes.split_first() { self.bytes = newly_remaining; self.current_position += 1; Ok(first) } else { Err(BytesReadError::InsufficientBytes { expected: 1, actual: 0, position: self.current_position }) } } #[inline] fn read_exact_buf(&mut self, buf: &mut [u8]) -> Result<(), Self::Error> { let to_read = buf.len(); if to_read <= self.bytes.len() { let (src, newly_remaining) = self.bytes.split_at(to_read); self.bytes = newly_remaining; self.current_position += to_read as u64; buf.copy_from_slice(src); Ok(()) } else { Err(BytesReadError::InsufficientBytes { expected: to_read, actual: self.bytes.len(), position: self.current_position }) } } } #[cfg(not(feature = "std"))] impl<'a> RmpRead for &'a [u8] { type Error = BytesReadError; fn read_u8(&mut self) -> Result { if let Some((&first, newly_remaining)) = self.split_first() { *self = newly_remaining; Ok(first) } else { Err(BytesReadError::InsufficientBytes { expected: 1, actual: 0, position: 0 }) } } fn read_exact_buf(&mut self, buf: &mut [u8]) -> Result<(), Self::Error> { let to_read = buf.len(); if to_read <= self.len() { let (src, newly_remaining) = self.split_at(to_read); *self = newly_remaining; buf.copy_from_slice(src); Ok(()) } else { Err(BytesReadError::InsufficientBytes { expected: to_read, actual: self.len(), position: 0 }) } } }rmp-0.8.11/src/decode/dec.rs000064400000000000000000000033200072674642500136520ustar 00000000000000use super::{RmpRead, read_marker, ValueReadError}; use crate::Marker; /// Attempts to read exactly 5 bytes from the given reader and to decode them as `f32` value. /// /// The first byte should be the marker and the others should represent the data itself. /// /// # Errors /// /// This function will return `ValueReadError` on any I/O error while reading either the marker or /// the data. /// /// It also returns `ValueReadError::TypeMismatch` if the actual type is not equal with the /// expected one, indicating you with the actual type. /// /// # Note /// /// This function will silently retry on every EINTR received from the underlying `Read` until /// successful read. pub fn read_f32(rd: &mut R) -> Result> { match read_marker(rd)? { Marker::F32 => Ok(rd.read_data_f32()?), marker => Err(ValueReadError::TypeMismatch(marker)), } } /// Attempts to read exactly 9 bytes from the given reader and to decode them as `f64` value. /// /// The first byte should be the marker and the others should represent the data itself. /// /// # Errors /// /// This function will return `ValueReadError` on any I/O error while reading either the marker or /// the data. /// /// It also returns `ValueReadError::TypeMismatch` if the actual type is not equal with the /// expected one, indicating you with the actual type. /// /// # Note /// /// This function will silently retry on every EINTR received from the underlying `Read` until /// successful read. pub fn read_f64(rd: &mut R) -> Result> { match read_marker(rd)? { Marker::F64 => Ok(rd.read_data_f64()?), marker => Err(ValueReadError::TypeMismatch(marker)), } } rmp-0.8.11/src/decode/ext.rs000064400000000000000000000136610072674642500137300ustar 00000000000000use crate::Marker; use super::{read_marker, RmpRead, ValueReadError}; /// Attempts to read exactly 3 bytes from the given reader and interpret them as a fixext1 type /// with data attached. /// /// According to the MessagePack specification, a fixext1 stores an integer and a byte array whose /// length is 1 byte. Its marker byte is `0xd4`. /// /// Note, that this function copies a byte array from the reader to the output `u8` variable. /// /// # Errors /// /// This function will return `ValueReadError` on any I/O error while reading either the marker or /// the data. /// /// # Note /// /// This function will silently retry on every EINTR received from the underlying `Read` until /// successful read. pub fn read_fixext1(rd: &mut R) -> Result<(i8, u8), ValueReadError> { match read_marker(rd)? { Marker::FixExt1 => { let ty = rd.read_data_i8()?; let data = rd.read_data_u8()?; Ok((ty, data)) } marker => Err(ValueReadError::TypeMismatch(marker)), } } /// Attempts to read exactly 4 bytes from the given reader and interpret them as a fixext2 type /// with data attached. /// /// According to the MessagePack specification, a fixext2 stores an integer and a byte array whose /// length is 2 bytes. Its marker byte is `0xd5`. /// /// Note, that this function copies a byte array from the reader to the output buffer, which is /// unlikely if you want zero-copy functionality. /// /// # Errors /// /// This function will return `ValueReadError` on any I/O error while reading either the marker or /// the data. pub fn read_fixext2(rd: &mut R) -> Result<(i8, [u8; 2]), ValueReadError> { match read_marker(rd)? { Marker::FixExt2 => { let mut buf = [0; 2]; read_fixext_data(rd, &mut buf).map(|ty| (ty, buf)) } marker => Err(ValueReadError::TypeMismatch(marker)), } } /// Attempts to read exactly 6 bytes from the given reader and interpret them as a fixext4 type /// with data attached. /// /// According to the MessagePack specification, a fixext4 stores an integer and a byte array whose /// length is 4 bytes. Its marker byte is `0xd6`. /// /// Note, that this function copies a byte array from the reader to the output buffer, which is /// unlikely if you want zero-copy functionality. /// /// # Errors /// /// This function will return `ValueReadError` on any I/O error while reading either the marker or /// the data. pub fn read_fixext4(rd: &mut R) -> Result<(i8, [u8; 4]), ValueReadError> { match read_marker(rd)? { Marker::FixExt4 => { let mut buf = [0; 4]; read_fixext_data(rd, &mut buf).map(|ty| (ty, buf)) } marker => Err(ValueReadError::TypeMismatch(marker)), } } /// Attempts to read exactly 10 bytes from the given reader and interpret them as a fixext8 type /// with data attached. /// /// According to the MessagePack specification, a fixext8 stores an integer and a byte array whose /// length is 8 bytes. Its marker byte is `0xd7`. /// /// Note, that this function copies a byte array from the reader to the output buffer, which is /// unlikely if you want zero-copy functionality. /// /// # Errors /// /// This function will return `ValueReadError` on any I/O error while reading either the marker or /// the data. pub fn read_fixext8(rd: &mut R) -> Result<(i8, [u8; 8]), ValueReadError> { match read_marker(rd)? { Marker::FixExt8 => { let mut buf = [0; 8]; read_fixext_data(rd, &mut buf).map(|ty| (ty, buf)) } marker => Err(ValueReadError::TypeMismatch(marker)), } } /// Attempts to read exactly 18 bytes from the given reader and interpret them as a fixext16 type /// with data attached. /// /// According to the MessagePack specification, a fixext16 stores an integer and a byte array whose /// length is 16 bytes. Its marker byte is `0xd8`. /// /// Note, that this function copies a byte array from the reader to the output buffer, which is /// unlikely if you want zero-copy functionality. /// /// # Errors /// /// This function will return `ValueReadError` on any I/O error while reading either the marker or /// the data. pub fn read_fixext16(rd: &mut R) -> Result<(i8, [u8; 16]), ValueReadError> { match read_marker(rd)? { Marker::FixExt16 => { let mut buf = [0; 16]; read_fixext_data(rd, &mut buf).map(|ty| (ty, buf)) } marker => Err(ValueReadError::TypeMismatch(marker)), } } fn read_fixext_data(rd: &mut R, buf: &mut [u8]) -> Result> { let id = rd.read_data_i8()?; match rd.read_exact_buf(buf) { Ok(()) => Ok(id), Err(err) => Err(ValueReadError::InvalidDataRead(err)), } } /// Extension type meta information. /// /// Extension represents a tuple of type information and a byte array where type information is an /// integer whose meaning is defined by applications. /// /// Applications can assign 0 to 127 to store application-specific type information. /// /// # Note /// /// MessagePack reserves -1 to -128 for future extension to add predefined types which will be /// described in separated documents. #[derive(Debug, PartialEq)] pub struct ExtMeta { /// Type information. pub typeid: i8, /// Byte array size. pub size: u32, } pub fn read_ext_meta(rd: &mut R) -> Result> { let size = match read_marker(rd)? { Marker::FixExt1 => 1, Marker::FixExt2 => 2, Marker::FixExt4 => 4, Marker::FixExt8 => 8, Marker::FixExt16 => 16, Marker::Ext8 => rd.read_data_u8()? as u32, Marker::Ext16 => rd.read_data_u16()? as u32, Marker::Ext32 => rd.read_data_u32()?, marker => return Err(ValueReadError::TypeMismatch(marker)), }; let ty = rd.read_data_i8()?; let meta = ExtMeta { typeid: ty, size }; Ok(meta) } rmp-0.8.11/src/decode/mod.rs000064400000000000000000000403410072674642500137020ustar 00000000000000//! Provides various functions and structs for MessagePack decoding. //! //! Most of the function defined in this module will silently handle interruption error (EINTR) //! received from the given `Read` to be in consistent state with the `Write::write_all` method in //! the standard library. //! //! Any other error would immediately interrupt the parsing process. If your reader can results in //! I/O error and simultaneously be a recoverable state (for example, when reading from //! non-blocking socket and it returns EWOULDBLOCK) be sure that you buffer the data externally //! to avoid data loss (using `BufRead` readers with manual consuming or some other way). mod dec; mod ext; mod sint; mod str; mod uint; pub use self::dec::{read_f32, read_f64}; pub use self::ext::{ read_ext_meta, read_fixext1, read_fixext16, read_fixext2, read_fixext4, read_fixext8, ExtMeta, }; pub use self::sint::{read_i16, read_i32, read_i64, read_i8, read_nfix}; #[allow(deprecated)] // While we re-export deprecated items, we don't want to trigger warnings while compiling this crate pub use self::str::{read_str, read_str_from_slice, read_str_len, read_str_ref, DecodeStringError}; pub use self::uint::{read_pfix, read_u16, read_u32, read_u64, read_u8}; #[cfg(feature = "std")] use std::error; use core::fmt::{self, Display, Debug, Formatter}; use num_traits::cast::FromPrimitive; use crate::Marker; pub mod bytes; pub use bytes::Bytes; #[doc(inline)] #[allow(deprecated)] pub use crate::errors::Error; /// The error type for I/O operations on `RmpRead` and associated traits. /// /// For [std::io::Read], this is [std::io::Error] pub trait RmpReadErr: Display + Debug + crate::errors::MaybeErrBound + 'static {} #[cfg(feature = "std")] impl RmpReadErr for std::io::Error {} impl RmpReadErr for core::convert::Infallible {} macro_rules! read_byteorder_utils { ($($name:ident => $tp:ident),* $(,)?) => { $( #[inline] #[doc(hidden)] fn $name(&mut self) -> Result<$tp, ValueReadError> where Self: Sized { const SIZE: usize = core::mem::size_of::<$tp>(); let mut buf: [u8; SIZE] = [0u8; SIZE]; self.read_exact_buf(&mut buf).map_err(ValueReadError::InvalidDataRead)?; Ok(paste::paste! { ::[](&mut buf) }) } )* }; } mod sealed{ pub trait Sealed {} #[cfg(feature = "std")] impl Sealed for T {} #[cfg(not(feature = "std"))] impl<'a> Sealed for &'a [u8] {} impl Sealed for super::Bytes<'_> {} } /// A type that `rmp` supports reading from. /// /// The methods of this trait should be considered an implementation detail (for now). /// It is currently sealed (can not be implemented by the user). /// /// See also [std::io::Read] and [byteorder::ReadBytesExt] /// /// Its primary implementations are [std::io::Read] and [Bytes]. pub trait RmpRead: sealed::Sealed { type Error: RmpReadErr; /// Read a single (unsigned) byte from this stream #[inline] fn read_u8(&mut self) -> Result { let mut buf = [0; 1]; self.read_exact_buf(&mut buf)?; Ok(buf[0]) } /// Read the exact number of bytes needed to fill the specified buffer. /// /// If there are not enough bytes, this will return an error. /// /// See also [std::io::Read::read_exact] fn read_exact_buf(&mut self, buf: &mut [u8]) -> Result<(), Self::Error>; // Internal helper functions to map I/O error into the `InvalidDataRead` error. /// Read a single (unsigned) byte from this stream. #[inline] #[doc(hidden)] fn read_data_u8(&mut self) -> Result> { self.read_u8().map_err(ValueReadError::InvalidDataRead) } /// Read a single (signed) byte from this stream. #[inline] #[doc(hidden)] fn read_data_i8(&mut self) -> Result> { self.read_data_u8().map(|b| b as i8) } read_byteorder_utils!( read_data_u16 => u16, read_data_u32 => u32, read_data_u64 => u64, read_data_i16 => i16, read_data_i32 => i32, read_data_i64 => i64, read_data_f32 => f32, read_data_f64 => f64 ); } /* * HACK: rmpv & rmp-erde used the internal read_data_* functions. * * Since adding no_std support moved these functions to the RmpRead trait, * this broke compatiblity (despite changing no public APIs). * * In theory, we could update rmpv and rmp-serde to use the new APIS, * but that would be needless churn (and might surprise users who just want to update rmp proper). * * Instead, we emulate these internal APIs for now, * so that rmpv and rmp-serde continue to compile without issue. * * * TODO: Remove this hack once we release a new version of rmp proper */ macro_rules! wrap_data_funcs_for_compatibility { ($($tp:ident),* $(,)?) => { $(paste::paste! { #[cfg(feature = "std")] #[doc(hidden)] #[deprecated(note = "internal function. rmpv & rmp-serde need to switch to RmpRead")] pub fn [] (buf: &mut R) -> Result<$tp, ValueReadError> { buf.[]() } })* }; } wrap_data_funcs_for_compatibility!( u8, u16, u32, u64, i8, i16, i32, i64, f32, f64 ); #[cfg(feature = "std")] impl RmpRead for T { type Error = std::io::Error; #[inline] fn read_exact_buf(&mut self, buf: &mut [u8]) -> Result<(), Self::Error> { std::io::Read::read_exact(self, buf) } } // An error returned from the `write_marker` and `write_fixval` functions. struct MarkerWriteError(E); impl From for MarkerWriteError { #[cold] fn from(err: E) -> Self { MarkerWriteError(err) } } /// An error that can occur when attempting to read a MessagePack marker from the reader. #[derive(Debug)] #[allow(deprecated)] // Needed for backwards compat pub struct MarkerReadError(pub E); /// An error which can occur when attempting to read a MessagePack value from the reader. #[derive(Debug)] #[allow(deprecated)] // Needed for backwards compat pub enum ValueReadError { /// Failed to read the marker. InvalidMarkerRead(E), /// Failed to read the data. InvalidDataRead(E), /// The type decoded isn't match with the expected one. TypeMismatch(Marker), } #[cfg(feature = "std")] impl error::Error for ValueReadError { #[cold] fn source(&self) -> Option<&(dyn error::Error + 'static)> { match *self { ValueReadError::InvalidMarkerRead(ref err) | ValueReadError::InvalidDataRead(ref err) => Some(err), ValueReadError::TypeMismatch(..) => None, } } } impl Display for ValueReadError { #[cold] fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> { // TODO: This should probably use formatting f.write_str(match *self { ValueReadError::InvalidMarkerRead(..) => "failed to read MessagePack marker", ValueReadError::InvalidDataRead(..) => "failed to read MessagePack data", ValueReadError::TypeMismatch(..) => { "the type decoded isn't match with the expected one" } }) } } impl From> for ValueReadError { #[cold] fn from(err: MarkerReadError) -> ValueReadError { match err { MarkerReadError(err) => ValueReadError::InvalidMarkerRead(err), } } } impl From for MarkerReadError { #[cold] fn from(err: E) -> MarkerReadError { MarkerReadError(err) } } /// Attempts to read a single byte from the given reader and to decode it as a MessagePack marker. #[inline] pub fn read_marker(rd: &mut R) -> Result> { Ok(Marker::from_u8(rd.read_u8()?)) } /// Attempts to read a single byte from the given reader and to decode it as a nil value. /// /// According to the MessagePack specification, a nil value is represented as a single `0xc0` byte. /// /// # Errors /// /// This function will return `ValueReadError` on any I/O error while reading the nil marker, /// except the EINTR, which is handled internally. /// /// It also returns `ValueReadError::TypeMismatch` if the actual type is not equal with the /// expected one, indicating you with the actual type. /// /// # Note /// /// This function will silently retry on every EINTR received from the underlying `Read` until /// successful read. pub fn read_nil(rd: &mut R) -> Result<(), ValueReadError> { match read_marker(rd)? { Marker::Null => Ok(()), marker => Err(ValueReadError::TypeMismatch(marker)), } } /// Attempts to read a single byte from the given reader and to decode it as a boolean value. /// /// According to the MessagePack specification, an encoded boolean value is represented as a single /// byte. /// /// # Errors /// /// This function will return `ValueReadError` on any I/O error while reading the bool marker, /// except the EINTR, which is handled internally. /// /// It also returns `ValueReadError::TypeMismatch` if the actual type is not equal with the /// expected one, indicating you with the actual type. /// /// # Note /// /// This function will silently retry on every EINTR received from the underlying `Read` until /// successful read. pub fn read_bool(rd: &mut R) -> Result> { match read_marker(rd)? { Marker::True => Ok(true), Marker::False => Ok(false), marker => Err(ValueReadError::TypeMismatch(marker)), } } /// An error which can occur when attempting to read a MessagePack numeric value from the reader. #[derive(Debug)] #[allow(deprecated)] // Used for compatibility pub enum NumValueReadError { /// Failed to read the marker. InvalidMarkerRead(E), /// Failed to read the data. InvalidDataRead(E), /// The type decoded isn't match with the expected one. TypeMismatch(Marker), /// Out of range integral type conversion attempted. OutOfRange, } #[cfg(feature = "std")] impl error::Error for NumValueReadError { fn source(&self) -> Option<&(dyn error::Error + 'static)> { match *self { NumValueReadError::InvalidMarkerRead(ref err) | NumValueReadError::InvalidDataRead(ref err) => Some(err), NumValueReadError::TypeMismatch(..) | NumValueReadError::OutOfRange => None, } } } impl Display for NumValueReadError { fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> { f.write_str(match *self { NumValueReadError::InvalidMarkerRead(..) => "failed to read MessagePack marker", NumValueReadError::InvalidDataRead(..) => "failed to read MessagePack data", NumValueReadError::TypeMismatch(..) => { "the type decoded isn't match with the expected one" } NumValueReadError::OutOfRange => "out of range integral type conversion attempted", }) } } impl From> for NumValueReadError { #[cold] fn from(err: MarkerReadError) -> NumValueReadError { match err { MarkerReadError(err) => NumValueReadError::InvalidMarkerRead(err), } } } impl From> for NumValueReadError { #[cold] fn from(err: ValueReadError) -> NumValueReadError { match err { ValueReadError::InvalidMarkerRead(err) => NumValueReadError::InvalidMarkerRead(err), ValueReadError::InvalidDataRead(err) => NumValueReadError::InvalidDataRead(err), ValueReadError::TypeMismatch(err) => NumValueReadError::TypeMismatch(err), } } } /// Attempts to read up to 9 bytes from the given reader and to decode them as integral `T` value. /// /// This function will try to read up to 9 bytes from the reader (1 for marker and up to 8 for data) /// and interpret them as a big-endian `T`. /// /// Unlike `read_*`, this function weakens type restrictions, allowing you to safely decode packed /// values even if you aren't sure about the actual integral type. /// /// # Errors /// /// This function will return `NumValueReadError` on any I/O error while reading either the marker /// or the data. /// /// It also returns `NumValueReadError::OutOfRange` if the actual type is not an integer or it does /// not fit in the given numeric range. /// /// # Examples /// /// ``` /// let buf = [0xcd, 0x1, 0x2c]; /// /// assert_eq!(300u16, rmp::decode::read_int(&mut &buf[..]).unwrap()); /// assert_eq!(300i16, rmp::decode::read_int(&mut &buf[..]).unwrap()); /// assert_eq!(300u32, rmp::decode::read_int(&mut &buf[..]).unwrap()); /// assert_eq!(300i32, rmp::decode::read_int(&mut &buf[..]).unwrap()); /// assert_eq!(300u64, rmp::decode::read_int(&mut &buf[..]).unwrap()); /// assert_eq!(300i64, rmp::decode::read_int(&mut &buf[..]).unwrap()); /// assert_eq!(300usize, rmp::decode::read_int(&mut &buf[..]).unwrap()); /// assert_eq!(300isize, rmp::decode::read_int(&mut &buf[..]).unwrap()); /// ``` pub fn read_int(rd: &mut R) -> Result> { let val = match read_marker(rd)? { Marker::FixPos(val) => T::from_u8(val), Marker::FixNeg(val) => T::from_i8(val), Marker::U8 => T::from_u8(rd.read_data_u8()?), Marker::U16 => T::from_u16(rd.read_data_u16()?), Marker::U32 => T::from_u32(rd.read_data_u32()?), Marker::U64 => T::from_u64(rd.read_data_u64()?), Marker::I8 => T::from_i8(rd.read_data_i8()?), Marker::I16 => T::from_i16(rd.read_data_i16()?), Marker::I32 => T::from_i32(rd.read_data_i32()?), Marker::I64 => T::from_i64(rd.read_data_i64()?), marker => return Err(NumValueReadError::TypeMismatch(marker)), }; val.ok_or(NumValueReadError::OutOfRange) } /// Attempts to read up to 5 bytes from the given reader and to decode them as a big-endian u32 /// array size. /// /// Array format family stores a sequence of elements in 1, 3, or 5 bytes of extra bytes in addition /// to the elements. /// /// # Note /// /// This function will silently retry on every EINTR received from the underlying `Read` until /// successful read. // TODO: Docs. // NOTE: EINTR is managed internally. pub fn read_array_len(rd: &mut R) -> Result> where R: RmpRead, { match read_marker(rd)? { Marker::FixArray(size) => Ok(size as u32), Marker::Array16 => Ok(rd.read_data_u16()? as u32), Marker::Array32 => Ok(rd.read_data_u32()?), marker => Err(ValueReadError::TypeMismatch(marker)), } } /// Attempts to read up to 5 bytes from the given reader and to decode them as a big-endian u32 /// map size. /// /// Map format family stores a sequence of elements in 1, 3, or 5 bytes of extra bytes in addition /// to the elements. /// /// # Note /// /// This function will silently retry on every EINTR received from the underlying `Read` until /// successful read. // TODO: Docs. pub fn read_map_len(rd: &mut R) -> Result> { let marker = read_marker(rd)?; marker_to_len(rd, marker) } pub fn marker_to_len(rd: &mut R, marker: Marker) -> Result> { match marker { Marker::FixMap(size) => Ok(size as u32), Marker::Map16 => Ok(rd.read_data_u16()? as u32), Marker::Map32 => Ok(rd.read_data_u32()?), marker => Err(ValueReadError::TypeMismatch(marker)), } } /// Attempts to read up to 5 bytes from the given reader and to decode them as Binary array length. /// /// # Note /// /// This function will silently retry on every EINTR received from the underlying `Read` until /// successful read. // TODO: Docs. pub fn read_bin_len(rd: &mut R) -> Result> { match read_marker(rd)? { Marker::Bin8 => Ok(rd.read_data_u8()? as u32), Marker::Bin16 => Ok(rd.read_data_u16()? as u32), Marker::Bin32 => Ok(rd.read_data_u32()?), marker => Err(ValueReadError::TypeMismatch(marker)), } } rmp-0.8.11/src/decode/sint.rs000064400000000000000000000104220072674642500140750ustar 00000000000000use crate::Marker; use super::{read_marker, RmpRead, ValueReadError}; /// Attempts to read a single byte from the given reader and to decode it as a negative fixnum /// value. /// /// According to the MessagePack specification, a negative fixed integer value is represented using /// a single byte in `[0xe0; 0xff]` range inclusively, prepended with a special marker mask. /// /// # Errors /// /// This function will return `ValueReadError` on any I/O error while reading the marker, /// except the EINTR, which is handled internally. /// /// It also returns `ValueReadError::TypeMismatch` if the actual type is not equal with the /// expected one, indicating you with the actual type. /// /// # Note /// /// This function will silently retry on every EINTR received from the underlying `Read` until /// successful read. pub fn read_nfix(rd: &mut R) -> Result> { match read_marker(rd)? { Marker::FixNeg(val) => Ok(val), marker => Err(ValueReadError::TypeMismatch(marker)), } } /// Attempts to read exactly 2 bytes from the given reader and to decode them as `i8` value. /// /// The first byte should be the marker and the second one should represent the data itself. /// /// # Errors /// /// This function will return `ValueReadError` on any I/O error while reading either the marker or /// the data. /// /// It also returns `ValueReadError::TypeMismatch` if the actual type is not equal with the /// expected one, indicating you with the actual type. /// /// # Note /// /// This function will silently retry on every EINTR received from the underlying `Read` until /// successful read. pub fn read_i8(rd: &mut R) -> Result> { match read_marker(rd)? { Marker::I8 => rd.read_data_i8(), marker => Err(ValueReadError::TypeMismatch(marker)), } } /// Attempts to read exactly 3 bytes from the given reader and to decode them as `i16` value. /// /// The first byte should be the marker and the others should represent the data itself. /// /// # Errors /// /// This function will return `ValueReadError` on any I/O error while reading either the marker or /// the data. /// /// It also returns `ValueReadError::TypeMismatch` if the actual type is not equal with the /// expected one, indicating you with the actual type. /// /// # Note /// /// This function will silently retry on every EINTR received from the underlying `Read` until /// successful read. pub fn read_i16(rd: &mut R) -> Result> { match read_marker(rd)? { Marker::I16 => rd.read_data_i16(), marker => Err(ValueReadError::TypeMismatch(marker)), } } /// Attempts to read exactly 5 bytes from the given reader and to decode them as `i32` value. /// /// The first byte should be the marker and the others should represent the data itself. /// /// # Errors /// /// This function will return `ValueReadError` on any I/O error while reading either the marker or /// the data. /// /// It also returns `ValueReadError::TypeMismatch` if the actual type is not equal with the /// expected one, indicating you with the actual type. /// /// # Note /// /// This function will silently retry on every EINTR received from the underlying `Read` until /// successful read. pub fn read_i32(rd: &mut R) -> Result> { match read_marker(rd)? { Marker::I32 => rd.read_data_i32(), marker => Err(ValueReadError::TypeMismatch(marker)), } } /// Attempts to read exactly 9 bytes from the given reader and to decode them as `i64` value. /// /// The first byte should be the marker and the others should represent the data itself. /// /// # Errors /// /// This function will return `ValueReadError` on any I/O error while reading either the marker or /// the data. /// /// It also returns `ValueReadError::TypeMismatch` if the actual type is not equal with the /// expected one, indicating you with the actual type. /// /// # Note /// /// This function will silently retry on every EINTR received from the underlying `Read` until /// successful read. pub fn read_i64(rd: &mut R) -> Result> { match read_marker(rd)? { Marker::I64 => rd.read_data_i64(), marker => Err(ValueReadError::TypeMismatch(marker)), } } rmp-0.8.11/src/decode/str.rs000064400000000000000000000152330072674642500137350ustar 00000000000000#[cfg(feature = "std")] use std::error; use core::fmt::{self, Display, Formatter}; use core::str::{from_utf8, Utf8Error}; use super::{RmpRead, RmpReadErr, read_marker, ValueReadError}; use crate::Marker; #[derive(Debug)] #[allow(deprecated)] // Only for compatibility pub enum DecodeStringError<'a, E: RmpReadErr = super::Error> { InvalidMarkerRead(E), InvalidDataRead(E), TypeMismatch(Marker), /// The given buffer is not large enough to accumulate the specified amount of bytes. BufferSizeTooSmall(u32), InvalidUtf8(&'a [u8], Utf8Error), } #[cfg(feature = "std")] impl<'a, E: RmpReadErr> error::Error for DecodeStringError<'a, E> { #[cold] fn source(&self) -> Option<&(dyn error::Error + 'static)> { match *self { DecodeStringError::InvalidMarkerRead(ref err) | DecodeStringError::InvalidDataRead(ref err) => Some(err), DecodeStringError::TypeMismatch(..) | DecodeStringError::BufferSizeTooSmall(..) => None, DecodeStringError::InvalidUtf8(_, ref err) => Some(err), } } } impl<'a, E: RmpReadErr> Display for DecodeStringError<'a, E> { #[cold] fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> { f.write_str("error while decoding string") } } impl<'a, E: RmpReadErr> From> for DecodeStringError<'a, E> { #[cold] fn from(err: ValueReadError) -> DecodeStringError<'a, E> { match err { ValueReadError::InvalidMarkerRead(err) => DecodeStringError::InvalidMarkerRead(err), ValueReadError::InvalidDataRead(err) => DecodeStringError::InvalidDataRead(err), ValueReadError::TypeMismatch(marker) => DecodeStringError::TypeMismatch(marker), } } } /// Attempts to read up to 9 bytes from the given reader and to decode them as a string `u32` size /// value. /// /// According to the MessagePack specification, the string format family stores an byte array in 1, /// 2, 3, or 5 bytes of extra bytes in addition to the size of the byte array. /// /// # Errors /// /// This function will return `ValueReadError` on any I/O error while reading either the marker or /// the data. /// /// It also returns `ValueReadError::TypeMismatch` if the actual type is not equal with the /// expected one, indicating you with the actual type. #[inline] pub fn read_str_len(rd: &mut R) -> Result> { Ok(read_str_len_with_nread(rd)?.0) } fn read_str_len_with_nread(rd: &mut R) -> Result<(u32, usize), ValueReadError> where R: RmpRead { match read_marker(rd)? { Marker::FixStr(size) => Ok((size as u32, 1)), Marker::Str8 => Ok((rd.read_data_u8()? as u32, 2)), Marker::Str16 => Ok((rd.read_data_u16()? as u32, 3)), Marker::Str32 => Ok((rd.read_data_u32()?, 5)), marker => Err(ValueReadError::TypeMismatch(marker)), } } /// Attempts to read a string data from the given reader and copy it to the buffer provided. /// /// On success returns a borrowed string type, allowing to view the copied bytes as properly utf-8 /// string. /// According to the spec, the string's data must to be encoded using utf-8. /// /// # Errors /// /// Returns `Err` in the following cases: /// /// - if any IO error (including unexpected EOF) occurs, while reading an `rd`, except the EINTR, /// which is handled internally. /// - if the `out` buffer size is not large enough to keep all the data copied. /// - if the data is not utf-8, with a description as to why the provided data is not utf-8 and /// with a size of bytes actually copied to be able to get them from `out`. /// /// # Examples /// ``` /// use rmp::decode::read_str; /// /// let buf = [0xaa, 0x6c, 0x65, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65]; /// let mut out = [0u8; 16]; /// /// assert_eq!("le message", read_str(&mut &buf[..], &mut &mut out[..]).unwrap()); /// ``` /// /// # Unstable /// /// This function is **unstable**, because it needs review. // TODO: Stabilize. Mark error values for each error case (in docs). pub fn read_str<'r, R>(rd: &mut R, buf: &'r mut [u8]) -> Result<&'r str, DecodeStringError<'r, R::Error>> where R: RmpRead, { let len = read_str_len(rd)?; let ulen = len as usize; if buf.len() < ulen { return Err(DecodeStringError::BufferSizeTooSmall(len)); } read_str_data(rd, len, &mut buf[0..ulen]) } pub fn read_str_data<'r, R>(rd: &mut R, len: u32, buf: &'r mut [u8]) -> Result<&'r str, DecodeStringError<'r, R::Error>> where R: RmpRead { debug_assert_eq!(len as usize, buf.len()); // Trying to copy exact `len` bytes. match rd.read_exact_buf(buf) { Ok(()) => match from_utf8(buf) { Ok(decoded) => Ok(decoded), Err(err) => Err(DecodeStringError::InvalidUtf8(buf, err)), }, Err(err) => Err(DecodeStringError::InvalidDataRead(err)), } } /// Attempts to read and decode a string value from the reader, returning a borrowed slice from it. /// // TODO: Also it's possible to implement all borrowing functions for all `BufRead` implementors. #[deprecated(since = "0.8.6", note = "useless, use `read_str_from_slice` instead")] pub fn read_str_ref(rd: &[u8]) -> Result<&[u8], DecodeStringError<'_, super::bytes::BytesReadError>> { let mut cur = super::Bytes::new(rd); let len = read_str_len(&mut cur)?; Ok(&cur.remaining_slice()[..len as usize]) } /// Attempts to read and decode a string value from the reader, returning a borrowed slice from it. /// /// # Examples /// /// ``` /// use rmp::encode::write_str; /// use rmp::decode::read_str_from_slice; /// /// let mut buf = Vec::new(); /// write_str(&mut buf, "Unpacking").unwrap(); /// write_str(&mut buf, "multiple").unwrap(); /// write_str(&mut buf, "strings").unwrap(); /// /// let mut chunks = Vec::new(); /// let mut unparsed = &buf[..]; /// while let Ok((chunk, tail)) = read_str_from_slice(unparsed) { /// chunks.push(chunk); /// unparsed = tail; /// } /// /// assert_eq!(vec!["Unpacking", "multiple", "strings"], chunks); /// ``` pub fn read_str_from_slice>( buf: &T, ) -> Result<(&str, &[u8]), DecodeStringError<'_, super::bytes::BytesReadError>> { let buf = buf.as_ref(); let (len, nread) = read_str_len_with_nread(&mut super::Bytes::new(buf))?; let ulen = len as usize; if buf[nread..].len() >= ulen { let (head, tail) = buf.split_at(nread + ulen); match from_utf8(&head[nread..]) { Ok(val) => Ok((val, tail)), Err(err) => Err(DecodeStringError::InvalidUtf8(buf, err)), } } else { Err(DecodeStringError::BufferSizeTooSmall(len)) } } rmp-0.8.11/src/decode/uint.rs000064400000000000000000000102130072674642500140750ustar 00000000000000use crate::Marker; use super::{read_marker, RmpRead, ValueReadError}; /// Attempts to read a single byte from the given reader and to decode it as a positive fixnum /// value. /// /// According to the MessagePack specification, a positive fixed integer value is represented using /// a single byte in `[0x00; 0x7f]` range inclusively, prepended with a special marker mask. /// /// # Errors /// /// This function will return `ValueReadError` on any I/O error while reading the marker, /// except the EINTR, which is handled internally. /// /// It also returns `ValueReadError::TypeMismatch` if the actual type is not equal with the /// expected one, indicating you with the actual type. /// /// # Note /// /// This function will silently retry on every EINTR received from the underlying `Read` until /// successful read. pub fn read_pfix(rd: &mut R) -> Result> { match read_marker(rd)? { Marker::FixPos(val) => Ok(val), marker => Err(ValueReadError::TypeMismatch(marker)), } } /// Attempts to read exactly 2 bytes from the given reader and to decode them as `u8` value. /// /// The first byte should be the marker and the second one should represent the data itself. /// /// # Errors /// /// This function will return `ValueReadError` on any I/O error while reading either the marker or /// the data. /// /// It also returns `ValueReadError::TypeMismatch` if the actual type is not equal with the /// expected one, indicating you with the actual type. pub fn read_u8(rd: &mut R) -> Result> { match read_marker(rd)? { Marker::U8 => rd.read_data_u8(), marker => Err(ValueReadError::TypeMismatch(marker)), } } /// Attempts to read exactly 3 bytes from the given reader and to decode them as `u16` value. /// /// The first byte should be the marker and the others should represent the data itself. /// /// # Errors /// /// This function will return `ValueReadError` on any I/O error while reading either the marker or /// the data. /// /// It also returns `ValueReadError::TypeMismatch` if the actual type is not equal with the /// expected one, indicating you with the actual type. /// /// # Note /// /// This function will silently retry on every EINTR received from the underlying `Read` until /// successful read. pub fn read_u16(rd: &mut R) -> Result> { match read_marker(rd)? { Marker::U16 => rd.read_data_u16(), marker => Err(ValueReadError::TypeMismatch(marker)), } } /// Attempts to read exactly 5 bytes from the given reader and to decode them as `u32` value. /// /// The first byte should be the marker and the others should represent the data itself. /// /// # Errors /// /// This function will return `ValueReadError` on any I/O error while reading either the marker or /// the data. /// /// It also returns `ValueReadError::TypeMismatch` if the actual type is not equal with the /// expected one, indicating you with the actual type. /// /// # Note /// /// This function will silently retry on every EINTR received from the underlying `Read` until /// successful read. pub fn read_u32(rd: &mut R) -> Result> { match read_marker(rd)? { Marker::U32 => rd.read_data_u32(), marker => Err(ValueReadError::TypeMismatch(marker)), } } /// Attempts to read exactly 9 bytes from the given reader and to decode them as `u64` value. /// /// The first byte should be the marker and the others should represent the data itself. /// /// # Errors /// /// This function will return `ValueReadError` on any I/O error while reading either the marker or /// the data. /// /// It also returns `ValueReadError::TypeMismatch` if the actual type is not equal with the /// expected one, indicating you with the actual type. /// /// # Note /// /// This function will silently retry on every EINTR received from the underlying `Read` until /// successful read. pub fn read_u64(rd: &mut R) -> Result> { match read_marker(rd)? { Marker::U64 => rd.read_data_u64(), marker => Err(ValueReadError::TypeMismatch(marker)), } } rmp-0.8.11/src/encode/bin.rs000064400000000000000000000030120072674642500136770ustar 00000000000000use super::{RmpWrite}; use crate::encode::{write_marker, ValueWriteError}; use crate::Marker; /// Encodes and attempts to write the most efficient binary array length implementation to the given /// write, returning the marker used. /// /// This function is useful when you want to get full control for writing the data itself, for /// example, when using non-blocking socket. /// /// # Errors /// /// This function will return `ValueWriteError` on any I/O error occurred while writing either the /// marker or the data. pub fn write_bin_len(wr: &mut W, len: u32) -> Result> { if len < 256 { write_marker(&mut *wr, Marker::Bin8)?; wr.write_data_u8(len as u8)?; Ok(Marker::Bin8) } else if len <= u16::MAX as u32 { write_marker(&mut *wr, Marker::Bin16)?; wr.write_data_u16(len as u16)?; Ok(Marker::Bin16) } else { write_marker(&mut *wr, Marker::Bin32)?; wr.write_data_u32(len)?; Ok(Marker::Bin32) } } /// Encodes and attempts to write the most efficient binary implementation to the given `Write`. /// /// # Errors /// /// This function will return `ValueWriteError` on any I/O error occurred while writing either the /// marker or the data. // TODO: Docs, range check, example, visibility. pub fn write_bin(wr: &mut W, data: &[u8]) -> Result<(), ValueWriteError> { write_bin_len(wr, data.len() as u32)?; wr.write_bytes(data) .map_err(ValueWriteError::InvalidDataWrite) } rmp-0.8.11/src/encode/buffer.rs000064400000000000000000000121030072674642500144010ustar 00000000000000//! Implementation of the [ByteBuf] type use super::RmpWrite; #[cfg(not(feature = "std"))] use core::fmt::{self, Display, Formatter}; use alloc::vec::Vec; /// An error returned from writing to `&mut [u8]` (a byte buffer of fixed capacity) on no_std /// /// In feature="std", capacity overflow in `<&mut [u8] as std::io::Write>::write_exact()` /// currently returns [`ErrorKind::WriteZero`](https://doc.rust-lang.org/std/io/enum.ErrorKind.html#variant.WriteZero). /// /// Since no_std doesn't have std::io::Error we use this instead ;) /// /// This is specific to `#[cfg(not(feature = "std"))]` so it is `#[doc(hidden)]` #[derive(Debug)] #[cfg(not(feature = "std"))] #[doc(hidden)] pub struct FixedBufCapacityOverflow { _priv: () } /// An error returned from writing to `&mut [u8]` /// /// Aliased for compatibility with `no_std` mode. #[cfg(feature = "std")] #[doc(hidden)] pub type FixedBufCapacityOverflow = std::io::Error; #[cfg(not(feature = "std"))] impl Display for FixedBufCapacityOverflow { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { // This is intentionally vauge because std::io::Error is // Doesn't make sense for no_std to have bettetr errors than std f.write_str("Capacity overflow for fixed-size byte buffer") } } #[cfg(not(feature = "std"))] impl crate::encode::RmpWriteErr for FixedBufCapacityOverflow {} /// Fallback implementation for fixed-capacity buffers /// /// Only needed for no-std because we don't have /// the blanket impl for `std::io::Write` #[cfg(not(feature = "std"))] impl<'a> RmpWrite for &'a mut [u8] { type Error = FixedBufCapacityOverflow; #[inline] fn write_bytes(&mut self, buf: &[u8]) -> Result<(), Self::Error> { let to_write = buf.len(); let remaining = self.len(); if to_write <= remaining { self[..to_write].copy_from_slice(buf); unsafe { //Cant use split_at or re-borrowing due to lifetime errors :( *self = core::slice::from_raw_parts_mut( self.as_mut_ptr().add(to_write), remaining - to_write, ) } Ok(()) } else { Err(FixedBufCapacityOverflow { _priv: () }) } } } /// A wrapper around `Vec` to serialize more efficiently. /// /// This has a specialized implementation of `RmpWrite` /// It gives `std::convert::Infailable` for errors. /// This is because writing to `Vec` can only fail due to allocation. /// /// This has the additional benefit of working on `#[no_std]` /// /// See also [serde_bytes::ByteBuf](https://docs.rs/serde_bytes/0.11/serde_bytes/struct.ByteBuf.html) #[derive(Debug, Clone, Default, Eq, PartialEq, Hash, Ord, PartialOrd)] pub struct ByteBuf { bytes: Vec, } impl ByteBuf { /// Construct a new empty buffer #[inline] pub fn new() -> Self { ByteBuf { bytes: Vec::new() } } /// Construct a new buffer with the specified capacity /// /// See [Vec::with_capacity] for details #[inline] pub fn with_capacity(capacity: usize) -> Self { ByteBuf { bytes: Vec::with_capacity(capacity) } } /// Unwrap the underlying buffer of this vector #[inline] pub fn into_vec(self) -> Vec { self.bytes } /// Wrap the specified vector as a [ByteBuf] #[inline] pub fn from_vec(bytes: Vec) -> Self { ByteBuf { bytes } } /// Get a reference to this type as a [Vec] #[inline] pub fn as_vec(&self) -> &Vec { &self.bytes } /// Get a mutable reference to this type as a [Vec] #[inline] pub fn as_mut_vec(&mut self) -> &mut Vec { &mut self.bytes } /// Get a reference to this type as a slice of bytes (`&[u8]`) #[inline] pub fn as_slice(&self) -> &[u8] { &self.bytes } } impl AsRef<[u8]> for ByteBuf { fn as_ref(&self) -> &[u8] { &self.bytes } } impl AsRef> for ByteBuf { #[inline] fn as_ref(&self) -> &Vec { &self.bytes } } impl AsMut> for ByteBuf { #[inline] fn as_mut(&mut self) -> &mut Vec { &mut self.bytes } } impl From for Vec { #[inline] fn from(buf: ByteBuf) -> Self { buf.bytes } } impl From> for ByteBuf { #[inline] fn from(bytes: Vec) -> Self { ByteBuf { bytes } } } impl RmpWrite for ByteBuf { type Error = core::convert::Infallible; #[inline] fn write_u8(&mut self, val: u8) -> Result<(), Self::Error> { self.bytes.push(val); Ok(()) } #[inline] fn write_bytes(&mut self, buf: &[u8]) -> Result<(), Self::Error> { self.bytes.extend_from_slice(buf); Ok(()) } } #[cfg(not(feature = "std"))] impl<'a> RmpWrite for Vec { type Error = core::convert::Infallible; #[inline] fn write_u8(&mut self, val: u8) -> Result<(), Self::Error> { self.push(val); Ok(()) } #[inline] fn write_bytes(&mut self, buf: &[u8]) -> Result<(), Self::Error> { self.extend_from_slice(buf); Ok(()) } }rmp-0.8.11/src/encode/dec.rs000064400000000000000000000021160072674642500136660ustar 00000000000000use super::{RmpWrite, write_marker}; use crate::encode::ValueWriteError; use crate::Marker; /// Encodes and attempts to write an `f32` value as a 5-byte sequence into the given write. /// /// The first byte becomes the `f32` marker and the others will represent the data itself. /// /// # Errors /// /// This function will return `ValueWriteError` on any I/O error occurred while writing either the /// marker or the data. pub fn write_f32(wr: &mut W, val: f32) -> Result<(), ValueWriteError> { write_marker(wr, Marker::F32)?; wr.write_data_f32(val)?; Ok(()) } /// Encodes and attempts to write an `f64` value as a 9-byte sequence into the given write. /// /// The first byte becomes the `f64` marker and the others will represent the data itself. /// /// # Errors /// /// This function will return `ValueWriteError` on any I/O error occurred while writing either the /// marker or the data. pub fn write_f64(wr: &mut W, val: f64) -> Result<(), ValueWriteError> { write_marker(wr, Marker::F64)?; wr.write_data_f64(val)?; Ok(()) } rmp-0.8.11/src/encode/ext.rs000064400000000000000000000000010072674642500137220ustar 00000000000000 rmp-0.8.11/src/encode/map.rs000064400000000000000000000000010072674642500136770ustar 00000000000000 rmp-0.8.11/src/encode/mod.rs000064400000000000000000000244770072674642500137300ustar 00000000000000//! Provides various functions and structs for MessagePack encoding. mod bin; mod dec; mod ext; mod map; mod sint; mod str; mod uint; mod vec; pub use self::bin::{write_bin, write_bin_len}; pub use self::dec::{write_f32, write_f64}; pub use self::sint::{write_i16, write_i32, write_i64, write_i8, write_nfix, write_sint}; pub use self::str::{write_str, write_str_len}; pub use self::uint::{write_pfix, write_u16, write_u32, write_u64, write_u8, write_uint}; #[cfg(feature = "std")] use std::error; use core::fmt::{self, Display, Debug, Formatter}; use crate::Marker; pub mod buffer; pub use buffer::ByteBuf; #[doc(inline)] #[allow(deprecated)] pub use crate::errors::Error; /// The error type for operations on the [RmpWrite] trait. /// /// For [std::io::Write], this is [std::io::Error] /// For [ByteBuf], this is [core::convert::Infallible] pub trait RmpWriteErr: Display + Debug + crate::errors::MaybeErrBound + 'static {} #[cfg(feature = "std")] impl RmpWriteErr for std::io::Error {} impl RmpWriteErr for core::convert::Infallible {} // An error returned from the `write_marker` and `write_fixval` functions. struct MarkerWriteError(E); impl From for MarkerWriteError { #[cold] fn from(err: E) -> Self { MarkerWriteError(err) } } /// Attempts to write the given marker into the writer. fn write_marker(wr: &mut W, marker: Marker) -> Result<(), MarkerWriteError> { wr.write_u8(marker.to_u8()).map_err(MarkerWriteError) } /// An error returned from primitive values write functions. #[doc(hidden)] pub struct DataWriteError(E); impl From for DataWriteError { #[cold] #[inline] fn from(err: E) -> DataWriteError { DataWriteError(err) } } /// Encodes and attempts to write a nil value into the given write. /// /// According to the MessagePack specification, a nil value is represented as a single `0xc0` byte. /// /// # Errors /// /// This function will return `Error` on any I/O error occurred while writing the nil marker. /// /// # Examples /// /// ``` /// let mut buf = Vec::new(); /// /// rmp::encode::write_nil(&mut buf).unwrap(); /// /// assert_eq!(vec![0xc0], buf); /// ``` #[inline] pub fn write_nil(wr: &mut W) -> Result<(), W::Error> { write_marker(wr, Marker::Null).map_err(|e| e.0) } /// Encodes and attempts to write a bool value into the given write. /// /// According to the MessagePack specification, an encoded boolean value is represented as a single /// byte. /// /// # Errors /// /// Each call to this function may generate an I/O error indicating that the operation could not be /// completed. #[inline] pub fn write_bool(wr: &mut W, val: bool) -> Result<(), W::Error> { let marker = if val { Marker::True } else { Marker::False }; write_marker(wr, marker).map_err(|e| e.0) } mod sealed{ pub trait Sealed {} #[cfg(feature = "std")] impl Sealed for T {} #[cfg(not(feature = "std"))] impl Sealed for &mut [u8] {} #[cfg(not(feature = "std"))] impl Sealed for alloc::vec::Vec {} impl Sealed for super::ByteBuf {} } macro_rules! write_byteorder_utils { ($($name:ident => $tp:ident),* $(,)?) => { $( #[inline] #[doc(hidden)] fn $name(&mut self, val: $tp) -> Result<(), DataWriteError> where Self: Sized { const SIZE: usize = core::mem::size_of::<$tp>(); let mut buf: [u8; SIZE] = [0u8; SIZE]; paste::paste! { ::[](&mut buf, val); } self.write_bytes(&buf).map_err(DataWriteError) } )* }; } /// A type that `rmp` supports writing into. /// /// The methods of this trait should be considered an implementation detail (for now). /// It is currently sealed (can not be implemented by the user). /// /// See also [std::uo::Write] and [byteorder::WriteBytesExt] /// /// Its primary implementations are [std::io::Write] and [ByteBuf]. pub trait RmpWrite: sealed::Sealed { type Error: RmpWriteErr; /// Write a single byte to this stream #[inline] fn write_u8(&mut self, val: u8) -> Result<(), Self::Error> { let buf = [val]; self.write_bytes(&buf) } /// Write a slice of bytes to the underlying stream /// /// This will either write all the bytes or return an error. /// See also [std::io::Write::write_all] fn write_bytes(&mut self, buf: &[u8]) -> Result<(), Self::Error>; // Internal helper functions to map I/O error into the `DataWriteError` error. /// Write a single (signed) byte to this stream. #[inline] #[doc(hidden)] fn write_data_u8(&mut self, val: u8) -> Result<(), DataWriteError> { self.write_u8(val).map_err(DataWriteError) } /// Write a single (signed) byte to this stream. #[inline] #[doc(hidden)] fn write_data_i8(&mut self, val: i8) -> Result<(), DataWriteError> { self.write_data_u8(val as u8) } write_byteorder_utils!( write_data_u16 => u16, write_data_u32 => u32, write_data_u64 => u64, write_data_i16 => i16, write_data_i32 => i32, write_data_i64 => i64, write_data_f32 => f32, write_data_f64 => f64 ); } #[cfg(feature = "std")] impl RmpWrite for T { type Error = std::io::Error; #[inline] fn write_bytes(&mut self, buf: &[u8]) -> Result<(), Self::Error> { self.write_all(buf) } } /// An error that can occur when attempting to write multi-byte MessagePack value. #[derive(Debug)] #[allow(deprecated)] // TODO: Needed for compatibility pub enum ValueWriteError { /// I/O error while writing marker. InvalidMarkerWrite(E), /// I/O error while writing data. InvalidDataWrite(E), } impl From> for ValueWriteError { #[cold] fn from(err: MarkerWriteError) -> Self { match err { MarkerWriteError(err) => ValueWriteError::InvalidMarkerWrite(err), } } } impl From> for ValueWriteError { #[cold] fn from(err: DataWriteError) -> Self { match err { DataWriteError(err) => ValueWriteError::InvalidDataWrite(err), } } } #[cfg(feature = "std")] // Backwards compatbility ;) impl From> for std::io::Error { #[cold] fn from(err: ValueWriteError) -> std::io::Error { match err { ValueWriteError::InvalidMarkerWrite(err) | ValueWriteError::InvalidDataWrite(err) => err, } } } #[cfg(feature = "std")] impl error::Error for ValueWriteError { #[cold] fn source(&self) -> Option<&(dyn error::Error + 'static)> { match *self { ValueWriteError::InvalidMarkerWrite(ref err) | ValueWriteError::InvalidDataWrite(ref err) => Some(err), } } } impl Display for ValueWriteError { #[cold] fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> { f.write_str("error while writing multi-byte MessagePack value") } } /// Encodes and attempts to write the most efficient array length implementation to the given write, /// returning the marker used. /// /// # Errors /// /// This function will return `ValueWriteError` on any I/O error occurred while writing either the /// marker or the data. pub fn write_array_len(wr: &mut W, len: u32) -> Result> { let marker = if len < 16 { write_marker(wr, Marker::FixArray(len as u8))?; Marker::FixArray(len as u8) } else if len <= u16::MAX as u32 { write_marker(wr, Marker::Array16)?; wr.write_data_u16(len as u16)?; Marker::Array16 } else { write_marker(wr, Marker::Array32)?; wr.write_data_u32(len)?; Marker::Array32 }; Ok(marker) } /// Encodes and attempts to write the most efficient map length implementation to the given write, /// returning the marker used. /// /// # Errors /// /// This function will return `ValueWriteError` on any I/O error occurred while writing either the /// marker or the data. pub fn write_map_len(wr: &mut W, len: u32) -> Result> { let marker = if len < 16 { write_marker(wr, Marker::FixMap(len as u8))?; Marker::FixMap(len as u8) } else if len <= u16::MAX as u32 { write_marker(wr, Marker::Map16)?; wr.write_data_u16(len as u16)?; Marker::Map16 } else { write_marker(wr, Marker::Map32)?; wr.write_data_u32(len)?; Marker::Map32 }; Ok(marker) } /// Encodes and attempts to write the most efficient ext metadata implementation to the given /// write, returning the marker used. /// /// # Errors /// /// This function will return `ValueWriteError` on any I/O error occurred while writing either the /// marker or the data. /// /// # Panics /// /// Panics if `ty` is negative, because it is reserved for future MessagePack extension including /// 2-byte type information. pub fn write_ext_meta(wr: &mut W, len: u32, ty: i8) -> Result> { let marker = match len { 1 => { write_marker(wr, Marker::FixExt1)?; Marker::FixExt1 } 2 => { write_marker(wr, Marker::FixExt2)?; Marker::FixExt2 } 4 => { write_marker(wr, Marker::FixExt4)?; Marker::FixExt4 } 8 => { write_marker(wr, Marker::FixExt8)?; Marker::FixExt8 } 16 => { write_marker(wr, Marker::FixExt16)?; Marker::FixExt16 } len if len < 256 => { write_marker(wr, Marker::Ext8)?; wr.write_data_u8(len as u8)?; Marker::Ext8 } len if len < 65536 => { write_marker(wr, Marker::Ext16)?; wr.write_data_u16(len as u16)?; Marker::Ext16 } len => { write_marker(wr, Marker::Ext32)?; wr.write_data_u32(len)?; Marker::Ext32 } }; wr.write_data_i8(ty)?; Ok(marker) } rmp-0.8.11/src/encode/sint.rs000064400000000000000000000160270072674642500141160ustar 00000000000000use super::{write_marker, RmpWrite}; use crate::encode::{ write_pfix, write_u16, write_u32, write_u64, write_u8, ValueWriteError, }; use crate::Marker; /// Encodes and attempts to write a negative small integer value as a negative fixnum into the /// given write. /// /// According to the MessagePack specification, a negative fixed integer value is represented using /// a single byte in `[0xe0; 0xff]` range inclusively, prepended with a special marker mask. /// /// The function is **strict** with the input arguments - it is the user's responsibility to check /// if the value fits in the described range, otherwise it will panic. /// /// If you are not sure if the value fits in the given range use `write_sint` instead, which /// automatically selects the most compact integer representation. /// /// # Errors /// /// This function will return `FixedValueWriteError` on any I/O error occurred while writing the /// positive integer marker. /// /// # Panics /// /// Panics if `val` does not fit in `[-32; 0)` range. #[inline] #[track_caller] pub fn write_nfix(wr: &mut W, val: i8) -> Result<(), W::Error> { assert!(-32 <= val && val < 0); write_marker(wr, Marker::FixNeg(val)).map_err(|e| e.0)?; Ok(()) } /// Encodes and attempts to write an `i8` value as a 2-byte sequence into the given write. /// /// The first byte becomes the marker and the second one will represent the data itself. /// /// Note, that this function will encode the given value in 2-byte sequence no matter what, even if /// the value can be represented using single byte as a fixnum. Also note, that the first byte will /// always be the i8 marker (`0xd0`). /// /// If you need to fit the given buffer efficiently use `write_sint` instead, which automatically /// selects the appropriate integer representation. /// /// # Errors /// /// This function will return `ValueWriteError` on any I/O error occurred while writing either the /// marker or the data. /// /// # Examples /// /// ``` /// let mut buf = [0x00, 0x00]; /// /// rmp::encode::write_i8(&mut &mut buf[..], 42).ok().unwrap(); /// assert_eq!([0xd0, 0x2a], buf); /// /// // Note, that -18 can be represented simply as `[0xee]`, but the function emits 2-byte sequence. /// rmp::encode::write_i8(&mut &mut buf[..], -18).ok().unwrap(); /// assert_eq!([0xd0, 0xee], buf); /// ``` pub fn write_i8(wr: &mut W, val: i8) -> Result<(), ValueWriteError> { write_marker(wr, Marker::I8)?; wr.write_data_i8(val)?; Ok(()) } /// Encodes and attempts to write an `i16` value as a 3-byte sequence into the given write. /// /// The first byte becomes the marker and the others will represent the data itself. /// /// Note, that this function will encode the given value in 3-byte sequence no matter what, even if /// the value can be represented using single byte as a fixnum. Also note, that the first byte will /// always be the i16 marker (`0xd1`). /// /// If you need to fit the given buffer efficiently use `write_sint` instead, which automatically /// selects the appropriate integer representation. /// /// # Errors /// /// This function will return `ValueWriteError` on any I/O error occurred while writing either the /// marker or the data. pub fn write_i16(wr: &mut W, val: i16) -> Result<(), ValueWriteError> { write_marker(wr, Marker::I16)?; wr.write_data_i16(val)?; Ok(()) } /// Encodes and attempts to write an `i32` value as a 5-byte sequence into the given write. /// /// The first byte becomes the marker and the others will represent the data itself. /// /// Note, that this function will encode the given value in 5-byte sequence no matter what, even if /// the value can be represented using single byte as a fixnum. Also note, that the first byte will /// always be the i32 marker (`0xd2`). /// /// If you need to fit the given buffer efficiently use `write_sint` instead, which automatically /// selects the appropriate integer representation. /// /// # Errors /// /// This function will return `ValueWriteError` on any I/O error occurred while writing either the /// marker or the data. pub fn write_i32(wr: &mut W, val: i32) -> Result<(), ValueWriteError> { write_marker(wr, Marker::I32)?; wr.write_data_i32(val)?; Ok(()) } /// Encodes and attempts to write an `i64` value as a 9-byte sequence into the given write. /// /// The first byte becomes the marker and the others will represent the data itself. /// /// Note, that this function will encode the given value in 9-byte sequence no matter what, even if /// the value can be represented using single byte as a fixnum. Also note, that the first byte will /// always be the i16 marker (`0xd3`). /// /// If you need to fit the given buffer efficiently use `write_sint` instead, which automatically /// selects the appropriate integer representation. /// /// # Errors /// /// This function will return `ValueWriteError` on any I/O error occurred while writing either the /// marker or the data. pub fn write_i64(wr: &mut W, val: i64) -> Result<(), ValueWriteError> { write_marker(wr, Marker::I64)?; wr.write_data_i64(val)?; Ok(()) } /// Encodes and attempts to write an `i64` value into the given write using the most efficient /// representation, returning the marker used. /// /// This function obeys the MessagePack specification, which requires that the serializer SHOULD use /// the format which represents the data in the smallest number of bytes, with the exception of /// sized/unsized types. /// /// Note, that the function will **always** use signed integer representation even if the value can /// be more efficiently represented using unsigned integer encoding. /// /// The first byte becomes the marker and the others (if present, up to 9) will represent the data /// itself. /// /// # Errors /// /// This function will return `ValueWriteError` on any I/O error occurred while writing either the /// marker or the data. pub fn write_sint(wr: &mut W, val: i64) -> Result> { match val { val if -32 <= val && val < 0 => { write_nfix(wr, val as i8) .and(Ok(Marker::FixNeg(val as i8))) .map_err(ValueWriteError::InvalidMarkerWrite) } val if -128 <= val && val < -32 => write_i8(wr, val as i8).and(Ok(Marker::I8)), val if -32768 <= val && val < -128 => write_i16(wr, val as i16).and(Ok(Marker::I16)), val if -2147483648 <= val && val < -32768 => write_i32(wr, val as i32).and(Ok(Marker::I32)), val if val < -2147483648 => write_i64(wr, val).and(Ok(Marker::I64)), val if 0 <= val && val < 128 => { write_pfix(wr, val as u8) .and(Ok(Marker::FixPos(val as u8))) .map_err(ValueWriteError::InvalidMarkerWrite) } val if val < 256 => write_u8(wr, val as u8).and(Ok(Marker::U8)), val if val < 65536 => write_u16(wr, val as u16).and(Ok(Marker::U16)), val if val < 4294967296 => write_u32(wr, val as u32).and(Ok(Marker::U32)), val => write_u64(wr, val as u64).and(Ok(Marker::U64)), } } rmp-0.8.11/src/encode/str.rs000064400000000000000000000027410072674642500137470ustar 00000000000000use super::{RmpWrite, write_marker}; use crate::encode::ValueWriteError; use crate::Marker; /// Encodes and attempts to write the most efficient string length implementation to the given /// write, returning the marker used. /// /// # Errors /// /// This function will return `ValueWriteError` on any I/O error occurred while writing either the /// marker or the data. pub fn write_str_len(wr: &mut W, len: u32) -> Result> { if len < 32 { write_marker(wr, Marker::FixStr(len as u8))?; Ok(Marker::FixStr(len as u8)) } else if len < 256 { write_marker(wr, Marker::Str8)?; wr.write_data_u8(len as u8)?; Ok(Marker::Str8) } else if len <= u16::MAX as u32 { write_marker(wr, Marker::Str16)?; wr.write_data_u16(len as u16)?; Ok(Marker::Str16) } else { write_marker(wr, Marker::Str32)?; wr.write_data_u32(len)?; Ok(Marker::Str32) } } /// Encodes and attempts to write the most efficient string binary representation to the /// given `Write`. /// /// # Errors /// /// This function will return `ValueWriteError` on any I/O error occurred while writing either the /// marker or the data. // TODO: Docs, range check, example, visibility. pub fn write_str(wr: &mut W, data: &str) -> Result<(), ValueWriteError> { write_str_len(wr, data.len() as u32)?; wr.write_bytes(data.as_bytes()).map_err(ValueWriteError::InvalidDataWrite) } rmp-0.8.11/src/encode/uint.rs000064400000000000000000000136000072674642500141120ustar 00000000000000use super::{RmpWrite, write_marker}; use crate::encode::{ValueWriteError}; use crate::Marker; /// Encodes and attempts to write an unsigned small integer value as a positive fixint into the /// given write. /// /// According to the MessagePack specification, a positive fixed integer value is represented using /// a single byte in `[0x00; 0x7f]` range inclusively, prepended with a special marker mask. /// /// The function is **strict** with the input arguments - it is the user's responsibility to check /// if the value fits in the described range, otherwise it will panic. /// /// If you are not sure if the value fits in the given range use `write_uint` instead, which /// automatically selects the most compact integer representation. /// /// # Errors /// /// This function will return `FixedValueWriteError` on any I/O error occurred while writing the /// positive integer marker. /// /// # Panics /// /// Panics if `val` is greater than 127. #[inline] pub fn write_pfix(wr: &mut W, val: u8) -> Result<(), W::Error> { assert!(val < 128); write_marker(wr, Marker::FixPos(val)).map_err(|e| e.0)?; Ok(()) } /// Encodes and attempts to write an `u8` value as a 2-byte sequence into the given write. /// /// The first byte becomes the marker and the second one will represent the data itself. /// /// Note, that this function will encode the given value in 2-byte sequence no matter what, even if /// the value can be represented using single byte as a positive fixnum. /// /// If you need to fit the given buffer efficiently use `write_uint` instead, which automatically /// selects the appropriate integer representation. /// /// # Errors /// /// This function will return `ValueWriteError` on any I/O error occurred while writing either the /// marker or the data. /// /// # Examples /// ``` /// let mut buf = [0x00, 0x00]; /// /// rmp::encode::write_u8(&mut &mut buf[..], 146).ok().unwrap(); /// assert_eq!([0xcc, 0x92], buf); /// /// // Note, that 42 can be represented simply as `[0x2a]`, but the function emits 2-byte sequence. /// rmp::encode::write_u8(&mut &mut buf[..], 42).ok().unwrap(); /// assert_eq!([0xcc, 0x2a], buf); /// ``` pub fn write_u8(wr: &mut W, val: u8) -> Result<(), ValueWriteError> { write_marker(wr, Marker::U8)?; wr.write_data_u8(val)?; Ok(()) } /// Encodes and attempts to write an `u16` value strictly as a 3-byte sequence into the given write. /// /// The first byte becomes the marker and the others will represent the data itself. /// /// Note, that this function will encode the given value in 3-byte sequence no matter what, even if /// the value can be represented using single byte as a positive fixnum. /// /// If you need to fit the given buffer efficiently use `write_uint` instead, which automatically /// selects the appropriate integer representation. /// /// # Errors /// /// This function will return `ValueWriteError` on any I/O error occurred while writing either the /// marker or the data. pub fn write_u16(wr: &mut W, val: u16) -> Result<(), ValueWriteError> { write_marker(wr, Marker::U16)?; wr.write_data_u16(val)?; Ok(()) } /// Encodes and attempts to write an `u32` value strictly as a 5-byte sequence into the given write. /// /// The first byte becomes the marker and the others will represent the data itself. /// /// Note, that this function will encode the given value in 5-byte sequence no matter what, even if /// the value can be represented using single byte as a positive fixnum. /// /// If you need to fit the given buffer efficiently use `write_uint` instead, which automatically /// selects the appropriate integer representation. /// /// # Errors /// /// This function will return `ValueWriteError` on any I/O error occurred while writing either the /// marker or the data. pub fn write_u32(wr: &mut W, val: u32) -> Result<(), ValueWriteError> { write_marker(wr, Marker::U32)?; wr.write_data_u32(val)?; Ok(()) } /// Encodes and attempts to write an `u64` value strictly as a 9-byte sequence into the given write. /// /// The first byte becomes the marker and the others will represent the data itself. /// /// Note, that this function will encode the given value in 9-byte sequence no matter what, even if /// the value can be represented using single byte as a positive fixnum. /// /// If you need to fit the given buffer efficiently use `write_uint` instead, which automatically /// selects the appropriate integer representation. /// /// # Errors /// /// This function will return `ValueWriteError` on any I/O error occurred while writing either the /// marker or the data. pub fn write_u64(wr: &mut W, val: u64) -> Result<(), ValueWriteError> { write_marker(wr, Marker::U64)?; wr.write_data_u64(val)?; Ok(()) } /// Encodes and attempts to write an `u64` value into the given write using the most efficient /// representation, returning the marker used. /// /// This function obeys the MessagePack specification, which requires that the serializer SHOULD use /// the format which represents the data in the smallest number of bytes. /// /// The first byte becomes the marker and the others (if present, up to 9) will represent the data /// itself. /// /// # Errors /// /// This function will return `ValueWriteError` on any I/O error occurred while writing either the /// marker or the data. pub fn write_uint(wr: &mut W, val: u64) -> Result> { if val < 128 { write_pfix(wr, val as u8) .and(Ok(Marker::FixPos(val as u8))) .map_err(ValueWriteError::InvalidMarkerWrite) } else if val < 256 { write_u8(wr, val as u8).and(Ok(Marker::U8)) } else if val < 65536 { write_u16(wr, val as u16).and(Ok(Marker::U16)) } else if val < 4294967296 { write_u32(wr, val as u32).and(Ok(Marker::U32)) } else { write_u64(wr, val).and(Ok(Marker::U64)) } } rmp-0.8.11/src/encode/vec.rs000064400000000000000000000000010072674642500136770ustar 00000000000000 rmp-0.8.11/src/errors.rs000064400000000000000000000027210072674642500132140ustar 00000000000000//! Internal error handling code, shared between encoding and decoding. //! //! This is used mainly for backwards compatibility and abstraction over std/no_std. /// An alias to the "default" error handling type. /// /// This is problematic because when working on `#[no_std]`, because there is no [`std::error::Error`] trait and also no [`std::io::Error`] type. /// /// Furthermore, this doesn't abstract over the differences between different implementations of [`RmpRead`](crate::decode::RmpRead)/[`RmpWrite`](crate::encode::RmpWrite). /// /// When working directly with bytes streams, the error type is actually [Infallible](core::convert::Infallible). /// /// For these two reasons, this type is deprecated #[cfg(feature = "std")] #[deprecated(note = "Doesn't abstract over RmpRead/RmpWrite (or work on no_std), use RmpRead::Error/RmpWrite::Error and RmpReadErr/RmpWriteErr instead")] pub type Error = ::std::io::Error; #[cfg(not(feature = "std"))] #[deprecated(note = "Doesn't work meaningfully on no_std")] pub type Error = ::core::convert::Infallible; /// Internal type used to abstract over the [`std::error::Error`] trait /// /// This is a nop in no-std environments. #[cfg(feature = "std")] #[doc(hidden)] pub trait MaybeErrBound: std::error::Error {} #[cfg(feature = "std")] impl MaybeErrBound for T {} #[cfg(not(feature = "std"))] #[doc(hidden)] pub trait MaybeErrBound {} #[cfg(not(feature = "std"))] impl MaybeErrBound for T {}rmp-0.8.11/src/lib.rs000064400000000000000000000134570072674642500124560ustar 00000000000000//! # The Rust MessagePack Library //! //! RMP is a pure Rust [MessagePack](http://msgpack.org) implementation of an efficient binary //! serialization format. This crate provides low-level core functionality, writers and readers for //! primitive values with direct mapping between binary MessagePack format. //! //! **Warning** this library is still in rapid development and everything may change until 1.0 //! comes. //! //! ## Usage //! //! To use `rmp`, first add this to your `Cargo.toml`: //! //! ```toml //! [dependencies.rmp] //! rmp = "^0.8" //! ``` //! //! Then, add this line to your crate root: //! //! ```rust //! extern crate rmp; //! ``` //! //! ## Features //! //! - **Convenient API** //! //! RMP is designed to be lightweight and straightforward. There are low-level API, which gives you //! full control on data encoding/decoding process and makes no heap allocations. On the other hand //! there are high-level API, which provides you convenient interface using Rust standard library and //! compiler reflection, allowing to encode/decode structures using `derive` attribute. //! //! - **Zero-copy value decoding** //! //! RMP allows to decode bytes from a buffer in a zero-copy manner easily and blazingly fast, while Rust //! static checks guarantees that the data will be valid until buffer lives. //! //! - **Clear error handling** //! //! RMP's error system guarantees that you never receive an error enum with unreachable variant. //! //! - **Robust and tested** //! //! This project is developed using TDD and CI, so any found bugs will be fixed without breaking //! existing functionality. //! //! ## Detailed //! //! This crate represents the very basic functionality needed to work with MessagePack format. //! Ideologically it is developed as a basis for building high-level abstractions. //! //! Currently there are two large modules: encode and decode. More detail you can find in the //! corresponding sections. //! //! Formally every MessagePack message consists of some marker encapsulating a data type and the //! data itself. Sometimes there are no separate data chunk, for example for booleans. In these //! cases a marker contains the value. For example, the `true` value is encoded as `0xc3`. //! //! ``` //! let mut buf = Vec::new(); //! rmp::encode::write_bool(&mut buf, true).unwrap(); //! //! assert_eq!([0xc3], buf[..]); //! ``` //! //! Sometimes a single value can be encoded in multiple ways. For example a value of `42` can be //! represented as: `[0x2a], [0xcc, 0x2a], [0xcd, 0x00, 0x2a]` and so on, and all of them are //! considered as valid representations. To allow fine-grained control over encoding such values //! the library provides direct mapping functions. //! //! ``` //! let mut bufs = vec![vec![]; 5]; //! //! rmp::encode::write_pfix(&mut bufs[0], 42).unwrap(); //! rmp::encode::write_u8(&mut bufs[1], 42).unwrap(); //! rmp::encode::write_u16(&mut bufs[2], 42).unwrap(); //! rmp::encode::write_u32(&mut bufs[3], 42).unwrap(); //! rmp::encode::write_u64(&mut bufs[4], 42).unwrap(); //! //! assert_eq!([0x2a], bufs[0][..]); //! assert_eq!([0xcc, 0x2a], bufs[1][..]); //! assert_eq!([0xcd, 0x00, 0x2a], bufs[2][..]); //! assert_eq!([0xce, 0x00, 0x00, 0x00, 0x2a], bufs[3][..]); //! assert_eq!([0xcf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2a], bufs[4][..]); //! ``` //! //! But they aren't planned to be widely used. Instead we often need to encode bytes compactly to //! save space. In these cases RMP provides functions that guarantee that for encoding the most //! compact representation will be chosen. //! //! ``` //! let mut buf = Vec::new(); //! //! rmp::encode::write_sint(&mut buf, 300).unwrap(); //! //! assert_eq!([0xcd, 0x1, 0x2c], buf[..]); //! ``` //! //! On the other hand for deserialization it is not matter in which representation the value is //! encoded - RMP deals with all of them. //! //! Sometimes you know the exact type representation and want to enforce the deserialization process //! to make it strongly type safe. //! //! ``` //! let buf = [0xcd, 0x1, 0x2c]; //! //! assert_eq!(300, rmp::decode::read_u16(&mut &buf[..]).unwrap()); //! ``` //! //! However if you try to decode such bytearray as other integer type, for example `u32`, there will //! be type mismatch error. //! //! ``` //! let buf = [0xcd, 0x1, 0x2c]; //! rmp::decode::read_u32(&mut &buf[..]).err().unwrap(); //! ``` //! //! But sometimes all you want is just to encode an integer that *must* fit in the specified type //! no matter how it was encoded. RMP provides [`such`][read_int] function to ease integration with //! other MessagePack libraries. //! //! ``` //! let buf = [0xcd, 0x1, 0x2c]; //! //! assert_eq!(300i16, rmp::decode::read_int(&mut &buf[..]).unwrap()); //! assert_eq!(300i32, rmp::decode::read_int(&mut &buf[..]).unwrap()); //! assert_eq!(300i64, rmp::decode::read_int(&mut &buf[..]).unwrap()); //! assert_eq!(300u16, rmp::decode::read_int(&mut &buf[..]).unwrap()); //! assert_eq!(300u32, rmp::decode::read_int(&mut &buf[..]).unwrap()); //! assert_eq!(300u64, rmp::decode::read_int(&mut &buf[..]).unwrap()); //! ``` //! //! ## API //! //! Almost all API are represented as pure functions, which accepts a generic `Write` or `Read` and //! the value to be encoded/decoded. For example let's do a round trip for π number. //! //! ``` //! let pi = std::f64::consts::PI; //! let mut buf = Vec::new(); //! rmp::encode::write_f64(&mut buf, pi).unwrap(); //! //! assert_eq!([0xcb, 0x40, 0x9, 0x21, 0xfb, 0x54, 0x44, 0x2d, 0x18], buf[..]); //! assert_eq!(pi, rmp::decode::read_f64(&mut &buf[..]).unwrap()); //! ``` //! //! [read_int]: decode/fn.read_int.html #![cfg_attr(not(feature = "std"), no_std)] extern crate alloc; pub mod decode; pub mod encode; mod marker; mod errors; pub use crate::marker::Marker; /// Version of the MessagePack [spec](http://github.com/msgpack/msgpack/blob/master/spec.md). pub const MSGPACK_VERSION: u32 = 5; rmp-0.8.11/src/marker.rs000064400000000000000000000102100072674642500131510ustar 00000000000000const FIXSTR_SIZE : u8 = 0x1f; const FIXARRAY_SIZE : u8 = 0x0f; const FIXMAP_SIZE : u8 = 0x0f; /// Format markers. #[derive(Clone, Copy, Debug, PartialEq)] pub enum Marker { FixPos(u8), FixNeg(i8), Null, True, False, U8, U16, U32, U64, I8, I16, I32, I64, F32, F64, FixStr(u8), Str8, Str16, Str32, Bin8, Bin16, Bin32, FixArray(u8), Array16, Array32, FixMap(u8), Map16, Map32, FixExt1, FixExt2, FixExt4, FixExt8, FixExt16, Ext8, Ext16, Ext32, Reserved, } impl Marker { /// Construct a msgpack marker from a single byte. pub fn from_u8(n: u8) -> Marker { match n { 0x00 ..= 0x7f => Marker::FixPos(n), 0xe0 ..= 0xff => Marker::FixNeg(n as i8), 0x80 ..= 0x8f => Marker::FixMap(n & FIXMAP_SIZE), 0x90 ..= 0x9f => Marker::FixArray(n & FIXARRAY_SIZE), 0xa0 ..= 0xbf => Marker::FixStr(n & FIXSTR_SIZE), 0xc0 => Marker::Null, // Marked in MessagePack spec as never used. 0xc1 => Marker::Reserved, 0xc2 => Marker::False, 0xc3 => Marker::True, 0xc4 => Marker::Bin8, 0xc5 => Marker::Bin16, 0xc6 => Marker::Bin32, 0xc7 => Marker::Ext8, 0xc8 => Marker::Ext16, 0xc9 => Marker::Ext32, 0xca => Marker::F32, 0xcb => Marker::F64, 0xcc => Marker::U8, 0xcd => Marker::U16, 0xce => Marker::U32, 0xcf => Marker::U64, 0xd0 => Marker::I8, 0xd1 => Marker::I16, 0xd2 => Marker::I32, 0xd3 => Marker::I64, 0xd4 => Marker::FixExt1, 0xd5 => Marker::FixExt2, 0xd6 => Marker::FixExt4, 0xd7 => Marker::FixExt8, 0xd8 => Marker::FixExt16, 0xd9 => Marker::Str8, 0xda => Marker::Str16, 0xdb => Marker::Str32, 0xdc => Marker::Array16, 0xdd => Marker::Array32, 0xde => Marker::Map16, 0xdf => Marker::Map32, } } /// Converts a marker object into a single-byte representation. pub fn to_u8(&self) -> u8 { match *self { Marker::FixPos(val) => val, Marker::FixNeg(val) => val as u8, Marker::Null => 0xc0, Marker::True => 0xc3, Marker::False => 0xc2, Marker::U8 => 0xcc, Marker::U16 => 0xcd, Marker::U32 => 0xce, Marker::U64 => 0xcf, Marker::I8 => 0xd0, Marker::I16 => 0xd1, Marker::I32 => 0xd2, Marker::I64 => 0xd3, Marker::F32 => 0xca, Marker::F64 => 0xcb, Marker::FixStr(len) => 0xa0 | (len & FIXSTR_SIZE), Marker::Str8 => 0xd9, Marker::Str16 => 0xda, Marker::Str32 => 0xdb, Marker::Bin8 => 0xc4, Marker::Bin16 => 0xc5, Marker::Bin32 => 0xc6, Marker::FixArray(len) => 0x90 | (len & FIXARRAY_SIZE), Marker::Array16 => 0xdc, Marker::Array32 => 0xdd, Marker::FixMap(len) => 0x80 | (len & FIXMAP_SIZE), Marker::Map16 => 0xde, Marker::Map32 => 0xdf, Marker::FixExt1 => 0xd4, Marker::FixExt2 => 0xd5, Marker::FixExt4 => 0xd6, Marker::FixExt8 => 0xd7, Marker::FixExt16 => 0xd8, Marker::Ext8 => 0xc7, Marker::Ext16 => 0xc8, Marker::Ext32 => 0xc9, Marker::Reserved => 0xc1, } } } impl From for Marker { #[inline] fn from(val: u8) -> Marker { Marker::from_u8(val) } } impl Into for Marker { #[inline] fn into(self) -> u8 { self.to_u8() } } rmp-0.8.11/tests/func/decode/array.rs000064400000000000000000000042570072674642500155550ustar 00000000000000use super::Cursor; use crate::msgpack::decode::*; use crate::msgpack::Marker; #[test] fn from_empty_array_read_size() { let buf: &[u8] = &[0x90]; let mut cur = Cursor::new(buf); assert_eq!(0, read_array_len(&mut cur).unwrap()); assert_eq!(1, cur.position()); } #[test] fn from_fixarray_max_read_size() { let buf: &[u8] = &[ 0x9f, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e ]; let mut cur = Cursor::new(buf); assert_eq!(15, read_array_len(&mut cur).unwrap()); assert_eq!(1, cur.position()); } #[test] fn from_array16_min_read_size() { let buf: &[u8] = &[0xdc, 0x00, 0x10]; let mut cur = Cursor::new(buf); assert_eq!(16, read_array_len(&mut cur).unwrap()); assert_eq!(3, cur.position()); } #[test] fn from_array16_max_read_size() { let buf: &[u8] = &[0xdc, 0xff, 0xff]; let mut cur = Cursor::new(buf); assert_eq!(65535, read_array_len(&mut cur).unwrap()); assert_eq!(3, cur.position()); } #[test] fn from_array16_unexpected_eof_read_size() { let buf: &[u8] = &[0xdc, 0xff]; let mut cur = Cursor::new(buf); read_array_len(&mut cur).err().unwrap(); assert!(cur.position() >= 1); } #[test] fn from_array32_min_read_size() { let buf: &[u8] = &[0xdd, 0x00, 0x00, 0x00, 0x00]; let mut cur = Cursor::new(buf); assert_eq!(0, read_array_len(&mut cur).unwrap()); assert_eq!(5, cur.position()); } #[test] fn from_array32_max_read_size() { let buf: &[u8] = &[0xdd, 0xff, 0xff, 0xff, 0xff]; let mut cur = Cursor::new(buf); assert_eq!(4294967295, read_array_len(&mut cur).unwrap()); assert_eq!(5, cur.position()); } #[test] fn from_array32_unexpected_eof_read_size() { let buf: &[u8] = &[0xdd, 0xff, 0xff, 0xff]; let mut cur = Cursor::new(buf); read_array_len(&mut cur).err().unwrap(); assert!(cur.position() >= 1); } #[test] fn from_null_read_array_len() { let buf: &[u8] = &[0xc0]; let mut cur = Cursor::new(buf); match read_array_len(&mut cur) { Err(ValueReadError::TypeMismatch(Marker::Null)) => (), other => panic!("unexpected result: {:?}", other), } assert_eq!(1, cur.position()); } rmp-0.8.11/tests/func/decode/bin.rs000064400000000000000000000026040072674642500152010ustar 00000000000000use super::Cursor; use crate::msgpack::decode::*; use crate::msgpack::Marker; #[test] fn from_bin8_min_read_len() { let buf: &[u8] = &[0xc4, 0x00]; let mut cur = Cursor::new(buf); assert_eq!(0, read_bin_len(&mut cur).unwrap()); assert_eq!(2, cur.position()); } #[test] fn from_bin8_max_read_len() { let buf: &[u8] = &[0xc4, 0xff]; let mut cur = Cursor::new(buf); assert_eq!(255, read_bin_len(&mut cur).unwrap()); assert_eq!(2, cur.position()); } #[test] fn from_bin8_eof_read_len() { let buf: &[u8] = &[0xc4]; let mut cur = Cursor::new(buf); read_bin_len(&mut cur).err().unwrap(); assert_eq!(1, cur.position()); } #[test] fn from_null_read_len() { let buf: &[u8] = &[0xc0]; let mut cur = Cursor::new(buf); match read_bin_len(&mut cur) { Err(ValueReadError::TypeMismatch(Marker::Null)) => (), other => panic!("unexpected result: {:?}", other), } assert_eq!(1, cur.position()); } #[test] fn from_bin16_max_read_len() { let buf: &[u8] = &[0xc5, 0xff, 0xff]; let mut cur = Cursor::new(buf); assert_eq!(65535, read_bin_len(&mut cur).unwrap()); assert_eq!(3, cur.position()); } #[test] fn from_bin32_max_read_len() { let buf: &[u8] = &[0xc6, 0xff, 0xff, 0xff, 0xff]; let mut cur = Cursor::new(buf); assert_eq!(4294967295, read_bin_len(&mut cur).unwrap()); assert_eq!(5, cur.position()); } rmp-0.8.11/tests/func/decode/bool.rs000064400000000000000000000006340072674642500153650ustar 00000000000000use super::Cursor; use crate::msgpack::decode::*; #[test] fn from_bool_false() { let buf = [0xc2]; let mut cur = Cursor::new(&buf[..]); assert_eq!(false, read_bool(&mut cur).unwrap()); assert_eq!(1, cur.position()); } #[test] fn from_bool_true() { let buf = [0xc3]; let mut cur = Cursor::new(&buf[..]); assert!(read_bool(&mut cur).unwrap()); assert_eq!(1, cur.position()); } rmp-0.8.11/tests/func/decode/ext.rs000064400000000000000000000066170072674642500152410ustar 00000000000000use super::Cursor; use crate::msgpack::decode::*; #[test] fn from_fixext1_read_fixext1() { let buf: &[u8] = &[0xd4, 0x01, 0x02]; let mut cur = Cursor::new(buf); assert_eq!((1, 2), read_fixext1(&mut cur).unwrap()); assert_eq!(3, cur.position()); } #[test] fn from_fixext2_read_fixext2() { let buf = [0xd5, 0x01, 0x00, 0x02]; let mut cur = Cursor::new(&buf[..]); assert_eq!((1, [0x00, 0x02]), read_fixext2(&mut cur).unwrap()); assert_eq!(4, cur.position()); } #[test] fn from_fixext4_read_fixext4() { let buf = [0xd6, 0x01, 0x00, 0x00, 0x00, 0x02]; let mut cur = Cursor::new(&buf[..]); assert_eq!((1, [0x00, 0x00, 0x00, 0x02]), read_fixext4(&mut cur).unwrap()); assert_eq!(6, cur.position()); } #[test] fn from_fixext8_read_fixext8() { let buf = [0xd7, 0x01, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08]; let mut cur = Cursor::new(&buf[..]); assert_eq!((1, [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08]), read_fixext8(&mut cur).unwrap()); assert_eq!(10, cur.position()); } #[test] fn from_fixext16_read_fixext16() { let buf = [ 0xd8, 0x01, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 ]; let mut cur = Cursor::new(&buf[..]); assert_eq!((1, [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08]), read_fixext16(&mut cur).unwrap()); assert_eq!(18, cur.position()); } #[test] fn from_fixext1_read_ext_meta() { let buf: &[u8] = &[0xd4, 0x01]; let mut cur = Cursor::new(buf); assert_eq!(ExtMeta { typeid: 1, size: 1 }, read_ext_meta(&mut cur).unwrap()); assert_eq!(2, cur.position()); } #[test] fn from_fixext2_read_ext_meta() { let buf: &[u8] = &[0xd5, 0x01]; let mut cur = Cursor::new(buf); assert_eq!(ExtMeta { typeid: 1, size: 2 }, read_ext_meta(&mut cur).unwrap()); assert_eq!(2, cur.position()); } #[test] fn from_fixext4_read_ext_meta() { let buf: &[u8] = &[0xd6, 0x01]; let mut cur = Cursor::new(buf); assert_eq!(ExtMeta { typeid: 1, size: 4 }, read_ext_meta(&mut cur).unwrap()); assert_eq!(2, cur.position()); } #[test] fn from_fixext8_read_ext_meta() { let buf: &[u8] = &[0xd7, 0x01]; let mut cur = Cursor::new(buf); assert_eq!(ExtMeta { typeid: 1, size: 8 }, read_ext_meta(&mut cur).unwrap()); assert_eq!(2, cur.position()); } #[test] fn from_fixext16_read_ext_meta() { let buf: &[u8] = &[0xd8, 0x01]; let mut cur = Cursor::new(buf); assert_eq!(ExtMeta { typeid: 1, size: 16 }, read_ext_meta(&mut cur).unwrap()); assert_eq!(2, cur.position()); } #[test] fn from_ext8_read_ext_meta() { let buf: &[u8] = &[0xc7, 0xff, 0x01]; let mut cur = Cursor::new(buf); assert_eq!(ExtMeta { typeid: 1, size: 255 }, read_ext_meta(&mut cur).unwrap()); assert_eq!(3, cur.position()); } #[test] fn from_ext16_read_ext_meta() { let buf: &[u8] = &[0xc8, 0xff, 0xff, 0x01]; let mut cur = Cursor::new(buf); assert_eq!(ExtMeta { typeid: 1, size: 65535 }, read_ext_meta(&mut cur).unwrap()); assert_eq!(4, cur.position()); } #[test] fn from_ext32_read_ext_meta() { let buf: &[u8] = &[0xc9, 0xff, 0xff, 0xff, 0xff, 0x01]; let mut cur = Cursor::new(buf); assert_eq!(ExtMeta { typeid: 1, size: 4294967295 }, read_ext_meta(&mut cur).unwrap()); assert_eq!(6, cur.position()); } rmp-0.8.11/tests/func/decode/float.rs000064400000000000000000000050400072674642500155330ustar 00000000000000use super::Cursor; use crate::msgpack::decode::*; use crate::msgpack::Marker; #[test] fn from_f32_zero_plus() { let buf: &[u8] = &[0xca, 0x00, 0x00, 0x00, 0x00]; let mut cur = Cursor::new(buf); assert_eq!(0.0, read_f32(&mut cur).unwrap()); assert_eq!(5, cur.position()); } #[test] fn from_f32_max() { let buf: &[u8] = &[0xca, 0x7f, 0x7f, 0xff, 0xff]; let mut cur = Cursor::new(buf); assert_eq!(3.4028234e38_f32, read_f32(&mut cur).unwrap()); assert_eq!(5, cur.position()); } #[test] fn from_f32_inf() { use std::f32; let buf: &[u8] = &[0xca, 0x7f, 0x80, 0x00, 0x00]; let mut cur = Cursor::new(buf); assert_eq!(f32::INFINITY, read_f32(&mut cur).unwrap()); assert_eq!(5, cur.position()); } #[test] fn from_f32_neg_inf() { use std::f32; let buf: &[u8] = &[0xca, 0xff, 0x80, 0x00, 0x00]; let mut cur = Cursor::new(buf); assert_eq!(f32::NEG_INFINITY, read_f32(&mut cur).unwrap()); assert_eq!(5, cur.position()); } #[test] fn from_null_read_f32() { let buf: &[u8] = &[0xc0]; let mut cur = Cursor::new(buf); match read_f32(&mut cur) { Err(ValueReadError::TypeMismatch(Marker::Null)) => (), other => panic!("unexpected result: {:?}", other), } assert_eq!(1, cur.position()); } #[test] fn from_f64_zero_plus() { let buf: &[u8] = &[0xcb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; let mut cur = Cursor::new(buf); assert_eq!(0.0, read_f64(&mut cur).unwrap()); assert_eq!(9, cur.position()); } #[test] fn from_f64_zero_minus() { let buf: &[u8] = &[0xcb, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; let mut cur = Cursor::new(buf); assert_eq!(-0.0, read_f64(&mut cur).unwrap()); assert_eq!(9, cur.position()); } #[test] fn from_f64_inf() { use std::f64; let buf: &[u8] = &[0xcb, 0x7f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; let mut cur = Cursor::new(buf); assert_eq!(f64::INFINITY, read_f64(&mut cur).unwrap()); assert_eq!(9, cur.position()); } #[test] fn from_f64_neg_inf() { use std::f64; let buf: &[u8] = &[0xcb, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; let mut cur = Cursor::new(buf); assert_eq!(f64::NEG_INFINITY, read_f64(&mut cur).unwrap()); assert_eq!(9, cur.position()); } #[test] fn from_null_read_f64() { let buf: &[u8] = &[0xc0]; let mut cur = Cursor::new(buf); match read_f64(&mut cur) { Err(ValueReadError::TypeMismatch(Marker::Null)) => (), other => panic!("unexpected result: {:?}", other), } assert_eq!(1, cur.position()); } rmp-0.8.11/tests/func/decode/map.rs000064400000000000000000000026510072674642500152100ustar 00000000000000use super::Cursor; use crate::msgpack::decode::*; use crate::msgpack::Marker; #[test] fn from_fixmap_min_read_size() { let buf: &[u8] = &[0x80]; let mut cur = Cursor::new(buf); assert_eq!(0, read_map_len(&mut cur).unwrap()); assert_eq!(1, cur.position()); } #[test] fn from_fixmap_max_read_size() { let buf: &[u8] = &[0x8f]; let mut cur = Cursor::new(buf); assert_eq!(15, read_map_len(&mut cur).unwrap()); assert_eq!(1, cur.position()); } #[test] fn from_map16_min_read_size() { let buf: &[u8] = &[0xde, 0x00, 0x00]; let mut cur = Cursor::new(buf); assert_eq!(0, read_map_len(&mut cur).unwrap()); assert_eq!(3, cur.position()); } #[test] fn from_map16_max_read_size() { let buf: &[u8] = &[0xde, 0xff, 0xff]; let mut cur = Cursor::new(buf); assert_eq!(65535, read_map_len(&mut cur).unwrap()); assert_eq!(3, cur.position()); } #[test] fn from_map32_min_read_size() { let buf: &[u8] = &[0xdf, 0x00, 0x00, 0x00, 0x00]; let mut cur = Cursor::new(buf); assert_eq!(0, read_map_len(&mut cur).unwrap()); assert_eq!(5, cur.position()); } #[test] fn from_null_read_map_len() { let buf: &[u8] = &[0xc0, 0x00, 0x00, 0x00, 0x00]; let mut cur = Cursor::new(buf); match read_map_len(&mut cur) { Err(ValueReadError::TypeMismatch(Marker::Null)) => (), other => panic!("unexpected result: {:?}", other), } assert_eq!(1, cur.position()); } rmp-0.8.11/tests/func/decode/mod.rs000064400000000000000000000004040072674642500152040ustar 00000000000000mod array; mod bin; mod bool; mod ext; mod float; mod map; mod null; mod sint; mod string; mod uint; #[cfg(feature = "std")] pub type Cursor<'a> = std::io::Cursor<&'a [u8]>; #[cfg(not(feature = "std"))] pub type Cursor<'a> = crate::msgpack::decode::Bytes<'a>;rmp-0.8.11/tests/func/decode/null.rs000064400000000000000000000026600072674642500154050ustar 00000000000000use super::Cursor; use crate::msgpack::decode::*; #[test] fn pass() { let buf = [0xc0]; let mut cur = Cursor::new(&buf[..]); assert_eq!((), read_nil(&mut cur).unwrap()); assert_eq!(1, cur.position()); } #[test] fn fail_invalid_marker() { let buf = [0xc1]; let mut cur = Cursor::new(&buf[..]); match read_nil(&mut cur) { Err(ValueReadError::TypeMismatch(..)) => (), other => panic!("unexpected result: {:?}", other), } assert_eq!(1, cur.position()); } #[test] fn fail_unexpected_eof() { let buf = []; let mut cur = Cursor::new(&buf[..]); read_nil(&mut cur).err().unwrap(); assert_eq!(0, cur.position()); } #[test] #[cfg(feature = "std")] fn interrupt_safe() { use std::io::{Error, ErrorKind, Read}; struct MockRead { state_: u8 } impl MockRead { fn state(&self) -> u8 { self.state_ } } impl Read for MockRead { fn read(&mut self, buf: &mut [u8]) -> Result { if self.state_ == 0 { self.state_ = 1; Err(Error::new(ErrorKind::Interrupted, "interrupted")) } else { assert!(!buf.is_empty()); buf[0] = 0xc0; Ok(1) } } } let mut cur = MockRead { state_: 0 }; // The function is interruption-safe, the first read should succeed. read_nil(&mut cur).unwrap(); assert_eq!(1, cur.state()); } rmp-0.8.11/tests/func/decode/sint.rs000064400000000000000000000147470072674642500154210ustar 00000000000000use super::Cursor; use crate::msgpack::decode::*; use crate::msgpack::Marker; #[test] fn from_nfix_min() { let buf = [0xe0]; let mut cur = Cursor::new(&buf[..]); assert_eq!(-32, read_nfix(&mut cur).unwrap()); assert_eq!(1, cur.position()); } #[test] fn from_nfix_max() { let buf = [0xff]; let mut cur = Cursor::new(&buf[..]); assert_eq!(-1, read_nfix(&mut cur).unwrap()); assert_eq!(1, cur.position()); } #[test] fn from_nfix_type_mismatch() { let buf = &[0xc0]; let mut cur = Cursor::new(&buf[..]); match read_nfix(&mut cur) { Err(ValueReadError::TypeMismatch(..)) => (), other => panic!("unexpected result: {:?}", other), } assert_eq!(1, cur.position()); } #[test] fn from_i8_min() { let buf = [0xd0, 0x80]; let mut cur = Cursor::new(&buf[..]); assert_eq!(-128, read_i8(&mut cur).unwrap()); assert_eq!(2, cur.position()); } #[test] fn from_i8_max() { let buf = [0xd0, 0x7f]; let mut cur = Cursor::new(&buf[..]); assert_eq!(127, read_i8(&mut cur).unwrap()); assert_eq!(2, cur.position()); } #[test] fn from_i8_type_mismatch() { let buf = [0xc0, 0x80]; let mut cur = Cursor::new(&buf[..]); match read_i8(&mut cur) { Err(ValueReadError::TypeMismatch(Marker::Null)) => (), other => panic!("unexpected result: {:?}", other), } assert_eq!(1, cur.position()); } #[test] fn from_i8_unexpected_eof() { let buf = [0xd0]; let mut cur = Cursor::new(&buf[..]); read_i8(&mut cur).err().unwrap(); assert_eq!(1, cur.position()); } #[test] fn from_i16_min() { let buf = [0xd1, 0x80, 0x00]; let mut cur = Cursor::new(&buf[..]); assert_eq!(-32768, read_i16(&mut cur).unwrap()); assert_eq!(3, cur.position()); } #[test] fn from_i16_max() { let buf = [0xd1, 0x7f, 0xff]; let mut cur = Cursor::new(&buf[..]); assert_eq!(32767, read_i16(&mut cur).unwrap()); assert_eq!(3, cur.position()); } #[test] fn from_i16_type_mismatch() { let buf = [0xc0, 0x80, 0x00]; let mut cur = Cursor::new(&buf[..]); match read_i16(&mut cur) { Err(ValueReadError::TypeMismatch(Marker::Null)) => (), other => panic!("unexpected result: {:?}", other), } assert_eq!(1, cur.position()); } #[test] fn from_i16_unexpected_eof() { let buf = [0xd1, 0x7f]; let mut cur = Cursor::new(&buf[..]); read_i16(&mut cur).err().unwrap(); assert!(cur.position() >= 1); } #[test] fn from_i32_min() { let buf = [0xd2, 0x80, 0x00, 0x00, 0x00]; let mut cur = Cursor::new(&buf[..]); assert_eq!(-2147483648, read_i32(&mut cur).unwrap()); assert_eq!(5, cur.position()); } #[test] fn from_i32_max() { let buf = &[0xd2, 0x7f, 0xff, 0xff, 0xff]; let mut cur = Cursor::new(&buf[..]); assert_eq!(2147483647, read_i32(&mut cur).unwrap()); assert_eq!(5, cur.position()); } #[test] fn from_i32_type_mismatch() { let buf = &[0xc0, 0x80, 0x00, 0x00, 0x00]; let mut cur = Cursor::new(&buf[..]); match read_i32(&mut cur) { Err(ValueReadError::TypeMismatch(Marker::Null)) => (), other => panic!("unexpected result: {:?}", other), } assert_eq!(1, cur.position()); } #[test] fn from_i32_unexpected_eof() { let buf = &[0xd2, 0x7f, 0xff, 0xff]; let mut cur = Cursor::new(&buf[..]); read_i32(&mut cur).err().unwrap(); assert!(cur.position() >= 1); } #[test] fn from_i64_min() { let buf = [0xd3, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; let mut cur = Cursor::new(&buf[..]); assert_eq!(-9223372036854775808, read_i64(&mut cur).unwrap()); assert_eq!(9, cur.position()); } #[test] fn from_i64_max() { let buf = [0xd3, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]; let mut cur = Cursor::new(&buf[..]); assert_eq!(9223372036854775807, read_i64(&mut cur).unwrap()); assert_eq!(9, cur.position()); } #[test] fn from_i64_type_mismatch() { let buf = [0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; let mut cur = Cursor::new(&buf[..]); match read_i64(&mut cur) { Err(ValueReadError::TypeMismatch(Marker::Null)) => (), other => panic!("unexpected result: {:?}", other), } assert_eq!(1, cur.position()); } #[test] fn from_i64_unexpected_eof() { let buf = [0xd3, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]; let mut cur = Cursor::new(&buf[..]); read_i64(&mut cur).err().unwrap(); assert!(cur.position() >= 1); } #[test] fn from_nfix_min_read_int() { let buf: &[u8] = &[0xe0]; let mut cur = Cursor::new(buf); assert_eq!(-32, read_int(&mut cur).unwrap()); assert_eq!(1, cur.position()); } #[test] fn from_nfix_max_read_int() { let buf: &[u8] = &[0xff]; let mut cur = Cursor::new(buf); assert_eq!(-1, read_int(&mut cur).unwrap()); assert_eq!(1, cur.position()); } #[test] fn from_i8_min_read_int() { let buf: &[u8] = &[0xd0, 0x80]; let mut cur = Cursor::new(buf); assert_eq!(-128, read_int(&mut cur).unwrap()); assert_eq!(2, cur.position()); } #[test] fn from_i8_max_read_int() { let buf: &[u8] = &[0xd0, 0x7f]; let mut cur = Cursor::new(buf); assert_eq!(127, read_int(&mut cur).unwrap()); assert_eq!(2, cur.position()); } #[test] fn from_i16_min_read_int() { let buf: &[u8] = &[0xd1, 0x80, 0x00]; let mut cur = Cursor::new(buf); assert_eq!(-32768, read_int(&mut cur).unwrap()); assert_eq!(3, cur.position()); } #[test] fn from_i16_max_read_int() { let buf: &[u8] = &[0xd1, 0x7f, 0xff]; let mut cur = Cursor::new(buf); assert_eq!(32767, read_int(&mut cur).unwrap()); assert_eq!(3, cur.position()); } #[test] fn from_i32_min_read_int() { let buf: &[u8] = &[0xd2, 0x80, 0x00, 0x00, 0x00]; let mut cur = Cursor::new(buf); assert_eq!(-2147483648, read_int(&mut cur).unwrap()); assert_eq!(5, cur.position()); } #[test] fn from_i32_max_read_int() { let buf: &[u8] = &[0xd2, 0x7f, 0xff, 0xff, 0xff]; let mut cur = Cursor::new(buf); assert_eq!(2147483647, read_int(&mut cur).unwrap()); assert_eq!(5, cur.position()); } #[test] fn from_i64_min_read_int() { let buf: &[u8] = &[0xd3, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; let mut cur = Cursor::new(buf); assert_eq!(-9223372036854775808i64, read_int(&mut cur).unwrap()); assert_eq!(9, cur.position()); } #[test] fn from_i64_max_read_int() { let buf: &[u8] = &[0xd3, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]; let mut cur = Cursor::new(buf); assert_eq!(9223372036854775807i64, read_int(&mut cur).unwrap()); assert_eq!(9, cur.position()); } rmp-0.8.11/tests/func/decode/string.rs000064400000000000000000000142140072674642500157370ustar 00000000000000use super::Cursor; use crate::msgpack::decode::*; use crate::msgpack::Marker; #[test] fn from_fixstr_min_read_str_len() { let buf: &[u8] = &[0xa0]; let mut cur = Cursor::new(buf); assert_eq!(0, read_str_len(&mut cur).unwrap()); assert_eq!(1, cur.position()); } #[test] fn from_fixstr_rnd_read_str_len() { let buf: &[u8] = &[0xaa]; let mut cur = Cursor::new(buf); assert_eq!(10, read_str_len(&mut cur).unwrap()); assert_eq!(1, cur.position()); } #[test] fn from_fixstr_max_read_str_len() { let buf: &[u8] = &[0xbf]; let mut cur = Cursor::new(buf); assert_eq!(31, read_str_len(&mut cur).unwrap()); assert_eq!(1, cur.position()); } #[test] fn from_str8_min_read_str_len() { let buf: &[u8] = &[0xd9, 0x00]; let mut cur = Cursor::new(buf); assert_eq!(0, read_str_len(&mut cur).unwrap()); assert_eq!(2, cur.position()); } #[test] fn from_str8_rnd_read_str_len() { let buf: &[u8] = &[0xd9, 0x0a]; let mut cur = Cursor::new(buf); assert_eq!(10, read_str_len(&mut cur).unwrap()); assert_eq!(2, cur.position()); } #[test] fn from_str8_read_str_len_eof() { let buf: &[u8] = &[0xd9]; let mut cur = Cursor::new(buf); read_str_len(&mut cur).err().unwrap(); assert_eq!(1, cur.position()); } #[test] fn from_str8_max_read_str_len() { let buf: &[u8] = &[0xd9, 0xff]; let mut cur = Cursor::new(buf); assert_eq!(255, read_str_len(&mut cur).unwrap()); assert_eq!(2, cur.position()); } #[test] fn from_str16_min_read_str_len() { let buf: &[u8] = &[0xda, 0x00, 0x00]; let mut cur = Cursor::new(buf); assert_eq!(0, read_str_len(&mut cur).unwrap()); assert_eq!(3, cur.position()); } #[test] fn from_str16_max_read_str_len() { let buf: &[u8] = &[0xda, 0xff, 0xff]; let mut cur = Cursor::new(buf); assert_eq!(65535, read_str_len(&mut cur).unwrap()); assert_eq!(3, cur.position()); } #[test] fn from_str16_read_str_len_eof() { let buf: &[u8] = &[0xda, 0x00]; let mut cur = Cursor::new(buf); read_str_len(&mut cur).err().unwrap(); assert!(cur.position() >= 1); } #[test] fn from_str32_min_read_str_len() { let buf: &[u8] = &[0xdb, 0x00, 0x00, 0x00, 0x00]; let mut cur = Cursor::new(buf); assert_eq!(0, read_str_len(&mut cur).unwrap()); assert_eq!(5, cur.position()); } #[test] fn from_str32_max_read_str_len() { let buf: &[u8] = &[0xdb, 0xff, 0xff, 0xff, 0xff]; let mut cur = Cursor::new(buf); assert_eq!(4294967295, read_str_len(&mut cur).unwrap()); assert_eq!(5, cur.position()); } #[test] fn from_str32_read_str_len_eof() { let buf: &[u8] = &[0xdb, 0x00, 0x00, 0x00]; let mut cur = Cursor::new(buf); read_str_len(&mut cur).err().unwrap(); assert!(cur.position() >= 1); } #[test] fn from_null_read_str_len() { let buf: &[u8] = &[0xc0]; let mut cur = Cursor::new(buf); match read_str_len(&mut cur) { Err(ValueReadError::TypeMismatch(Marker::Null)) => (), other => panic!("unexpected result: {:?}", other), } assert_eq!(1, cur.position()); } #[test] fn from_str_strfix() { let buf: &[u8] = &[0xaa, 0x6c, 0x65, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65]; let mut cur = Cursor::new(buf); let out: &mut [u8] = &mut [0u8; 16]; assert_eq!("le message", read_str(&mut cur, out).unwrap()); assert_eq!(11, cur.position()); } #[test] fn from_str_strfix_extra_data() { let buf: &[u8] = &[0xaa, 0x6c, 0x65, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x00]; let mut cur = Cursor::new(buf); let out: &mut [u8] = &mut [0u8; 16]; assert_eq!("le message", read_str(&mut cur, out).unwrap()); assert_eq!(11, cur.position()); } #[test] fn from_str_strfix_exact_buffer() { let buf: &[u8] = &[0xaa, 0x6c, 0x65, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65]; let mut cur = Cursor::new(buf); let out: &mut [u8] = &mut [0u8; 10]; assert_eq!("le message", read_str(&mut cur, out).unwrap()); assert_eq!(11, cur.position()); } #[test] fn from_str_strfix_invalid_utf8() { // Invalid 2 Octet Sequence. let buf: &[u8] = &[0xa2, 0xc3, 0x28]; let mut cur = Cursor::new(buf); let out: &mut [u8] = &mut [0u8; 16]; match read_str(&mut cur, out) { Err(DecodeStringError::InvalidUtf8(raw, _)) => { assert_eq!(&[0xc3, 0x28], raw); } other => panic!("unexpected result: {:?}", other) } assert_eq!(3, cur.position()); } #[test] fn from_str_strfix_buffer_too_small() { let buf: &[u8] = &[0xaa, 0x6c, 0x65, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65]; let mut cur = Cursor::new(buf); let out: &mut [u8] = &mut [0u8; 9]; match read_str(&mut cur, out) { Err(DecodeStringError::BufferSizeTooSmall(10)) => (), other => panic!("unexpected result: {:?}", other) } assert_eq!(1, cur.position()); } #[test] fn from_str_strfix_decode_from_slice() { // Wrap an incomplete buffer into the Cursor to see how many bytes were consumed. let mut buf = vec![0xaa, 0x6c, 0x65, 0x20, 0x6d, 0x65, 0x73]; assert!(read_str_from_slice(&buf).is_err()); // ... complete the buffer and try to parse again. buf.append(&mut vec![0x73, 0x61, 0x67, 0x65]); assert_eq!(("le message", &[][..]), read_str_from_slice(&buf).unwrap()); } #[test] fn from_str_strfix_decode_from_slice_with_trailing_bytes() { let buf = vec![ 0xaa, 0x6c, 0x65, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x01, 0x02, 0x03 ]; assert_eq!(("le message", &[0x01, 0x02, 0x03][..]), read_str_from_slice(&buf).unwrap()); } #[test] fn example_process_sequence_of_strings() { // Encoded: 'Unpacking', 'multiple', 'strings'. let vec = vec![ 0xa9, 0x55, 0x6e, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 0xa8, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0xa7, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x73 ]; let mut chunks = Vec::new(); let mut unparsed = &vec[..]; loop { match read_str_from_slice(unparsed) { Ok((chunk, tail)) => { chunks.push(chunk); unparsed = tail; } Err(..) => break, } } assert_eq!(vec!["Unpacking", "multiple", "strings"], chunks); } rmp-0.8.11/tests/func/decode/uint.rs000064400000000000000000000115610072674642500154120ustar 00000000000000use super::Cursor; use crate::msgpack::decode::*; use crate::msgpack::Marker; #[test] fn from_positive_fixnum() { let buf = [0x00, 0x7f, 0x20]; let mut cur = Cursor::new(&buf[..]); assert_eq!(0u8, read_pfix(&mut cur).unwrap()); assert_eq!(1, cur.position()); assert_eq!(127u8, read_pfix(&mut cur).unwrap()); assert_eq!(2, cur.position()); assert_eq!(32u8, read_pfix(&mut cur).unwrap()); assert_eq!(3, cur.position()); } #[test] fn from_u8_min() { let buf = [0xcc, 0x00]; let mut cur = Cursor::new(&buf[..]); assert_eq!(0, read_u8(&mut cur).unwrap()); assert_eq!(2, cur.position()); } #[test] fn from_u8_max() { let buf = [0xcc, 0xff]; let mut cur = Cursor::new(&buf[..]); assert_eq!(255, read_u8(&mut cur).unwrap()); assert_eq!(2, cur.position()); } #[test] fn from_u8_type_mismatch() { let buf = [0xc0, 0x80]; let mut cur = Cursor::new(&buf[..]); match read_u8(&mut cur) { Err(ValueReadError::TypeMismatch(Marker::Null)) => (), other => panic!("unexpected result: {:?}", other), } assert_eq!(1, cur.position()); } #[test] fn from_u8_unexpected_eof() { let buf = [0xcc]; let mut cur = Cursor::new(&buf[..]); read_u8(&mut cur).err().unwrap(); assert_eq!(1, cur.position()); } #[test] fn from_u16_min() { let buf = [0xcd, 0x00, 0x00]; let mut cur = Cursor::new(&buf[..]); assert_eq!(0, read_u16(&mut cur).unwrap()); assert_eq!(3, cur.position()); } #[test] fn from_u32_max() { let buf = [0xce, 0xff, 0xff, 0xff, 0xff]; let mut cur = Cursor::new(&buf[..]); assert_eq!(4294967295, read_u32(&mut cur).unwrap()); assert_eq!(5, cur.position()); } #[test] fn from_unsigned_fixnum_read_int() { let buf = [0x00, 0x7f, 0x20]; let mut cur = Cursor::new(&buf[..]); assert_eq!(0u64, read_int(&mut cur).unwrap()); assert_eq!(1, cur.position()); assert_eq!(127u64, read_int(&mut cur).unwrap()); assert_eq!(2, cur.position()); assert_eq!(32u64, read_int(&mut cur).unwrap()); assert_eq!(3, cur.position()); } #[test] fn from_unsigned_u8_read_int() { let buf = [0xcc, 0x80, 0xcc, 0xff]; let mut cur = Cursor::new(&buf[..]); assert_eq!(128u64, read_int(&mut cur).unwrap()); assert_eq!(2, cur.position()); assert_eq!(255u64, read_int(&mut cur).unwrap()); assert_eq!(4, cur.position()); } #[test] fn from_unsigned_u8_incomplete_read_int() { let buf = [0xcc]; let mut cur = Cursor::new(&buf[..]); read_int::(&mut cur).err().unwrap(); assert_eq!(1, cur.position()); } #[test] fn from_unsigned_u16_read_int() { let buf = [0xcd, 0x01, 0x00, 0xcd, 0xff, 0xff]; let mut cur = Cursor::new(&buf[..]); assert_eq!(256u64, read_int(&mut cur).unwrap()); assert_eq!(3, cur.position()); assert_eq!(65535u64, read_int(&mut cur).unwrap()); assert_eq!(6, cur.position()); } #[test] fn from_unsigned_u16_incomplete_read_int() { let buf = [0xcd]; let mut cur = Cursor::new(&buf[..]); read_int::(&mut cur).err().unwrap(); assert_eq!(1, cur.position()); } #[test] fn from_unsigned_u32_read_int() { let buf = [0xce, 0x00, 0x01, 0x00, 0x00, 0xce, 0xff, 0xff, 0xff, 0xff]; let mut cur = Cursor::new(&buf[..]); assert_eq!(65536u64, read_int(&mut cur).unwrap()); assert_eq!(5, cur.position()); assert_eq!(4294967295u64, read_int(&mut cur).unwrap()); assert_eq!(10, cur.position()); } #[test] fn from_unsigned_u32_incomplete_read_int() { let buf = [0xce]; let mut cur = Cursor::new(&buf[..]); read_int::(&mut cur).err().unwrap(); assert_eq!(1, cur.position()); } #[test] fn from_unsigned_u64_read_int() { let buf = [ 0xcf, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff ]; let mut cur = Cursor::new(&buf[..]); assert_eq!(4294967296u64, read_int(&mut cur).unwrap()); assert_eq!(9, cur.position()); assert_eq!(18446744073709551615u64, read_int(&mut cur).unwrap()); assert_eq!(18, cur.position()); } #[test] fn from_unsigned_u64_incomplete_read_int() { let buf = [0xcf]; let mut cur = Cursor::new(&buf[..]); read_int::(&mut cur).err().unwrap(); assert_eq!(1, cur.position()); } #[test] fn from_unsigned_invalid_marker_read_int() { let buf = [0xc0]; let mut cur = Cursor::new(&buf[..]); match read_int::(&mut cur) { Err(NumValueReadError::TypeMismatch(Marker::Null)) => (), other => panic!("unexpected result: {:?}", other) } assert_eq!(1, cur.position()); } #[test] fn from_unsigned_invalid_unknown_marker_read_int() { let buf = [0xc1]; let mut cur = Cursor::new(&buf[..]); match read_int::(&mut cur) { Err(NumValueReadError::TypeMismatch(Marker::Reserved)) => (), other => panic!("unexpected result: {:?}", other) } assert_eq!(1, cur.position()); } rmp-0.8.11/tests/func/encode/array.rs000064400000000000000000000012400072674642500155540ustar 00000000000000use crate::msgpack::encode::*; use crate::msgpack::Marker; #[test] fn pass_pack_len_fix() { let mut buf = [0x00]; assert_eq!(Marker::FixArray(15), write_array_len(&mut &mut buf[..], 15).unwrap()); assert_eq!([0x9f], buf); } #[test] fn pass_pack_len_u16() { let mut buf = [0x00, 0x00, 0x00]; assert_eq!(Marker::Array16, write_array_len(&mut &mut buf[..], 65535).unwrap()); assert_eq!([0xdc, 0xff, 0xff], buf); } #[test] fn pass_pack_len_u32() { let mut buf = [0x00, 0x00, 0x00, 0x00, 0x00]; assert_eq!(Marker::Array32, write_array_len(&mut &mut buf[..], 4294967295).unwrap()); assert_eq!([0xdd, 0xff, 0xff, 0xff, 0xff], buf); } rmp-0.8.11/tests/func/encode/bin.rs000064400000000000000000000012320072674642500152070ustar 00000000000000use crate::msgpack::encode::*; use crate::msgpack::Marker; #[test] fn pass_pack_len_u8() { let mut buf = [0x00, 0x00]; assert_eq!(Marker::Bin8, write_bin_len(&mut &mut buf[..], 255).unwrap()); assert_eq!([0xc4, 0xff], buf); } #[test] fn pass_pack_len_u16() { let mut buf = [0x00, 0x00, 0x00]; assert_eq!(Marker::Bin16, write_bin_len(&mut &mut buf[..], 65535).unwrap()); assert_eq!([0xc5, 0xff, 0xff], buf); } #[test] fn pass_pack_len_u32() { let mut buf = [0x00, 0x00, 0x00, 0x00, 0x00]; assert_eq!(Marker::Bin32, write_bin_len(&mut &mut buf[..], 4294967295).unwrap()); assert_eq!([0xc6, 0xff, 0xff, 0xff, 0xff], buf); } rmp-0.8.11/tests/func/encode/bool.rs000064400000000000000000000004710072674642500153760ustar 00000000000000use crate::msgpack::encode::*; #[test] fn pass_pack_true() { let mut buf = [0x00]; write_bool(&mut &mut buf[..], true).unwrap(); assert_eq!([0xc3], buf); } #[test] fn pass_pack_false() { let mut buf = [0x00]; write_bool(&mut &mut buf[..], false).unwrap(); assert_eq!([0xc2], buf); } rmp-0.8.11/tests/func/encode/ext.rs000064400000000000000000000035210072674642500152420ustar 00000000000000use crate::msgpack::encode::*; use crate::msgpack::Marker; #[test] fn pass_pack_meta_fix1() { let mut buf = [0x00, 0x00]; assert_eq!(Marker::FixExt1, write_ext_meta(&mut &mut buf[..], 1, 16).unwrap()); assert_eq!([0xd4, 0x10], buf); } #[test] fn pass_pack_meta_fix2() { let mut buf = [0x00, 0x00]; assert_eq!(Marker::FixExt2, write_ext_meta(&mut &mut buf[..], 2, 16).unwrap()); assert_eq!([0xd5, 0x10], buf); } #[test] fn pass_pack_meta_fix4() { let mut buf = [0x00, 0x00]; assert_eq!(Marker::FixExt4, write_ext_meta(&mut &mut buf[..], 4, 16).unwrap()); assert_eq!([0xd6, 0x10], buf); } #[test] fn pass_pack_meta_fix4_timesamp() { let mut buf = [0x00, 0x00]; assert_eq!(Marker::FixExt4, write_ext_meta(&mut &mut buf[..], 4, -1).unwrap()); assert_eq!([0xd6, 0xff], buf); } #[test] fn pass_pack_meta_fix8() { let mut buf = [0x00, 0x00]; assert_eq!(Marker::FixExt8, write_ext_meta(&mut &mut buf[..], 8, 16).unwrap()); assert_eq!([0xd7, 0x10], buf); } #[test] fn pass_pack_meta_fix16() { let mut buf = [0x00, 0x00]; assert_eq!(Marker::FixExt16, write_ext_meta(&mut &mut buf[..], 16, 16).unwrap()); assert_eq!([0xd8, 0x10], buf); } #[test] fn pass_pack_meta_8() { let mut buf = [0x00, 0x00, 0x00]; assert_eq!(Marker::Ext8, write_ext_meta(&mut &mut buf[..], 255, 16).unwrap()); assert_eq!([0xc7, 0xff, 0x10], buf); } #[test] fn pass_pack_meta_16() { let mut buf = [0x00, 0x00, 0x00, 0x00]; assert_eq!(Marker::Ext16, write_ext_meta(&mut &mut buf[..], 65535, 16).unwrap()); assert_eq!([0xc8, 0xff, 0xff, 0x10], buf); } #[test] fn pass_pack_meta_32() { let mut buf = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; assert_eq!(Marker::Ext32, write_ext_meta(&mut &mut buf[..], 4294967295, 16).unwrap()); assert_eq!([0xc9, 0xff, 0xff, 0xff, 0xff, 0x10], buf); } rmp-0.8.11/tests/func/encode/float.rs000064400000000000000000000007650072674642500155560ustar 00000000000000use crate::msgpack::encode::*; #[test] fn pass_pack_f32() { let mut buf = [0x00, 0x00, 0x00, 0x00, 0x00]; write_f32(&mut &mut buf[..], 3.4028234e38_f32).ok().unwrap(); assert_eq!([0xca, 0x7f, 0x7f, 0xff, 0xff], buf); } #[test] fn pass_pack_f64() { use std::f64; let mut buf = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; write_f64(&mut &mut buf[..], f64::INFINITY).ok().unwrap(); assert_eq!([0xcb, 0x7f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], buf); } rmp-0.8.11/tests/func/encode/int.rs000064400000000000000000000140060072674642500152340ustar 00000000000000use crate::msgpack::encode::*; use crate::msgpack::Marker; #[test] fn pass_pack_pfix() { let mut buf = [0x00]; write_pfix(&mut &mut buf[..], 127).ok().unwrap(); assert_eq!([0x7f], buf); } #[test] fn fail_pack_pfix_too_small_buffer() { let mut buf = []; write_pfix(&mut &mut buf[..], 127).err().unwrap(); } #[test] #[should_panic(expected = "assertion failed")] fn fail_pack_pfix_too_large() { let mut buf = [0x00]; write_pfix(&mut &mut buf[..], 128).ok().unwrap(); } #[test] fn pass_pack_u8() { let mut buf = [0x00, 0x00]; write_u8(&mut &mut buf[..], 255).ok().unwrap(); assert_eq!([0xcc, 0xff], buf); } #[test] fn pass_pack_u16() { let mut buf = [0x00, 0x00, 0x00]; write_u16(&mut &mut buf[..], 65535).ok().unwrap(); assert_eq!([0xcd, 0xff, 0xff], buf); } #[test] fn pass_pack_u32() { let mut buf = [0x00, 0x00, 0x00, 0x00, 0x00]; write_u32(&mut &mut buf[..], 4294967295).ok().unwrap(); assert_eq!([0xce, 0xff, 0xff, 0xff, 0xff], buf); } #[test] fn pass_pack_u64() { let mut buf = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; write_u64(&mut &mut buf[..], 18446744073709551615).ok().unwrap(); assert_eq!([0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff], buf); } #[test] fn pass_pack_nfix() { let mut buf = [0x00]; write_nfix(&mut &mut buf[..], -32).ok().unwrap(); assert_eq!([0xe0], buf); } #[test] #[should_panic(expected = "assertion failed")] fn fail_pack_nfix_too_large() { let mut buf = [0x00]; write_nfix(&mut &mut buf[..], 0).ok().unwrap(); } #[test] #[should_panic(expected = "assertion failed")] fn fail_pack_nfix_too_small() { let mut buf = [0x00]; write_nfix(&mut &mut buf[..], -33).ok().unwrap(); } #[test] fn pass_pack_i8() { let mut buf = [0x00, 0x00]; write_i8(&mut &mut buf[..], -128).ok().unwrap(); assert_eq!([0xd0, 0x80], buf); } #[test] fn pass_pack_i16() { let mut buf = [0x00, 0x00, 0x00]; write_i16(&mut &mut buf[..], -32768).ok().unwrap(); assert_eq!([0xd1, 0x80, 0x00], buf); } #[test] fn pass_pack_i32() { let mut buf = [0x00, 0x00, 0x00, 0x00, 0x00]; write_i32(&mut &mut buf[..], -2147483648).ok().unwrap(); assert_eq!([0xd2, 0x80, 0x00, 0x00, 0x00], buf); } #[test] fn pass_pack_i64() { let mut buf = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; write_i64(&mut &mut buf[..], -9223372036854775808).ok().unwrap(); assert_eq!([0xd3, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], buf); } #[test] fn pass_pack_uint_fix() { let mut buf = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; assert_eq!(Marker::FixPos(127), write_uint(&mut &mut buf[..], 127).ok().unwrap()); assert_eq!([0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], buf); } #[test] fn pass_pack_uint_u8() { let mut buf = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; assert_eq!(Marker::U8, write_uint(&mut &mut buf[..], 255).ok().unwrap()); assert_eq!([0xcc, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], buf); } #[test] fn pass_pack_uint_u16() { let mut buf = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; assert_eq!(Marker::U16, write_uint(&mut &mut buf[..], 65535).ok().unwrap()); assert_eq!([0xcd, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], buf); } #[test] fn pass_pack_uint_u32() { let mut buf = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; assert_eq!(Marker::U32, write_uint(&mut &mut buf[..], 4294967295).ok().unwrap()); assert_eq!([0xce, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00], buf); } #[test] fn pass_pack_uint_u64() { let mut buf = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; assert_eq!(Marker::U64, write_uint(&mut &mut buf[..], 18446744073709551615).ok().unwrap()); assert_eq!([0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff], buf); } #[test] fn pass_pack_sint_fix() { let mut buf = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; assert_eq!(Marker::FixNeg(-32), write_sint(&mut &mut buf[..], -32).ok().unwrap()); assert_eq!([0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], buf); } #[test] fn pass_pack_sint_i8_min() { let mut buf = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; assert_eq!(Marker::I8, write_sint(&mut &mut buf[..], -128).ok().unwrap()); assert_eq!([0xd0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], buf); } #[test] fn pass_pack_sint_i16_min() { let mut buf = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; assert_eq!(Marker::I16, write_sint(&mut &mut buf[..], -32768).ok().unwrap()); assert_eq!([0xd1, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], buf); } #[test] fn pass_pack_sint_i16_max() { let mut buf = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; assert_eq!(Marker::U16, write_sint(&mut &mut buf[..], 32767).ok().unwrap()); assert_eq!([0xcd, 0x7f, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], buf); } #[test] fn pass_pack_sint_i32_min() { let mut buf = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; assert_eq!(Marker::I32, write_sint(&mut &mut buf[..], -2147483648).ok().unwrap()); assert_eq!([0xd2, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], buf); } #[test] fn pass_pack_sint_i32_max() { let mut buf = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; assert_eq!(Marker::U32, write_sint(&mut &mut buf[..], 2147483647).ok().unwrap()); assert_eq!([0xce, 0x7f, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00], buf); } #[test] fn pass_pack_sint_i64_min() { let mut buf = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; assert_eq!(Marker::I64, write_sint(&mut &mut buf[..], -9223372036854775808).ok().unwrap()); assert_eq!([0xd3, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], buf); } #[test] fn pass_pack_sint_i64_max() { let mut buf = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; assert_eq!(Marker::U64, write_sint(&mut &mut buf[..], 9223372036854775807).ok().unwrap()); assert_eq!([0xcf, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff], buf); } rmp-0.8.11/tests/func/encode/map.rs000064400000000000000000000012240072674642500152150ustar 00000000000000use crate::msgpack::encode::*; use crate::msgpack::Marker; #[test] fn pass_pack_len_fix() { let mut buf = [0x00]; assert_eq!(Marker::FixMap(15), write_map_len(&mut &mut buf[..], 15).unwrap()); assert_eq!([0x8f], buf); } #[test] fn pass_pack_len_u16() { let mut buf = [0x00, 0x00, 0x00]; assert_eq!(Marker::Map16, write_map_len(&mut &mut buf[..], 65535).unwrap()); assert_eq!([0xde, 0xff, 0xff], buf); } #[test] fn pass_pack_len_u32() { let mut buf = [0x00, 0x00, 0x00, 0x00, 0x00]; assert_eq!(Marker::Map32, write_map_len(&mut &mut buf[..], 4294967295).unwrap()); assert_eq!([0xdf, 0xff, 0xff, 0xff, 0xff], buf); } rmp-0.8.11/tests/func/encode/mod.rs000064400000000000000000000001320072674642500152140ustar 00000000000000mod array; mod bin; mod bool; mod ext; mod float; mod int; mod map; mod null; mod string; rmp-0.8.11/tests/func/encode/null.rs000064400000000000000000000004230072674642500154120ustar 00000000000000use crate::msgpack::encode::*; #[test] fn pass_pack() { let mut buf = [0x00]; write_nil(&mut &mut buf[..]).unwrap(); assert_eq!([0xc0], buf); } #[test] fn fail_pack_too_small_buffer() { let mut buf = []; write_nil(&mut &mut buf[..]).err().unwrap(); } rmp-0.8.11/tests/func/encode/string.rs000064400000000000000000000015120072674642500157460ustar 00000000000000use crate::msgpack::encode::*; use crate::msgpack::Marker; #[test] fn pass_pack_len_fix() { let mut buf = [0x00]; assert_eq!(Marker::FixStr(31), write_str_len(&mut &mut buf[..], 31).unwrap()); assert_eq!([0xbf], buf); } #[test] fn pass_pack_len_u8() { let mut buf = [0x00, 0x00]; assert_eq!(Marker::Str8, write_str_len(&mut &mut buf[..], 255).unwrap()); assert_eq!([0xd9, 0xff], buf); } #[test] fn pass_pack_len_u16() { let mut buf = [0x00, 0x00, 0x00]; assert_eq!(Marker::Str16, write_str_len(&mut &mut buf[..], 65535).unwrap()); assert_eq!([0xda, 0xff, 0xff], buf); } #[test] fn pass_pack_len_u32() { let mut buf = [0x00, 0x00, 0x00, 0x00, 0x00]; assert_eq!(Marker::Str32, write_str_len(&mut &mut buf[..], 4294967295).unwrap()); assert_eq!([0xdb, 0xff, 0xff, 0xff, 0xff], buf); } rmp-0.8.11/tests/func/mirror.rs000064400000000000000000000020610072674642500145150ustar 00000000000000use msgpack::decode::Bytes; use msgpack::encode::ByteBuf; use crate::msgpack::{decode, encode}; quickcheck! { fn mirror_uint(xs: u64) -> bool { let mut buf = ByteBuf::new(); encode::write_uint(&mut buf, xs).unwrap(); xs == decode::read_int(&mut Bytes::new(buf.as_slice())).unwrap() } fn mirror_sint(xs: i64) -> bool { let mut buf = ByteBuf::new(); encode::write_sint(&mut buf, xs).unwrap(); xs == decode::read_int(&mut Bytes::new(buf.as_slice())).unwrap() } fn mirror_f32(xs: f32) -> bool { let mut buf = ByteBuf::new(); encode::write_f32(&mut buf, xs).unwrap(); let res = decode::read_f32(&mut Bytes::new(buf.as_slice())).unwrap(); xs == res || (xs.is_nan() && res.is_nan()) } fn mirror_f64(xs: f64) -> bool { let mut buf = ByteBuf::new(); encode::write_f64(&mut buf, xs).expect("write"); let res = decode::read_f64(&mut Bytes::new(buf.as_slice())).expect("read"); true || xs == res || (xs.is_nan() && res.is_nan()) } } rmp-0.8.11/tests/func/mod.rs000064400000000000000000000000440072674642500137610ustar 00000000000000mod decode; mod encode; mod mirror; rmp-0.8.11/tests/lib.rs000064400000000000000000000001340072674642500130150ustar 00000000000000extern crate rmp as msgpack; #[cfg(test)] #[macro_use] extern crate quickcheck; mod func;