rmp-0.8.14/.cargo_vcs_info.json0000644000000001410000000000100117200ustar { "git": { "sha1": "143897c5abae2b3fbf7afbaaa6be22828c891c54" }, "path_in_vcs": "rmp" }rmp-0.8.14/CHANGELOG.md000064400000000000000000000163251046102023000123340ustar 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.14/Cargo.lock0000644000000100210000000000100076710ustar # This file is automatically @generated by Cargo. # It is not intended for manual editing. version = 3 [[package]] name = "aho-corasick" version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" dependencies = [ "memchr", ] [[package]] name = "autocfg" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80" [[package]] name = "byteorder" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "cfg-if" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "env_logger" version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a19187fea3ac7e84da7dacf48de0c45d63c6a76f9490dae389aead16c243fce3" dependencies = [ "log", "regex", ] [[package]] name = "getrandom" version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94b22e06ecb0110981051723910cbf0b5f5e09a2062dd7663334ee79a9d1286c" dependencies = [ "cfg-if", "libc", "wasi", ] [[package]] name = "libc" version = "0.2.153" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" [[package]] name = "log" version = "0.4.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" [[package]] name = "memchr" version = "2.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" [[package]] name = "num-traits" version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" dependencies = [ "autocfg", ] [[package]] name = "paste" version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" [[package]] name = "quickcheck" version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "588f6378e4dd99458b60ec275b4477add41ce4fa9f64dcba6f15adccb19b50d6" dependencies = [ "env_logger", "log", "rand", ] [[package]] name = "rand" version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "rand_core", ] [[package]] name = "rand_core" version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ "getrandom", ] [[package]] name = "regex" version = "1.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" dependencies = [ "aho-corasick", "memchr", "regex-automata", "regex-syntax", ] [[package]] name = "regex-automata" version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" dependencies = [ "aho-corasick", "memchr", "regex-syntax", ] [[package]] name = "regex-syntax" version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" [[package]] name = "rmp" version = "0.8.14" dependencies = [ "byteorder", "num-traits", "paste", "quickcheck", ] [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" rmp-0.8.14/Cargo.toml0000644000000023730000000000100077270ustar # 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 = "2021" name = "rmp" version = "0.8.14" 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" [package.metadata.release] tag-prefix = "{{crate_name}}/" [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 = "looking-for-maintainer" rmp-0.8.14/Cargo.toml.orig000064400000000000000000000014161046102023000134050ustar 00000000000000[package] name = "rmp" version = "0.8.14" 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 = "2021" [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" [package.metadata.release] tag-prefix = "{{crate_name}}/" [badges] maintenance = { status = "looking-for-maintainer" } rmp-0.8.14/LICENSE000064400000000000000000000020601046102023000115170ustar 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.14/README.md000064400000000000000000000114371046102023000120010ustar 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. [Looking for Serde support](https://lib.rs/crates/rmp-serde)? 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. ### Usage To use `rmp`, first add this to your `Cargo.toml`: ```toml [dependencies.rmp] rmp = "0.8" ``` ### Features - **Low-level API** RMP is designed to be lightweight and straightforward. There are low-level APIs, which give you full control over the encoding/decoding process. `no-std` environments are supported. - **Zero-copy value decoding** RMP allows to decode bytes from a buffer in a zero-copy manner, without any heap allocations. easily and blazingly fast. Rust static checks guarantee 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 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()); ``` License: MIT [read_int]: https://docs.rs/rmp/latest/rmp/decode/fn.read_int.html rmp-0.8.14/benches/bench.rs000064400000000000000000000017451046102023000135570ustar 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.14/clippy.toml000064400000000000000000000000431046102023000127060ustar 00000000000000doc-valid-idents = ["MessagePack"] rmp-0.8.14/examples/inspect.rs000064400000000000000000000121301046102023000143420ustar 00000000000000use std::fmt; use std::io::{self, Read}; use rmp::{decode::*, Marker}; fn main() { let path = std::env::args_os().nth(1).expect("Specify path to a file with msgpack content"); let data = std::fs::read(&path).expect(&path.to_string_lossy()); dump(&mut Indent { i: 0, start: true }, &mut data.as_slice()).unwrap(); } fn dump(indent: &mut Indent, rd: &mut &[u8]) -> Result<(), Box> { match read_marker(rd).map_err(ValueReadError::from)? { Marker::FixPos(n) => print!("U0({n})"), Marker::FixNeg(n) => print!("I0({n})"), Marker::Null => print!("Null"), Marker::True => print!("True"), Marker::False => print!("False"), Marker::U8 => print!("U8({})", rd.read_data_u8()?), Marker::U16 => print!("U16({})", rd.read_data_u16()?), Marker::U32 => print!("U32({})", rd.read_data_u32()?), Marker::U64 => print!("U64({})", rd.read_data_u64()?), Marker::I8 => print!("I8({})", rd.read_data_i8()?), Marker::I16 => print!("I16({})", rd.read_data_i16()?), Marker::I32 => print!("I32({})", rd.read_data_i32()?), Marker::I64 => print!("I64({})", rd.read_data_i64()?), Marker::F32 => print!("F32({})", rd.read_data_f32()?), Marker::F64 => print!("F64({})", rd.read_data_f64()?), Marker::FixStr(len) => print!("Str0(\"{}\")", read_str_data(len.into(), rd)?), Marker::Str8 => print!("Str8(\"{}\")", read_str_data(rd.read_data_u8()?.into(), rd)?), Marker::Str16 => print!("Str16(\"{}\")", read_str_data(rd.read_data_u16()?.into(), rd)?), Marker::Str32 => print!("Str32(\"{}\")", read_str_data(rd.read_data_u32()?.into(), rd)?), Marker::Bin8 => print!("Bin8({})", HexDump(&read_bin_data(rd.read_data_u8()?.into(), rd)?)), Marker::Bin16 => print!("Bin16({})", HexDump(&read_bin_data(rd.read_data_u16()?.into(), rd)?)), Marker::Bin32 => print!("Bin32({})", HexDump(&read_bin_data(rd.read_data_u32()?.into(), rd)?)), Marker::FixArray(len) => dump_array(indent, 0, len.into(), rd)?, Marker::Array16 => dump_array(indent, 16, rd.read_data_u16()?.into(), rd)?, Marker::Array32 => dump_array(indent, 32, rd.read_data_u32()?.into(), rd)?, Marker::FixMap(len) => dump_map(indent, 0, len.into(), rd)?, Marker::Map16 => dump_map(indent, 16, rd.read_data_u16()?.into(), rd)?, Marker::Map32 => dump_map(indent, 32, rd.read_data_u32()?.into(), rd)?, Marker::FixExt1 => todo!(), Marker::FixExt2 => todo!(), Marker::FixExt4 => todo!(), Marker::FixExt8 => todo!(), Marker::FixExt16 => todo!(), Marker::Ext8 => todo!(), Marker::Ext16 => todo!(), Marker::Ext32 => todo!(), Marker::Reserved => todo!(), } Ok(()) } fn dump_map(indent: &mut Indent, ty: u8, len: u32, rd: &mut &[u8]) -> Result<(), Box> { indent.print(format_args!("Map{ty}{{")); let multiline = len > 1; if multiline { indent.ln(); } else { print!(" ") } indent.ind(); for i in 0..len { indent.print(""); dump(indent, rd)?; print!(": "); dump(indent, rd)?; if multiline { print!(","); indent.ln(); } else if i+1 != len { print!(", ") } } indent.out(); indent.print(format_args!("}}")); Ok(()) } fn dump_array(indent: &mut Indent, ty: u8, len: u32, rd: &mut &[u8]) -> Result<(), Box> { indent.print(format_args!("Array{ty}[")); let multiline = len > 1; if multiline { indent.ln(); } else { print!(" ") } indent.ind(); for i in 0..len { indent.print(""); dump(indent, rd)?; if multiline { print!(","); indent.ln(); } else if i+1 != len { print!(", ") } } indent.out(); indent.print("]"); Ok(()) } fn read_str_data(len: u32, rd: &mut R) -> Result { Ok(String::from_utf8_lossy(&read_bin_data(len, rd)?).into_owned()) } fn read_bin_data(len: u32, rd: &mut R) -> Result, io::Error> { let mut buf = Vec::with_capacity(len.min(1<<16) as usize); let bytes_read = rd.take(len as u64).read_to_end(&mut buf)?; if bytes_read != len as usize { return Err(io::ErrorKind::UnexpectedEof.into()); } Ok(buf) } struct Indent { i: u16, start: bool } impl Indent { fn print(&mut self, args: impl fmt::Display) { print!("{:w$}{args}", "", w = if self.start { (self.i as usize) * 2 } else { 0 }); self.start = false; } pub fn ind(&mut self) { self.i += 1; } pub fn ln(&mut self) { println!(); self.start = true; } pub fn out(&mut self) { self.i -= 1; } } struct HexDump<'a>(&'a [u8]); impl fmt::Display for HexDump<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let truncate = self.0.len() > 50; if truncate { f.write_fmt(format_args!("{}B ", self.0.len()))?; } for &b in &self.0[0.. (if truncate { 50 } else { self.0.len() })] { f.write_fmt(format_args!("{b:02x}"))?; } if truncate { f.write_str("…")?; } Ok(()) } } rmp-0.8.14/src/decode/bytes.rs000064400000000000000000000113271046102023000142260ustar 00000000000000//! Implementation of the [Bytes] type use super::RmpRead; use crate::decode::RmpReadErr; use core::fmt::{Display, Formatter}; /// 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 {expected}, but only got {actual} (pos {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] #[must_use] pub fn new(bytes: &'a [u8]) -> Self { Bytes { bytes, current_position: 0 } } /// Get a reference to the remaining bytes in the buffer. #[inline] #[must_use] 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] #[must_use] 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.14/src/decode/dec.rs000064400000000000000000000033201046102023000136250ustar 00000000000000use super::{read_marker, RmpRead, 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.14/src/decode/ext.rs000064400000000000000000000136711046102023000137040ustar 00000000000000use super::{read_marker, RmpRead, ValueReadError}; use crate::Marker; /// 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 => u32::from(rd.read_data_u8()?), Marker::Ext16 => u32::from(rd.read_data_u16()?), 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.14/src/decode/mod.rs000064400000000000000000000404031046102023000136540ustar 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}; use core::fmt::{self, Debug, Display, Formatter}; #[cfg(feature = "std")] use std::error; 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(u32::from(size)), Marker::Array16 => Ok(u32::from(rd.read_data_u16()?)), 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(u32::from(size)), Marker::Map16 => Ok(u32::from(rd.read_data_u16()?)), 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(u32::from(rd.read_data_u8()?)), Marker::Bin16 => Ok(u32::from(rd.read_data_u16()?)), Marker::Bin32 => Ok(rd.read_data_u32()?), marker => Err(ValueReadError::TypeMismatch(marker)), } } rmp-0.8.14/src/decode/sint.rs000064400000000000000000000104221046102023000140500ustar 00000000000000use super::{read_marker, RmpRead, ValueReadError}; use crate::Marker; /// 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.14/src/decode/str.rs000064400000000000000000000152471046102023000137150ustar 00000000000000#[cfg(feature = "std")] use std::error; use core::fmt::{self, Display, Formatter}; use core::str::{from_utf8, Utf8Error}; use super::{read_marker, RmpRead, RmpReadErr, 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((u32::from(size), 1)), Marker::Str8 => Ok((u32::from(rd.read_data_u8()?), 2)), Marker::Str16 => Ok((u32::from(rd.read_data_u16()?), 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.14/src/decode/uint.rs000064400000000000000000000102131046102023000140500ustar 00000000000000use super::{read_marker, RmpRead, ValueReadError}; use crate::Marker; /// 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.14/src/encode/bin.rs000064400000000000000000000030451046102023000136600ustar 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> { let marker = if len < 256 { Marker::Bin8 } else if len <= u16::MAX as u32 { Marker::Bin16 } else { Marker::Bin32 }; write_marker(&mut *wr, marker)?; if marker == Marker::Bin8 { wr.write_data_u8(len as u8)?; } else if marker == Marker::Bin16 { wr.write_data_u16(len as u16)?; } else if marker == Marker::Bin32 { wr.write_data_u32(len)?; } Ok(marker) } /// 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.14/src/encode/buffer.rs000064400000000000000000000122431046102023000143610ustar 00000000000000//! Implementation of the [`ByteBuf`] type use super::RmpWrite; use alloc::vec::Vec; #[cfg(not(feature = "std"))] use core::fmt::{self, Display, Formatter}; /// 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] #[must_use] pub fn new() -> Self { ByteBuf { bytes: Vec::new() } } /// Construct a new buffer with the specified capacity /// /// See [`Vec::with_capacity`] for details #[inline] #[must_use] pub fn with_capacity(capacity: usize) -> Self { ByteBuf { bytes: Vec::with_capacity(capacity), } } /// Unwrap the underlying buffer of this vector #[inline] #[must_use] pub fn into_vec(self) -> Vec { self.bytes } /// Wrap the specified vector as a [`ByteBuf`] #[inline] #[must_use] pub fn from_vec(bytes: Vec) -> Self { ByteBuf { bytes } } /// Get a reference to this type as a [Vec] #[inline] #[must_use] 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] #[must_use] 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.14/src/encode/dec.rs000064400000000000000000000021161046102023000136410ustar 00000000000000use super::{write_marker, RmpWrite}; 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.14/src/encode/ext.rs000064400000000000000000000000011046102023000136750ustar 00000000000000 rmp-0.8.14/src/encode/map.rs000064400000000000000000000000011046102023000136520ustar 00000000000000 rmp-0.8.14/src/encode/mod.rs000064400000000000000000000235521046102023000136740ustar 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, write_uint8}; use core::fmt::{self, Debug, Display, Formatter}; #[cfg(feature = "std")] use std::error; 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::io::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 { Marker::FixArray(len as u8) } else if len <= u16::MAX as u32 { Marker::Array16 } else { Marker::Array32 }; write_marker(wr, marker)?; if marker == Marker::Array16 { wr.write_data_u16(len as u16)?; } else if marker == Marker::Array32 { wr.write_data_u32(len)?; } 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 { Marker::FixMap(len as u8) } else if len <= u16::MAX as u32 { Marker::Map16 } else { Marker::Map32 }; write_marker(wr, marker)?; if marker == Marker::Map16 { wr.write_data_u16(len as u16)?; } else if marker == Marker::Map32 { wr.write_data_u32(len)?; } 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 => Marker::FixExt1, 2 => Marker::FixExt2, 4 => Marker::FixExt4, 8 => Marker::FixExt8, 16 => Marker::FixExt16, 0..=255 => Marker::Ext8, 256..=65535 => Marker::Ext16, _ => Marker::Ext32, }; write_marker(wr, marker)?; if marker == Marker::Ext8 { wr.write_data_u8(len as u8)?; } else if marker == Marker::Ext16 { wr.write_data_u16(len as u16)?; } else if marker == Marker::Ext32 { wr.write_data_u32(len)?; } wr.write_data_i8(ty)?; Ok(marker) } rmp-0.8.14/src/encode/sint.rs000064400000000000000000000160201046102023000140620ustar 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.14/src/encode/str.rs000064400000000000000000000027171046102023000137250ustar 00000000000000use super::{write_marker, RmpWrite}; 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> { let marker = if len < 32 { Marker::FixStr(len as u8) } else if len < 256 { Marker::Str8 } else if len <= u16::MAX as u32 { Marker::Str16 } else { Marker::Str32 }; write_marker(wr, marker)?; if marker == Marker::Str8 { wr.write_data_u8(len as u8)?; } if marker == Marker::Str16 { wr.write_data_u16(len as u16)?; } if marker == Marker::Str32 { wr.write_data_u32(len)?; } Ok(marker) } /// 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.14/src/encode/uint.rs000064400000000000000000000142711046102023000140720ustar 00000000000000use super::{write_marker, RmpWrite}; 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 `u8` value into the given write using the most efficient /// representation, returning the marker used. /// /// See [`write_uint`] for more info. pub fn write_uint8(wr: &mut W, val: u8) -> Result> { if val < 128 { write_pfix(wr, val) .and(Ok(Marker::FixPos(val))) .map_err(ValueWriteError::InvalidMarkerWrite) } else { write_u8(wr, val).and(Ok(Marker::U8)) } } /// 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 < 256 { write_uint8(wr, val as 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.14/src/encode/vec.rs000064400000000000000000000000011046102023000136520ustar 00000000000000 rmp-0.8.14/src/errors.rs000064400000000000000000000027171046102023000131740ustar 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.14/src/lib.rs000064400000000000000000000005031046102023000124150ustar 00000000000000#![doc = include_str!("../README.md")] #![cfg_attr(not(feature = "std"), no_std)] extern crate alloc; pub mod decode; pub mod encode; mod errors; mod marker; 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.14/src/marker.rs000064400000000000000000000105031046102023000131310ustar 00000000000000const FIXSTR_SIZE : u8 = 0x1f; const FIXARRAY_SIZE : u8 = 0x0f; const FIXMAP_SIZE : u8 = 0x0f; /// Format markers. #[derive(Clone, Copy, Debug, PartialEq)] #[repr(u8)] pub enum Marker { FixPos(u8) = 0x00, FixNeg(i8) = 0xe0, FixMap(u8) = 0x80, FixArray(u8) = 0x90, FixStr(u8) = 0xa0, Null = 0xc0, // Marked in MessagePack spec as never used. Reserved, False, True, Bin8, Bin16, Bin32, Ext8, Ext16, Ext32, F32, F64, U8, U16, U32, U64, I8, I16, I32, I64, FixExt1, FixExt2, FixExt4, FixExt8, FixExt16, Str8, Str16, Str32, Array16, Array32, Map16, Map32, } impl Marker { /// Construct a msgpack marker from a single byte. #[must_use] #[inline] 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. #[must_use] #[inline] 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(always)] fn from(val: u8) -> Marker { Marker::from_u8(val) } } impl From for u8 { #[inline(always)] fn from(val: Marker) -> Self { val.to_u8() } } rmp-0.8.14/tests/func/decode/array.rs000064400000000000000000000042271046102023000155250ustar 00000000000000use super::Cursor; use rmp::decode::*; use rmp::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.14/tests/func/decode/bin.rs000064400000000000000000000025541046102023000151600ustar 00000000000000use super::Cursor; use rmp::decode::*; use rmp::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.14/tests/func/decode/bool.rs000064400000000000000000000006101046102023000153320ustar 00000000000000use super::Cursor; use rmp::decode::*; #[test] fn from_bool_false() { let buf = [0xc2]; let mut cur = Cursor::new(&buf[..]); assert!(!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.14/tests/func/decode/ext.rs000064400000000000000000000066041046102023000152100ustar 00000000000000use super::Cursor; use rmp::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.14/tests/func/decode/float.rs000064400000000000000000000050061046102023000155100ustar 00000000000000use super::Cursor; use rmp::decode::*; use rmp::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.14/tests/func/decode/map.rs000064400000000000000000000026211046102023000151600ustar 00000000000000use super::Cursor; use rmp::decode::*; use rmp::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.14/tests/func/decode/mod.rs000064400000000000000000000003721046102023000151630ustar 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> = rmp::decode::Bytes<'a>; rmp-0.8.14/tests/func/decode/null.rs000064400000000000000000000026431046102023000153610ustar 00000000000000use super::Cursor; use rmp::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.14/tests/func/decode/sint.rs000064400000000000000000000147121046102023000153640ustar 00000000000000use super::Cursor; use rmp::decode::*; use rmp::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!(-2_147_483_648, 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.14/tests/func/decode/string.rs000064400000000000000000000141571046102023000157200ustar 00000000000000use super::Cursor; use rmp::decode::*; use rmp::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 = [ 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!(["Unpacking", "multiple", "strings"], chunks[..]); } rmp-0.8.14/tests/func/decode/uint.rs000064400000000000000000000115251046102023000153650ustar 00000000000000use super::Cursor; use rmp::decode::*; use rmp::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.14/tests/func/encode/array.rs000064400000000000000000000012121046102023000155260ustar 00000000000000use rmp::encode::*; use rmp::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.14/tests/func/encode/bin.rs000064400000000000000000000012041046102023000151610ustar 00000000000000use rmp::encode::*; use rmp::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.14/tests/func/encode/bool.rs000064400000000000000000000004561046102023000153540ustar 00000000000000use rmp::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.14/tests/func/encode/ext.rs000064400000000000000000000034731046102023000152230ustar 00000000000000use rmp::encode::*; use rmp::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.14/tests/func/encode/float.rs000064400000000000000000000007521046102023000155250ustar 00000000000000use rmp::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.14/tests/func/encode/int.rs000064400000000000000000000137601046102023000152150ustar 00000000000000use rmp::encode::*; use rmp::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.14/tests/func/encode/map.rs000064400000000000000000000011761046102023000151760ustar 00000000000000use rmp::encode::*; use rmp::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.14/tests/func/encode/mod.rs000064400000000000000000000001321046102023000151670ustar 00000000000000mod array; mod bin; mod bool; mod ext; mod float; mod int; mod map; mod null; mod string; rmp-0.8.14/tests/func/encode/null.rs000064400000000000000000000004101046102023000153610ustar 00000000000000use rmp::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.14/tests/func/encode/string.rs000064400000000000000000000014641046102023000157270ustar 00000000000000use rmp::encode::*; use rmp::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.14/tests/func/mirror.rs000064400000000000000000000020361046102023000144720ustar 00000000000000use rmp::decode::Bytes; use rmp::encode::ByteBuf; use rmp::{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.14/tests/lib.rs000064400000000000000000000001611046102023000127700ustar 00000000000000#[cfg(test)] #[macro_use] extern crate quickcheck; mod func { mod decode; mod encode; mod mirror; }