├── .github └── workflows │ └── ci.yml ├── .gitignore ├── .rustfmt.toml ├── Cargo.toml ├── LICENSE ├── README.md ├── rmp-serde ├── CHANGELOG.md ├── Cargo.toml ├── LICENSE ├── README.md ├── benches │ └── buf.rs ├── src │ ├── bytes.rs │ ├── config.rs │ ├── decode.rs │ ├── encode.rs │ └── lib.rs └── tests │ ├── decode.rs │ ├── decode_derive.rs │ ├── encode.rs │ ├── encode_derive.rs │ └── round.rs ├── rmp ├── CHANGELOG.md ├── Cargo.toml ├── LICENSE ├── README.md ├── benches │ └── bench.rs ├── clippy.toml ├── examples │ └── inspect.rs ├── src │ ├── decode │ │ ├── bytes.rs │ │ ├── dec.rs │ │ ├── est.rs │ │ ├── ext.rs │ │ ├── mod.rs │ │ ├── sint.rs │ │ ├── str.rs │ │ └── uint.rs │ ├── encode │ │ ├── bin.rs │ │ ├── buffer.rs │ │ ├── dec.rs │ │ ├── ext.rs │ │ ├── map.rs │ │ ├── mod.rs │ │ ├── sint.rs │ │ ├── str.rs │ │ ├── uint.rs │ │ └── vec.rs │ ├── errors.rs │ ├── lib.rs │ └── marker.rs └── tests │ ├── func │ ├── decode │ │ ├── array.rs │ │ ├── bin.rs │ │ ├── bool.rs │ │ ├── ext.rs │ │ ├── float.rs │ │ ├── map.rs │ │ ├── mod.rs │ │ ├── null.rs │ │ ├── sint.rs │ │ ├── string.rs │ │ └── uint.rs │ ├── encode │ │ ├── array.rs │ │ ├── bin.rs │ │ ├── bool.rs │ │ ├── ext.rs │ │ ├── float.rs │ │ ├── int.rs │ │ ├── map.rs │ │ ├── mod.rs │ │ ├── null.rs │ │ └── string.rs │ ├── est.rs │ └── mirror.rs │ └── lib.rs ├── rmpv-tests ├── Cargo.toml ├── LICENSE ├── benches │ └── value.rs └── tests │ ├── de_ref.rs │ ├── decode.rs │ ├── encode.rs │ └── round.rs └── rmpv ├── CHANGELOG.md ├── Cargo.toml ├── LICENSE ├── README.md ├── benches └── value.rs ├── src ├── decode │ ├── mod.rs │ ├── value.rs │ └── value_ref.rs ├── encode │ ├── mod.rs │ ├── value.rs │ └── value_ref.rs ├── ext │ ├── de.rs │ ├── mod.rs │ └── se.rs └── lib.rs └── tests ├── decode.rs ├── decode_ref.rs ├── encode_ref.rs ├── mirror.rs └── value.rs /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: Build 2 | on: 3 | push: 4 | pull_request: 5 | 6 | jobs: 7 | check: 8 | name: Tests 9 | runs-on: ubuntu-latest 10 | strategy: 11 | matrix: 12 | rust: 13 | - stable 14 | - beta 15 | steps: 16 | - uses: actions/checkout@v2 17 | - uses: actions-rs/toolchain@v1 18 | with: 19 | profile: minimal 20 | toolchain: ${{ matrix.rust }} 21 | override: true 22 | - uses: actions-rs/cargo@v1 23 | with: 24 | command: test 25 | args: --all --all-features 26 | - uses: actions-rs/cargo@v1 27 | with: 28 | command: test 29 | # Test no_std support 30 | args: -p rmp --no-default-features 31 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | Cargo.lock 2 | target 3 | .idea 4 | -------------------------------------------------------------------------------- /.rustfmt.toml: -------------------------------------------------------------------------------- 1 | # Rustfmt makes too many mistakes to be applied unconditionally to the whole code. 2 | # Please don't apply rustfmt to code in this project. Disable rustfmt in your editor. 3 | disable_all_formatting = true 4 | ignore = ["/"] 5 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | resolver = "2" 3 | members = [ 4 | "rmp", 5 | "rmp-serde", 6 | "rmpv", 7 | "rmpv-tests" 8 | ] 9 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Evgeny Safronov 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # RMP - Rust MessagePack 2 | 3 | RMP is a complete pure-Rust [MessagePack](http://msgpack.org) implementation. MessagePack a compact self-describing binary serialization format. 4 | 5 | This project consists of three crates: 6 | 7 | * [RMP-Serde][crates-rmps-url] ([Documentation][rmps-docs-url]) — easy serializing/deserializing via [Serde](https://serde.rs). 8 | * [RMP-Value][crates-rmpv-url] ([Documentation][rmpv-docs-url]) — a universal `Value` enum that can hold any MessagePack type. Allows deserializing arbitrary messages without a known schema. 9 | * [RMP][crates-rmp-url] ([Documentation][rmp-docs-url]) — low-level functions for reading/writing encoded data. 10 | 11 | ## Features 12 | 13 | - **Convenient and powerful APIs** 14 | 15 | RMP is designed to be lightweight and straightforward. There is a high-level API with support for Serde, 16 | which provides you convenient interface for encode/decode Rust's data structures using `derive` attribute. 17 | There are also low-level APIs, which give you full control over data encoding/decoding process, 18 | with no-std support and without heap allocations. 19 | 20 | - **Zero-copy value decoding** 21 | 22 | RMP allows to decode bytes from a buffer in a zero-copy manner. Parsing is implemented in safe Rust. 23 | 24 | - **Robust, stable and tested** 25 | 26 | This project is developed using TDD and CI, so any found bugs will be fixed without breaking 27 | existing functionality. 28 | 29 | ## Why MessagePack? 30 | 31 | It's smaller and much simpler to parse than JSON. The encoded data is self-describing and extensible, without using any schema definitions. It supports the same data types as JSON, plus binary data, non-string map keys, all float values, and 64-bit numbers. Msgpack values use `` encoding, so they can be safely concatenated and read from a stream. 32 | 33 | MessagePack is similar to CBOR, but has simpler data types (no bignums, decimal floats, dates, or indefinite-length sets, etc.) 34 | 35 | ## Requirements 36 | 37 | - An up-to-date stable version of [Rust](https://www.rust-lang.org), preferably from [rustup](https://rustup.rs). 38 | 39 | [rustc-serialize]: https://github.com/rust-lang-nursery/rustc-serialize 40 | [serde]: https://github.com/serde-rs/serde 41 | 42 | [ci-img]: https://github.com/3Hren/msgpack-rust/actions/workflows/ci.yml/badge.svg 43 | [ci-url]: https://github.com/3Hren/msgpack-rust/actions/workflows/ci.yml 44 | 45 | [coveralls-img]: https://coveralls.io/repos/3Hren/msgpack-rust/badge.svg?branch=master&service=github 46 | [coveralls-url]: https://coveralls.io/github/3Hren/msgpack-rust?branch=master 47 | 48 | [rmp-docs-url]: https://docs.rs/rmp 49 | [rmps-docs-url]: https://docs.rs/rmp-serde 50 | [rmpv-docs-url]: https://docs.rs/rmpv 51 | 52 | [crates-rmp-url]: https://lib.rs/crates/rmp 53 | [crates-rmps-url]: https://lib.rs/crates/rmp-serde 54 | [crates-rmpv-url]: https://lib.rs/crates/rmpv 55 | 56 | 57 | [![Build][ci-img]][ci-url] [![Coverage Status][coveralls-img]][coveralls-url] 58 | -------------------------------------------------------------------------------- /rmp-serde/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | All notable changes to this project will be documented in this file. 3 | This project adheres to [Semantic Versioning](http://semver.org/). 4 | 5 | ## [Unreleased][unreleased] 6 | ### Added: 7 | - Generic `decode::from_read_ref` function that allows to deserialize a borrowed byte-array into the specified type. 8 | - Add `Ext` trait for `Serializer` that allows to wrap a serializer with another one, that overrides exactly one serialization policy. For example using `with_struct_map` method it is possible to serialize structs as a MessagePack map with field names, overriding default serialization policy, which emits structs as a tuple. 9 | - Add `UnderlyingWrite` trait for `Serializer` and its wrappers to be able to obtain the underlying writer. 10 | - Add missing `Debug` implementations. 11 | - More `decode::Error` conversions. 12 | - Support for serializing and deserializing 128-bit values in serde. 13 | - Support for serializing sequences and maps with unknown length, that enables the use of `#[serde(flatten)]` attribute (#196). 14 | - Depth limit is now enforced for `Deserializer`. 15 | 16 | ### Changed: 17 | - (Breaking) Serialize newtype structs by serializing its inner type without wrapping into a tuple. 18 | - (Breaking) Enums are now encoded as a map `{tag: data}` rather than as a list `[tag, data]`. (#149) 19 | - Function `encode::to_vec_named` now accepts unsized values. 20 | - Renamed `decode::Read` trait to `decode::ReadSlice` to avoid clashing with `std::io::Read` and to specify more precisely what it does. 21 | - Support reading encoded integers as floats when safe (#204) 22 | 23 | ### Removed: 24 | - Type parameter `VariantWriter` is no longer a type member of `Serializer`. Instead a `Serializer` can be wrapped by another serializer using `with_struct_map`, `with_struct_tuple` etc. methods. 25 | 26 | ### Fixed: 27 | - Fix error decoding `Some(enum)` (#185) 28 | - Fix error decoding unit structs which were encoded as `[]` (#181) 29 | - Fix `Display` implementations for errors not including all relevant information (#199) 30 | - Fix deserialization of nested `Option`s (#245) 31 | 32 | ## 0.13.7 - 2017-09-13 33 | ### Changed: 34 | - `Raw` and `RawRef` are now serializable. 35 | - Allow to construct `Raw` and `RawRef` from string or from a byte array. 36 | 37 | ## 0.13.6 - 2017-08-04 38 | ### Added: 39 | - Serialize struct as a map (#140). 40 | 41 | ## 0.13.5 - 2017-07-21 42 | ### Changed 43 | - Switch to using `char::encode_utf8`. 44 | In Rust 1.15, the function `char::encode_utf8` was stabilized. Assuming that `rmp` follows the `serde` standard of supporting the last 3 stable releases, this function is now safe to use. I believe this removes the last allocation required on the serialization path. 45 | 46 | ## 0.13.4 - 2017-07-11 47 | ### Fixed 48 | - Fixed build on nightly rustc (#135). 49 | 50 | ## 0.13.3 - 2017-05-27 51 | ### Fixed 52 | - Fixed build on nightly rustc (#131). 53 | 54 | ## 0.13.2 - 2017-04-30 55 | ### Changed 56 | - Fixed `rmp_serde::decode::from_read` signature by marking that it can only deserialize into `DeserializeOwned`. The previous signature let try to deserialize, for example `&str` and other borrow types and it failed at runtime instead of catching it at compile time. 57 | 58 | ## 0.13.1 - 2017-04-25 59 | ### Added 60 | - Add helper `RawRef` struct that allows to deserialize borrowed strings even if they contain invalid UTF-8. This can be when deserializing frames from older MessagePack spec. 61 | 62 | ## 0.13.0 - 2017-04-24 63 | ### Added 64 | - Zero-copy deserialization from `&[u8]`. 65 | 66 | ### Changed 67 | - Adapt with serde 1.0. 68 | 69 | ## 0.12.4 - 2017-03-26 70 | ### Fixed 71 | - Fix compilation on rustc 1.13. 72 | 73 | ## 0.12.3 - 2017-03-26 74 | ### Added 75 | - Add helper `Raw` struct that allows to deserialize strings even if they contain invalid UTF-8. This can be when deserializing frames from older MessagePack spec. 76 | - Serializer can now return back its underlying writer by reference, mutable reference and by value. 77 | 78 | ## 0.12.2 - 2017-02-17 79 | ### Added 80 | - Added `write`, `to_vec` and `from_read` functions to reduce boilerplate for serializing and deserializing custom types that implement `Serialize` or `Deserialize`. 81 | 82 | ## 0.12.1 - 2017-02-11 83 | ### Added 84 | - Allow `Deserializer` to return number of bytes read in case of using Cursor as an underlying reader. 85 | 86 | ## 0.12.0 - 2017-02-08 87 | ### Changed 88 | - Adapt with serde 0.9. 89 | 90 | ## 0.11.0 - 2017-01-05 91 | ### Changed 92 | - Adapt with RMP core 0.8. 93 | - The `Serializer` now encodes integers using the most effective representation. 94 | - The `Deserializer` now properly decodes integer values that fit in the expected type. 95 | - Default stack protector depth is now 1024 instead of 1000. 96 | - Internal buffer in the `Deserializer` now have some capacity preallocated. 97 | 98 | ## 0.10.0 - 2016-10-06 99 | ### Changed 100 | - Update serde dependency to 0.8. 101 | 102 | ## 0.9.6 - 2016-08-05 103 | ### Fixed 104 | - Switch unit structs to using the same serialization mechanism as other structs (#76). 105 | 106 | ## 0.9.5 - 2016-07-28 107 | ### Added 108 | - Added a wrapper over `rmp::Value` to be able to serialize it. 109 | 110 | ## 0.9.4 - 2016-07-11 111 | ### Fixed 112 | - Reading binary should no longer trigger unexpected EOF error on valid read. 113 | 114 | ## 0.9.3 - 2016-07-11 115 | ### Changed 116 | - Reuse deserializer buffer on every read for string and binary deserialization without unnecessary intermediate buffer creation. 117 | This change increases the string and binary deserialization performance (many thanks to Fedor Gogolev ). 118 | 119 | ## 0.9.2 - 2016-07-03 120 | ### Added 121 | - Implement `size_hint()` function for `SeqVisitor` and `MapVisitor`, so it can be possible to preallocate things, increasing the performance greatly. 122 | 123 | ## 0.9.1 - 2016-06-24 124 | ### Fixed 125 | - Serializer should no longer panic with unimplemented error on struct variant serialization ([#64]). 126 | 127 | ## 0.9.0 - 2016-03-28 128 | ### Changed 129 | - Adapt code to be compilable with Serde v0.7. 130 | 131 | ## 0.8.2 - 2015-11-10 132 | ### Changed 133 | - Fixed stack overflow when unpacking recursive data structures. 134 | 135 | ## 0.8.1 - 2015-10-03 136 | ### Changed 137 | - Upper limit for serde version. 138 | 139 | ### Fixed 140 | - Use the most effective int encoding 141 | Even if the value is explicitly marked as i64 it must be encoded using 142 | the most effective bytes representation despite of signed it or 143 | unsigned. 144 | 145 | ## 0.8.0 - 2015-09-11 146 | ### Changed 147 | - Serializer can now be extended with custom struct encoding policy. 148 | - Improved error types and its messages for serialization part. 149 | - New error type introduced - UnknownLength. Returned on attempt to serialize struct, map or serquence with unknown 150 | length (Serde allows this). 151 | - The new type is returned if necessary. 152 | 153 | ### Fixed 154 | - Deserializer now properly works with enums. 155 | - Options with default values (that can be initialized using unit marker) deserialization. 156 | This fix also forbids the following Option deserialization cases: 157 | - Option<()>. 158 | - Option>. 159 | It's impossible to properly deserialize the listed cases without explicit option marker in protocol. 160 | - Serializer now properly serializes unit structs. 161 | Previously it was serialized as a unit (nil), now there is just an empty array ([]). 162 | 163 | [#64]: (https://github.com/3Hren/msgpack-rust/pull/64) 164 | [#76]: (https://github.com/3Hren/msgpack-rust/pull/76) 165 | -------------------------------------------------------------------------------- /rmp-serde/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "rmp-serde" 3 | version = "1.3.0" 4 | authors = ["Evgeny Safronov "] 5 | license = "MIT" 6 | description = "Serde bindings for RMP" 7 | repository = "https://github.com/3Hren/msgpack-rust" 8 | documentation = "https://docs.rs/rmp-serde" 9 | readme = "README.md" 10 | keywords = ["msgpack", "MessagePack", "serde", "serialization"] 11 | categories = ["encoding"] 12 | edition = "2021" 13 | 14 | [package.metadata.release] 15 | tag-prefix = "{{crate_name}}/" 16 | 17 | [dependencies] 18 | byteorder = "1.4.3" 19 | serde = "1.0.197" 20 | rmp = { version = "0.8.14", path = "../rmp" } 21 | 22 | [dev-dependencies] 23 | rmpv = { path = "../rmpv" } 24 | serde_bytes = "0.11.5" 25 | serde = { version = "1.0.197", features = ["derive"] } 26 | 27 | [badges] 28 | maintenance = { status = "looking-for-maintainer" } 29 | -------------------------------------------------------------------------------- /rmp-serde/LICENSE: -------------------------------------------------------------------------------- 1 | ../LICENSE -------------------------------------------------------------------------------- /rmp-serde/README.md: -------------------------------------------------------------------------------- 1 | # MessagePack + Serde 2 | 3 | This crate connects Rust MessagePack library with [`serde`][serde] providing an ability to 4 | easily serialize and deserialize both Rust built-in types, the standard library and custom data 5 | structures. 6 | 7 | ## Motivating example 8 | 9 | ```rust 10 | let buf = rmp_serde::to_vec(&(42, "the Answer")).unwrap(); 11 | 12 | assert_eq!( 13 | vec![0x92, 0x2a, 0xaa, 0x74, 0x68, 0x65, 0x20, 0x41, 0x6e, 0x73, 0x77, 0x65, 0x72], 14 | buf 15 | ); 16 | 17 | assert_eq!((42, "the Answer"), rmp_serde::from_slice(&buf).unwrap()); 18 | ``` 19 | 20 | ## Type-based Serialization and Deserialization 21 | 22 | Serde provides a mechanism for low boilerplate serialization & deserialization of values to and 23 | from MessagePack via the serialization API. 24 | 25 | To be able to serialize a piece of data, it must implement the `serde::Serialize` trait. To be 26 | able to deserialize a piece of data, it must implement the `serde::Deserialize` trait. Serde 27 | provides an annotation to automatically generate the code for these 28 | traits: `#[derive(Serialize, Deserialize)]`. 29 | 30 | ## Examples 31 | 32 | ```rust 33 | use std::collections::HashMap; 34 | use serde::{Deserialize, Serialize}; 35 | use rmp_serde::{Deserializer, Serializer}; 36 | 37 | #[derive(Debug, PartialEq, Deserialize, Serialize)] 38 | struct Human { 39 | age: u32, 40 | name: String, 41 | } 42 | 43 | fn main() { 44 | let mut buf = Vec::new(); 45 | let val = Human { 46 | age: 42, 47 | name: "John".into(), 48 | }; 49 | 50 | val.serialize(&mut Serializer::new(&mut buf)).unwrap(); 51 | } 52 | ``` 53 | 54 | ## Efficient storage of `&[u8]` types 55 | 56 | MessagePack can efficiently store binary data. However, Serde's standard derived implementations *do not* use binary representations by default. Serde prefers to represent types like `&[u8; N]` or `Vec` as arrays of objects of arbitrary/unknown type, and not as slices of bytes. This creates about a 50% overhead in storage size. 57 | 58 | Wrap your data in [`serde_bytes`](https://lib.rs/crates/serde_bytes) to store blobs quickly and efficiently. Alternatively, [configure an override in `rmp_serde` to force use of byte slices](https://docs.rs/rmp-serde/latest/rmp_serde/encode/struct.Serializer.html#method.with_bytes). 59 | 60 | [serde]: https://serde.rs/ 61 | -------------------------------------------------------------------------------- /rmp-serde/benches/buf.rs: -------------------------------------------------------------------------------- 1 | #![feature(test)] 2 | 3 | extern crate test; 4 | 5 | use serde::{Deserialize, Serialize}; 6 | 7 | use test::Bencher; 8 | 9 | #[bench] 10 | fn bench_strings_1000(bencher: &mut Bencher) { 11 | bench_strings(bencher, 1000); 12 | } 13 | 14 | #[bench] 15 | fn bench_strings_5000(bencher: &mut Bencher) { 16 | bench_strings(bencher, 5000); 17 | } 18 | 19 | #[bench] 20 | fn bench_strings_10000(bencher: &mut Bencher) { 21 | bench_strings(bencher, 10000); 22 | } 23 | 24 | fn bench_strings(bencher: &mut Bencher, size: usize) { 25 | let vec: Vec = ::std::iter::repeat("abcdefghijklmnopqrstuvwxyz".into()) 26 | .take(size) 27 | .collect(); 28 | 29 | let mut buf = Vec::new(); 30 | vec.serialize(&mut rmp_serde::Serializer::new(&mut buf)).unwrap(); 31 | 32 | bencher.iter(|| { 33 | >::deserialize(&mut rmp_serde::Deserializer::new(&buf[..])).unwrap(); 34 | }); 35 | } 36 | -------------------------------------------------------------------------------- /rmp-serde/src/bytes.rs: -------------------------------------------------------------------------------- 1 | //! Hacky serializer that only allows `u8` 2 | 3 | use serde::ser::Impossible; 4 | use serde::Serialize; 5 | use std::fmt; 6 | 7 | pub(crate) struct OnlyBytes; 8 | pub(crate) struct Nope; 9 | 10 | impl std::error::Error for Nope { 11 | } 12 | 13 | impl std::fmt::Display for Nope { 14 | fn fmt(&self, _: &mut fmt::Formatter<'_>) -> fmt::Result { 15 | Ok(()) 16 | } 17 | } 18 | 19 | impl std::fmt::Debug for Nope { 20 | fn fmt(&self, _: &mut fmt::Formatter<'_>) -> fmt::Result { 21 | Ok(()) 22 | } 23 | } 24 | 25 | impl serde::ser::Error for Nope { 26 | fn custom(_: T) -> Self { 27 | Self 28 | } 29 | } 30 | 31 | impl serde::de::Error for Nope { 32 | fn custom(_: T) -> Self { 33 | Self 34 | } 35 | } 36 | 37 | impl serde::Serializer for OnlyBytes { 38 | type Ok = u8; 39 | type Error = Nope; 40 | type SerializeSeq = Impossible; 41 | type SerializeTuple = Impossible; 42 | type SerializeTupleStruct = Impossible; 43 | type SerializeTupleVariant = Impossible; 44 | type SerializeMap = Impossible; 45 | type SerializeStruct = Impossible; 46 | type SerializeStructVariant = Impossible; 47 | 48 | fn serialize_u8(self, val: u8) -> Result { 49 | Ok(val) 50 | } 51 | 52 | fn serialize_bool(self, _: bool) -> Result { 53 | Err(Nope) 54 | } 55 | 56 | fn serialize_i8(self, _: i8) -> Result { 57 | Err(Nope) 58 | } 59 | 60 | fn serialize_i16(self, _: i16) -> Result { 61 | Err(Nope) 62 | } 63 | 64 | fn serialize_i32(self, _: i32) -> Result { 65 | Err(Nope) 66 | } 67 | 68 | fn serialize_i64(self, _: i64) -> Result { 69 | Err(Nope) 70 | } 71 | 72 | fn serialize_u16(self, _: u16) -> Result { 73 | Err(Nope) 74 | } 75 | 76 | fn serialize_u32(self, _: u32) -> Result { 77 | Err(Nope) 78 | } 79 | 80 | fn serialize_u64(self, _: u64) -> Result { 81 | Err(Nope) 82 | } 83 | 84 | fn serialize_f32(self, _: f32) -> Result { 85 | Err(Nope) 86 | } 87 | 88 | fn serialize_f64(self, _: f64) -> Result { 89 | Err(Nope) 90 | } 91 | 92 | fn serialize_char(self, _: char) -> Result { 93 | Err(Nope) 94 | } 95 | 96 | fn serialize_str(self, _: &str) -> Result { 97 | Err(Nope) 98 | } 99 | 100 | fn serialize_bytes(self, _: &[u8]) -> Result { 101 | Err(Nope) 102 | } 103 | 104 | fn serialize_none(self) -> Result { 105 | Err(Nope) 106 | } 107 | 108 | fn serialize_some(self, _: &T) -> Result where T: Serialize { 109 | Err(Nope) 110 | } 111 | 112 | fn serialize_unit(self) -> Result { 113 | Err(Nope) 114 | } 115 | 116 | fn serialize_unit_struct(self, _: &'static str) -> Result { 117 | Err(Nope) 118 | } 119 | 120 | fn serialize_unit_variant(self, _: &'static str, _: u32, _: &'static str) -> Result { 121 | Err(Nope) 122 | } 123 | 124 | fn serialize_newtype_struct(self, _: &'static str, _: &T) -> Result where T: Serialize { 125 | Err(Nope) 126 | } 127 | 128 | fn serialize_newtype_variant(self, _: &'static str, _: u32, _: &'static str, _: &T) -> Result where T: Serialize { 129 | Err(Nope) 130 | } 131 | 132 | fn serialize_seq(self, _: Option) -> Result { 133 | Err(Nope) 134 | } 135 | 136 | fn serialize_tuple(self, _: usize) -> Result { 137 | Err(Nope) 138 | } 139 | 140 | fn serialize_tuple_struct(self, _: &'static str, _: usize) -> Result { 141 | Err(Nope) 142 | } 143 | 144 | fn serialize_tuple_variant(self, _: &'static str, _: u32, _: &'static str, _: usize) -> Result { 145 | Err(Nope) 146 | } 147 | 148 | fn serialize_map(self, _: Option) -> Result { 149 | Err(Nope) 150 | } 151 | 152 | fn serialize_struct(self, _: &'static str, _: usize) -> Result { 153 | Err(Nope) 154 | } 155 | 156 | fn serialize_struct_variant(self, _: &'static str, _: u32, _: &'static str, _: usize) -> Result { 157 | Err(Nope) 158 | } 159 | 160 | fn collect_seq(self, _: I) -> Result where I: IntoIterator, ::Item: Serialize { 161 | Err(Nope) 162 | } 163 | 164 | fn collect_map(self, _: I) -> Result where K: Serialize, V: Serialize, I: IntoIterator { 165 | Err(Nope) 166 | } 167 | 168 | fn collect_str(self, _: &T) -> Result where T: fmt::Display { 169 | Err(Nope) 170 | } 171 | } 172 | -------------------------------------------------------------------------------- /rmp-serde/src/config.rs: -------------------------------------------------------------------------------- 1 | //! Change MessagePack behavior with configuration wrappers. 2 | 3 | /// Represents configuration that dicatates what the serializer does. 4 | /// 5 | /// Implemented as an empty trait depending on a hidden trait in order to allow changing the 6 | /// methods of this trait without breaking backwards compatibility. 7 | pub trait SerializerConfig: sealed::SerializerConfig {} 8 | 9 | impl SerializerConfig for T {} 10 | 11 | pub(crate) mod sealed { 12 | use crate::config::BytesMode; 13 | 14 | /// This is the inner trait - the real `SerializerConfig`. 15 | /// 16 | /// This hack disallows external implementations and usage of `SerializerConfig` and thus 17 | /// allows us to change `SerializerConfig` methods freely without breaking backwards compatibility. 18 | pub trait SerializerConfig: Copy { 19 | /// Determines the value of `Serializer::is_human_readable` and 20 | /// `Deserializer::is_human_readable`. 21 | fn is_human_readable(&self) -> bool; 22 | 23 | /// String struct fields 24 | fn is_named(&self) -> bool; 25 | fn bytes(&self) -> BytesMode; 26 | } 27 | } 28 | 29 | #[derive(Copy, Clone, Debug)] 30 | pub(crate) struct RuntimeConfig { 31 | pub(crate) is_human_readable: bool, 32 | pub(crate) is_named: bool, 33 | pub(crate) bytes: BytesMode, 34 | } 35 | 36 | /// When to encode `[u8]` as `bytes` rather than a sequence 37 | /// of integers. Serde without `serde_bytes` has trouble 38 | /// using `bytes`, and this is hack to force it. It may 39 | /// break some data types. 40 | #[non_exhaustive] 41 | #[derive(Debug, Copy, Clone, Default, PartialEq, Eq)] 42 | pub enum BytesMode { 43 | /// Use bytes only when Serde requires it 44 | /// (typically only when `serde_bytes` is used) 45 | #[default] 46 | Normal, 47 | /// Use bytes for slices, `Vec`, and a few other types that 48 | /// use `Iterator` in Serde. 49 | /// 50 | /// This may break some implementations of `Deserialize`. 51 | /// 52 | /// This does not include fixed-length arrays. 53 | ForceIterables, 54 | /// Use bytes for everything that looks like a container of `u8`. 55 | /// This breaks some implementations of `Deserialize`. 56 | ForceAll, 57 | } 58 | 59 | impl RuntimeConfig { 60 | pub(crate) fn new(other: impl sealed::SerializerConfig) -> Self { 61 | Self { 62 | is_human_readable: other.is_human_readable(), 63 | is_named: other.is_named(), 64 | bytes: other.bytes(), 65 | } 66 | } 67 | } 68 | 69 | impl sealed::SerializerConfig for RuntimeConfig { 70 | #[inline] 71 | fn is_human_readable(&self) -> bool { 72 | self.is_human_readable 73 | } 74 | 75 | #[inline] 76 | fn is_named(&self) -> bool { 77 | self.is_named 78 | } 79 | 80 | #[inline] 81 | fn bytes(&self) -> BytesMode { 82 | self.bytes 83 | } 84 | } 85 | 86 | /// The default serializer/deserializer configuration. 87 | /// 88 | /// This configuration: 89 | /// - Writes structs as a tuple, without field names 90 | /// - Writes enum variants as integers 91 | /// - Writes and reads types as binary, not human-readable 92 | // 93 | /// This is the most compact representation. 94 | #[derive(Copy, Clone, Debug)] 95 | pub struct DefaultConfig; 96 | 97 | impl sealed::SerializerConfig for DefaultConfig { 98 | #[inline(always)] 99 | fn is_named(&self) -> bool { 100 | false 101 | } 102 | 103 | #[inline(always)] 104 | fn is_human_readable(&self) -> bool { 105 | false 106 | } 107 | 108 | #[inline(always)] 109 | fn bytes(&self) -> BytesMode { 110 | BytesMode::default() 111 | } 112 | } 113 | 114 | /// Config wrapper, that overrides struct serialization by packing as a map with field names. 115 | /// 116 | /// MessagePack specification does not tell how to serialize structs. This trait allows you to 117 | /// extend serialization to match your app's requirements. 118 | /// 119 | /// Default `Serializer` implementation writes structs as a tuple, i.e. only its length is encoded, 120 | /// because it is the most compact representation. 121 | #[derive(Copy, Clone, Debug)] 122 | pub struct StructMapConfig(C); 123 | 124 | impl StructMapConfig { 125 | /// Creates a `StructMapConfig` inheriting unchanged configuration options from the given configuration. 126 | #[inline] 127 | pub const fn new(inner: C) -> Self { 128 | Self(inner) 129 | } 130 | } 131 | 132 | impl sealed::SerializerConfig for StructMapConfig 133 | where 134 | C: sealed::SerializerConfig, 135 | { 136 | #[inline(always)] 137 | fn is_named(&self) -> bool { 138 | true 139 | } 140 | 141 | #[inline(always)] 142 | fn is_human_readable(&self) -> bool { 143 | self.0.is_human_readable() 144 | } 145 | 146 | fn bytes(&self) -> BytesMode { 147 | self.0.bytes() 148 | } 149 | } 150 | 151 | /// Config wrapper that overrides struct serlization by packing as a tuple without field 152 | /// names. 153 | #[derive(Copy, Clone, Debug)] 154 | pub struct StructTupleConfig(C); 155 | 156 | impl StructTupleConfig { 157 | /// Creates a `StructTupleConfig` inheriting unchanged configuration options from the given configuration. 158 | #[inline] 159 | pub const fn new(inner: C) -> Self { 160 | Self(inner) 161 | } 162 | } 163 | 164 | impl sealed::SerializerConfig for StructTupleConfig 165 | where 166 | C: sealed::SerializerConfig, 167 | { 168 | #[inline(always)] 169 | fn is_named(&self) -> bool { 170 | false 171 | } 172 | 173 | #[inline(always)] 174 | fn is_human_readable(&self) -> bool { 175 | self.0.is_human_readable() 176 | } 177 | 178 | fn bytes(&self) -> BytesMode { 179 | self.0.bytes() 180 | } 181 | } 182 | 183 | /// Config wrapper that overrides `Serializer::is_human_readable` and 184 | /// `Deserializer::is_human_readable` to return `true`. 185 | #[derive(Copy, Clone, Debug)] 186 | pub struct HumanReadableConfig(C); 187 | 188 | impl HumanReadableConfig { 189 | /// Creates a `HumanReadableConfig` inheriting unchanged configuration options from the given configuration. 190 | #[inline] 191 | pub const fn new(inner: C) -> Self { 192 | Self(inner) 193 | } 194 | } 195 | 196 | impl sealed::SerializerConfig for HumanReadableConfig 197 | where 198 | C: sealed::SerializerConfig, 199 | { 200 | #[inline(always)] 201 | fn is_named(&self) -> bool { 202 | self.0.is_named() 203 | } 204 | 205 | #[inline(always)] 206 | fn is_human_readable(&self) -> bool { 207 | true 208 | } 209 | 210 | fn bytes(&self) -> BytesMode { 211 | self.0.bytes() 212 | } 213 | } 214 | 215 | /// Config wrapper that overrides `Serializer::is_human_readable` and 216 | /// `Deserializer::is_human_readable` to return `false`. 217 | #[derive(Copy, Clone, Debug)] 218 | pub struct BinaryConfig(C); 219 | 220 | impl BinaryConfig { 221 | /// Creates a `BinaryConfig` inheriting unchanged configuration options from the given configuration. 222 | #[inline(always)] 223 | pub const fn new(inner: C) -> Self { 224 | Self(inner) 225 | } 226 | } 227 | 228 | impl sealed::SerializerConfig for BinaryConfig 229 | where 230 | C: sealed::SerializerConfig, 231 | { 232 | #[inline(always)] 233 | fn is_named(&self) -> bool { 234 | self.0.is_named() 235 | } 236 | 237 | #[inline(always)] 238 | fn is_human_readable(&self) -> bool { 239 | false 240 | } 241 | 242 | fn bytes(&self) -> BytesMode { 243 | self.0.bytes() 244 | } 245 | } 246 | -------------------------------------------------------------------------------- /rmp/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | All notable changes to this project will be documented in this file. 3 | This project adheres to [Semantic Versioning](http://semver.org/). 4 | 5 | ## Unreleased (0.8.11) 6 | ### Added 7 | - Implemeneted support for `#![no_std]` in `rmpv` 8 | - Adds new `feature="std"` (on by default) 9 | - Introduces new `RmpRead` and `RmpWrite` traits. 10 | - Needed because `std::io::Read` (and Write) are missing on `#![no_std]` 11 | - Introduces new `Bytes` and `ByteBuf` wrappers, that implement RmpRead/RmpWrite for no\_std targets. 12 | 13 | ## 0.8.6 - 2017-04-23 14 | ### Added 15 | - New `rmp::decode::read_str_from_slice` function for zero-copy reading strings from slices. 16 | 17 | ### Changed 18 | - Deprecate `rmp::decode::read_str_ref`, because it's useless and inconvenient. 19 | 20 | ## 0.8.5 - 2017-03-13 21 | ### Fixed 22 | - Fix compilation on rustc 1.13.0. 23 | 24 | ## 0.8.4 - 2017-03-09 25 | ### Added 26 | - Derive `Debug` for `MarkerReadError`. 27 | 28 | ## 0.8.3 - 2017-03-04 29 | ### Fixed 30 | - Fixed `write_sint`, so it should mark positive values as unsigned integers. 31 | Before this change it marked signed integers larger than `4294967296` with I64 marker, which is not consistent with other MessagePack implementations. 32 | Now it should mark such integers with U64 marker. 33 | 34 | ## 0.8.2 - 2017-02-01 35 | ### Added 36 | - Conversion from `ValueWriteError` into I/O error. 37 | 38 | ## 0.8.1 - 2017-01-05 39 | ### Changed 40 | - Fixed docs link. 41 | 42 | ## 0.8.0 - 2017-01-05 43 | ### Added 44 | - Marker now implements `From` and `Into` traits for `u8`. 45 | - 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. 46 | - Add `NumValueReadError` enum with additional `OutOfRange` variant to be able to detect whether integer decoding failed because of out of range. 47 | 48 | ### Changed 49 | - Update `byteorder` dependency to 1.0. 50 | - Unexpected EOF variant has been merged with the default one in the I/O Error enum. 51 | - Function `write_sint` now encodes 64-bit signed integers using the most compact representation. 52 | - Function `write_uint` now encodes 64-bit unsigned integers using the most compact representation. 53 | - Rename `read_array_size` function to `read_array_len` for consistency. 54 | - Rename `read_map_size` function to `read_map_len` for consistency. 55 | - Make `FixedValueWriteError` struct private. All functions, that previously returned such kind of error now return the Standard I/O error. 56 | 57 | ### Removed 58 | - Move `Value` and `ValueRef` enums and associated functions into the separate `rmpv` crate. 59 | - Remove conversions from `byteorder` crate errors, because since 0.5 there are no such errors. 60 | - Remove `write_sint_eff` function - its functionality can now be done using `write_sint` instead. 61 | - Remove `write_uint_eff` function - its functionality can now be done using `write_uint` instead. 62 | - 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. 63 | - Remove `read_bin_borrow` function. 64 | 65 | ## 0.7.5 - 2016-07-24 66 | ### Added 67 | - Add `is_*` methods for Value for checking its underlying value without explicit matching. 68 | - Add `as_*` methods for Value for borrowing its underlying value. 69 | - Value is now indexable by integer. 70 | 71 | ## 0.7.4 - 2016-07-18 72 | ### Added 73 | - Value now can be initialized from primitive values using From trait. 74 | 75 | ## 0.7.3 - 2015-09-23 76 | ### Changed 77 | - Restricted upper version limit for dependencies. 78 | 79 | ## 0.7.2 - 2015-09-23 80 | ### Added 81 | - Implemented `Display` trait for `Value`. 82 | 83 | ## 0.7.1 - 2015-09-11 84 | ### Changed 85 | - Use `to_owned` instead of `to_string` while converting `ValueRef` into `Value`. 86 | 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`. 87 | 88 | ## 0.7.0 - 2015-08-24 89 | ### Changed 90 | - The big single crate has been refactored, which results in three crates: `rmp`, `rmp-serialize` and `rmp-serde`. 91 | 92 | ## 0.6.0 - 2015-08-17 93 | ### Added 94 | - Initial support for [Serde](https://github.com/serde-rs/serde) serializer and deserializer. 95 | - Efficient bytes serialization with Serde. 96 | - Efficient binaries deserialization with Serde using `ByteBuf`. 97 | - Rust serialize Decoder now can provide the underlying reader both by reference or by value, destroying itself in the last case. 98 | 99 | ### Changed 100 | - Update well-formness for `BigEndianRead` trait to be implemented only for sized types. 101 | - Renamed `PositiveFixnum` marker to `FixPos`. 102 | - Renamed `NegativeFixnum` marker to `FixNeg`. 103 | - Renamed `FixedString` marker to `FixStr`. 104 | - Renamed `FixedArray` marker to `FixArray`. 105 | - Renamed `FixedMap` to `FixMap`. 106 | - Minor documentation updates and markdown fixes. 107 | 108 | ## 0.5.1 - 2015-08-10 109 | ### Changed 110 | - Now the `rustc_serialize::Encoder` should encode signed integers using the most effective underlying representation. 111 | - Now the `rustc_serialize::Decoder` should properly map integers to the result type if the decoded value fits in 112 | result type's range. 113 | 114 | ## 0.5.0 - 2015-08-01 115 | ### Added 116 | - New `ValueRef` value struct represents MessagePack'ed value, but unlike an owning `Value` it owns nothing except its 117 | structure. It means that all strings and binaries it contains are borrowed from the byte array from which the value 118 | was created. 119 | - New `BorrowRead` trait, which looks like a standard `BufRead` but unlike the standard this has an explicit internal 120 | buffer lifetime, which allows to borrow from underlying buffer while mutating the type. 121 | - Encoding function for `ValueRef` with its own error category. 122 | - Decoding function for `ValueRef` with its own error category. 123 | - Conversion method from `ValueRef` to `Value`. 124 | - More benchmarks and tests. 125 | 126 | ### Changed 127 | - Derive `Copy` trait for `Integer` and `Float` enums. 128 | 129 | ## 0.4.0 - 2015-07-17 130 | ### Added 131 | - Low level `write_str` function allows to serialize the UTF-8 encoded strings the most efficient way. 132 | - Low level `write_bin` function allows to serialize the binary array the most efficient way. 133 | - Implemented `std::error::Error` trait for error types. 134 | 135 | ## 0.3.2 - 2015-07-05 136 | ### Changed 137 | - Encoder now should return proper error types. 138 | 139 | ## 0.3.1 - 2015-06-28 140 | ### Changed 141 | - Stabilizing enum serialization/deserialization. Now every enum is serialized as [int, [args...]]. 142 | - Suppressed some warnings appeared on updated compiler. 143 | 144 | ## 0.3.0 - 2015-06-25 145 | ### Added 146 | - Enum serialization/deserialization. 147 | 148 | ## 0.2.2 - 2015-06-15 149 | ### Changed 150 | - Minor integer decoding performance tweaking. 151 | 152 | ## 0.2.1 - 2015-05-30 153 | ### Added 154 | - Benchmarking module. 155 | 156 | ### Changed 157 | - Increased string decoding performance by ~30 times. 158 | - Exported `read_value` function to the `rmp::decode` module. 159 | - Exported `Value` struct to the root crate namespace. 160 | 161 | ## 0.2.0 - 2015-05-27 162 | ### Added 163 | - Introducing a `Value` algebraic data type, which represents an owning MessagePack object. It can 164 | be found in `rmp::value` module. 165 | - The Value ADT encoding and decoding functions. 166 | - Low-level ext type decoders. 167 | 168 | ## 0.1.1 - 2015-05-18 169 | ### Changed 170 | - Added documentation and repository site in Cargo.toml. 171 | - Added keywords to ease searching using crates.io. 172 | 173 | ## 0.1.0 - 2015-05-15 174 | ### Added 175 | - Initial commit. 176 | - This CHANGELOG file to hopefully serve as an evolving example of a standardized open source 177 | project CHANGELOG. 178 | -------------------------------------------------------------------------------- /rmp/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "rmp" 3 | version = "0.8.14" 4 | authors = ["Evgeny Safronov ", "Kornel "] 5 | license = "MIT" 6 | description = "Pure Rust MessagePack serialization implementation" 7 | repository = "https://github.com/3Hren/msgpack-rust" 8 | documentation = "https://docs.rs/rmp" 9 | readme = "README.md" 10 | keywords = ["msgpack", "MessagePack"] 11 | categories = ["encoding"] 12 | edition = "2021" 13 | 14 | [dependencies] 15 | byteorder = { version = "1.4.2", default-features = false } 16 | num-traits = { version = "0.2.14", default-features = false } 17 | # This is macro_only ;) 18 | paste = "1.0" 19 | 20 | [features] 21 | default = ["std"] 22 | std = ["byteorder/std", "num-traits/std"] 23 | 24 | [[example]] 25 | name = "inspect" 26 | required-features = ["std"] 27 | 28 | [dev-dependencies] 29 | quickcheck = "1.0.2" 30 | 31 | [package.metadata.release] 32 | tag-prefix = "{{crate_name}}/" 33 | 34 | [badges] 35 | maintenance = { status = "looking-for-maintainer" } 36 | -------------------------------------------------------------------------------- /rmp/LICENSE: -------------------------------------------------------------------------------- 1 | ../LICENSE -------------------------------------------------------------------------------- /rmp/README.md: -------------------------------------------------------------------------------- 1 | ## The Rust MessagePack Library 2 | 3 | RMP is a pure Rust [MessagePack](http://msgpack.org) implementation of an efficient binary 4 | serialization format. This crate provides low-level core functionality, writers and readers for 5 | primitive values with direct mapping between binary MessagePack format. 6 | 7 | [Looking for Serde support](https://lib.rs/crates/rmp-serde)? 8 | 9 | This crate represents the very basic functionality needed to work with MessagePack format. 10 | Ideologically it is developed as a basis for building high-level abstractions. 11 | 12 | ### Usage 13 | 14 | To use `rmp`, first add this to your `Cargo.toml`: 15 | 16 | ```toml 17 | [dependencies.rmp] 18 | rmp = "0.8" 19 | ``` 20 | 21 | ### Features 22 | 23 | - **Low-level API** 24 | 25 | RMP is designed to be lightweight and straightforward. There are low-level APIs, which give you 26 | full control over the encoding/decoding process. `no-std` environments are supported. 27 | 28 | - **Zero-copy value decoding** 29 | 30 | RMP allows to decode bytes from a buffer in a zero-copy manner, without any heap allocations. 31 | easily and blazingly fast. Rust static checks guarantee that the data will be valid until buffer lives. 32 | 33 | - **Clear error handling** 34 | 35 | RMP's error system guarantees that you never receive an error enum with unreachable variant. 36 | 37 | - **Robust and tested** 38 | 39 | This project is developed using TDD and CI, so any found bugs will be fixed without breaking 40 | existing functionality. 41 | 42 | ### Detailed 43 | 44 | Currently there are two large modules: encode and decode. More detail you can find in the 45 | corresponding sections. 46 | 47 | Formally every MessagePack message consists of some marker encapsulating a data type and the 48 | data itself. Sometimes there are no separate data chunk, for example for booleans. In these 49 | cases a marker contains the value. For example, the `true` value is encoded as `0xc3`. 50 | 51 | ```rust 52 | let mut buf = Vec::new(); 53 | rmp::encode::write_bool(&mut buf, true).unwrap(); 54 | 55 | assert_eq!([0xc3], buf[..]); 56 | ``` 57 | 58 | Sometimes a single value can be encoded in multiple ways. For example a value of `42` can be 59 | represented as: `[0x2a], [0xcc, 0x2a], [0xcd, 0x00, 0x2a]` and so on, and all of them are 60 | considered as valid representations. To allow fine-grained control over encoding such values 61 | the library provides direct mapping functions. 62 | 63 | ```rust 64 | let mut bufs = vec![vec![]; 5]; 65 | 66 | rmp::encode::write_pfix(&mut bufs[0], 42).unwrap(); 67 | rmp::encode::write_u8(&mut bufs[1], 42).unwrap(); 68 | rmp::encode::write_u16(&mut bufs[2], 42).unwrap(); 69 | rmp::encode::write_u32(&mut bufs[3], 42).unwrap(); 70 | rmp::encode::write_u64(&mut bufs[4], 42).unwrap(); 71 | 72 | assert_eq!([0x2a], bufs[0][..]); 73 | assert_eq!([0xcc, 0x2a], bufs[1][..]); 74 | assert_eq!([0xcd, 0x00, 0x2a], bufs[2][..]); 75 | assert_eq!([0xce, 0x00, 0x00, 0x00, 0x2a], bufs[3][..]); 76 | assert_eq!([0xcf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2a], bufs[4][..]); 77 | ``` 78 | 79 | But they aren't planned to be widely used. Instead we often need to encode bytes compactly to 80 | save space. In these cases RMP provides functions that guarantee that for encoding the most 81 | compact representation will be chosen. 82 | 83 | ```rust 84 | let mut buf = Vec::new(); 85 | 86 | rmp::encode::write_sint(&mut buf, 300).unwrap(); 87 | 88 | assert_eq!([0xcd, 0x1, 0x2c], buf[..]); 89 | ``` 90 | 91 | On the other hand for deserialization it is not matter in which representation the value is 92 | encoded - RMP deals with all of them. 93 | 94 | Sometimes you know the exact type representation and want to enforce the deserialization process 95 | to make it strongly type safe. 96 | 97 | ```rust 98 | let buf = [0xcd, 0x1, 0x2c]; 99 | 100 | assert_eq!(300, rmp::decode::read_u16(&mut &buf[..]).unwrap()); 101 | ``` 102 | 103 | However if you try to decode such bytearray as other integer type, for example `u32`, there will 104 | be type mismatch error. 105 | 106 | ```rust 107 | let buf = [0xcd, 0x1, 0x2c]; 108 | rmp::decode::read_u32(&mut &buf[..]).err().unwrap(); 109 | ``` 110 | 111 | But sometimes all you want is just to encode an integer that *must* fit in the specified type 112 | no matter how it was encoded. RMP provides [`such`][read_int] function to ease integration with 113 | other MessagePack libraries. 114 | 115 | ```rust 116 | let buf = [0xcd, 0x1, 0x2c]; 117 | 118 | assert_eq!(300i16, rmp::decode::read_int(&mut &buf[..]).unwrap()); 119 | assert_eq!(300i32, rmp::decode::read_int(&mut &buf[..]).unwrap()); 120 | assert_eq!(300i64, rmp::decode::read_int(&mut &buf[..]).unwrap()); 121 | assert_eq!(300u16, rmp::decode::read_int(&mut &buf[..]).unwrap()); 122 | assert_eq!(300u32, rmp::decode::read_int(&mut &buf[..]).unwrap()); 123 | assert_eq!(300u64, rmp::decode::read_int(&mut &buf[..]).unwrap()); 124 | ``` 125 | 126 | ### API 127 | 128 | Almost all API are represented as pure functions, which accepts a generic `Write` or `Read` and 129 | the value to be encoded/decoded. For example let's do a round trip for π number. 130 | 131 | ```rust 132 | let pi = std::f64::consts::PI; 133 | let mut buf = Vec::new(); 134 | rmp::encode::write_f64(&mut buf, pi).unwrap(); 135 | 136 | assert_eq!([0xcb, 0x40, 0x9, 0x21, 0xfb, 0x54, 0x44, 0x2d, 0x18], buf[..]); 137 | assert_eq!(pi, rmp::decode::read_f64(&mut &buf[..]).unwrap()); 138 | ``` 139 | 140 | License: MIT 141 | 142 | [read_int]: https://docs.rs/rmp/latest/rmp/decode/fn.read_int.html 143 | -------------------------------------------------------------------------------- /rmp/benches/bench.rs: -------------------------------------------------------------------------------- 1 | #![feature(test)] 2 | 3 | extern crate test; 4 | 5 | use test::Bencher; 6 | 7 | use rmp::decode::*; 8 | 9 | #[bench] 10 | fn from_i64_read_i64(b: &mut Bencher) { 11 | let buf = [0xd3, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]; 12 | 13 | b.iter(|| { 14 | let res = read_i64(&mut &buf[..]).unwrap(); 15 | test::black_box(res); 16 | }); 17 | } 18 | 19 | #[bench] 20 | fn from_i64_read_int(b: &mut Bencher) { 21 | let buf = [0xd3, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]; 22 | 23 | b.iter(|| { 24 | let res: i64 = read_int(&mut &buf[..]).unwrap(); 25 | test::black_box(res); 26 | }); 27 | } 28 | 29 | #[bench] 30 | fn from_string_read_str(b: &mut Bencher) { 31 | // Lorem ipsum dolor sit amet. 32 | let buf = [ 33 | 0xbb, 0x4c, 0x6f, 0x72, 0x65, 0x6d, 0x20, 0x69, 0x70, 0x73, 34 | 0x75, 0x6d, 0x20, 0x64, 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x73, 35 | 0x69, 0x74, 0x20, 0x61, 0x6d, 0x65, 0x74, 0x2e 36 | ]; 37 | 38 | let mut out = [0u8; 32]; 39 | 40 | b.iter(|| { 41 | let res = read_str(&mut &buf[..], &mut out[..]).unwrap(); 42 | test::black_box(res); 43 | }); 44 | } 45 | -------------------------------------------------------------------------------- /rmp/clippy.toml: -------------------------------------------------------------------------------- 1 | doc-valid-idents = ["MessagePack"] 2 | -------------------------------------------------------------------------------- /rmp/examples/inspect.rs: -------------------------------------------------------------------------------- 1 | use rmp::{decode::*, Marker}; 2 | use std::fmt; 3 | use std::io::{self, Read}; 4 | 5 | fn main() { 6 | let path = std::env::args_os().nth(1).expect("Specify path to a file with msgpack content"); 7 | let data = std::fs::read(&path).expect(&path.to_string_lossy()); 8 | 9 | dump(&mut Indent { i: 0, start: true }, &mut data.as_slice()).unwrap(); 10 | } 11 | 12 | fn dump(indent: &mut Indent, rd: &mut &[u8]) -> Result<(), Box> { 13 | match read_marker(rd).map_err(ValueReadError::from)? { 14 | Marker::FixPos(n) => print!("U0({n})"), 15 | Marker::FixNeg(n) => print!("I0({n})"), 16 | Marker::Null => print!("Null"), 17 | Marker::True => print!("True"), 18 | Marker::False => print!("False"), 19 | Marker::U8 => print!("U8({})", rd.read_data_u8()?), 20 | Marker::U16 => print!("U16({})", rd.read_data_u16()?), 21 | Marker::U32 => print!("U32({})", rd.read_data_u32()?), 22 | Marker::U64 => print!("U64({})", rd.read_data_u64()?), 23 | Marker::I8 => print!("I8({})", rd.read_data_i8()?), 24 | Marker::I16 => print!("I16({})", rd.read_data_i16()?), 25 | Marker::I32 => print!("I32({})", rd.read_data_i32()?), 26 | Marker::I64 => print!("I64({})", rd.read_data_i64()?), 27 | Marker::F32 => print!("F32({})", rd.read_data_f32()?), 28 | Marker::F64 => print!("F64({})", rd.read_data_f64()?), 29 | Marker::FixStr(len) => print!("Str0(\"{}\")", read_str_data(len.into(), rd)?), 30 | Marker::Str8 => print!("Str8(\"{}\")", read_str_data(rd.read_data_u8()?.into(), rd)?), 31 | Marker::Str16 => print!("Str16(\"{}\")", read_str_data(rd.read_data_u16()?.into(), rd)?), 32 | Marker::Str32 => print!("Str32(\"{}\")", read_str_data(rd.read_data_u32()?, rd)?), 33 | Marker::Bin8 => print!("Bin8({})", HexDump(&read_bin_data(rd.read_data_u8()?.into(), rd)?)), 34 | Marker::Bin16 => print!("Bin16({})", HexDump(&read_bin_data(rd.read_data_u16()?.into(), rd)?)), 35 | Marker::Bin32 => print!("Bin32({})", HexDump(&read_bin_data(rd.read_data_u32()?, rd)?)), 36 | Marker::FixArray(len) => dump_array(indent, 0, len.into(), rd)?, 37 | Marker::Array16 => dump_array(indent, 16, rd.read_data_u16()?.into(), rd)?, 38 | Marker::Array32 => dump_array(indent, 32, rd.read_data_u32()?, rd)?, 39 | Marker::FixMap(len) => dump_map(indent, 0, len.into(), rd)?, 40 | Marker::Map16 => dump_map(indent, 16, rd.read_data_u16()?.into(), rd)?, 41 | Marker::Map32 => dump_map(indent, 32, rd.read_data_u32()?, rd)?, 42 | Marker::FixExt1 => todo!(), 43 | Marker::FixExt2 => todo!(), 44 | Marker::FixExt4 => todo!(), 45 | Marker::FixExt8 => todo!(), 46 | Marker::FixExt16 => todo!(), 47 | Marker::Ext8 => todo!(), 48 | Marker::Ext16 => todo!(), 49 | Marker::Ext32 => todo!(), 50 | Marker::Reserved => todo!(), 51 | } 52 | Ok(()) 53 | } 54 | 55 | fn dump_map(indent: &mut Indent, ty: u8, len: u32, rd: &mut &[u8]) -> Result<(), Box> { 56 | indent.print(format_args!("Map{ty}{{")); 57 | let multiline = len > 1; 58 | if multiline { indent.ln(); } else { print!(" ") } 59 | indent.ind(); 60 | for i in 0..len { 61 | indent.print(""); dump(indent, rd)?; print!(": "); dump(indent, rd)?; 62 | if multiline { print!(","); indent.ln(); } else if i+1 != len { print!(", ") } 63 | } 64 | indent.out(); 65 | indent.print(format_args!("}}")); 66 | Ok(()) 67 | } 68 | 69 | fn dump_array(indent: &mut Indent, ty: u8, len: u32, rd: &mut &[u8]) -> Result<(), Box> { 70 | indent.print(format_args!("Array{ty}[")); 71 | let multiline = len > 1; 72 | if multiline { indent.ln(); } else { print!(" ") } 73 | indent.ind(); 74 | for i in 0..len { 75 | indent.print(""); dump(indent, rd)?; 76 | if multiline { print!(","); indent.ln(); } else if i+1 != len { print!(", ") } 77 | } 78 | indent.out(); 79 | indent.print("]"); 80 | Ok(()) 81 | } 82 | 83 | fn read_str_data(len: u32, rd: &mut R) -> Result { 84 | Ok(String::from_utf8_lossy(&read_bin_data(len, rd)?).into_owned()) 85 | } 86 | 87 | fn read_bin_data(len: u32, rd: &mut R) -> Result, io::Error> { 88 | let mut buf = Vec::with_capacity(len.min(1 << 16) as usize); 89 | let bytes_read = rd.take(u64::from(len)).read_to_end(&mut buf)?; 90 | if bytes_read != len as usize { 91 | return Err(io::ErrorKind::UnexpectedEof.into()); 92 | } 93 | Ok(buf) 94 | } 95 | 96 | struct Indent { i: u16, start: bool } 97 | impl Indent { 98 | fn print(&mut self, args: impl fmt::Display) { 99 | print!("{:w$}{args}", "", w = if self.start { (self.i as usize) * 2 } else { 0 }); 100 | self.start = false; 101 | } 102 | 103 | pub const fn ind(&mut self) { 104 | self.i += 1; 105 | } 106 | 107 | pub fn ln(&mut self) { 108 | println!(); 109 | self.start = true; 110 | } 111 | 112 | pub const fn out(&mut self) { 113 | self.i -= 1; 114 | } 115 | } 116 | 117 | struct HexDump<'a>(&'a [u8]); 118 | impl fmt::Display for HexDump<'_> { 119 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 120 | let truncate = self.0.len() > 50; 121 | if truncate { 122 | f.write_fmt(format_args!("{}B ", self.0.len()))?; 123 | } 124 | 125 | for &b in &self.0[0.. (if truncate { 50 } else { self.0.len() })] { 126 | f.write_fmt(format_args!("{b:02x}"))?; 127 | } 128 | 129 | if truncate { 130 | f.write_str("…")?; 131 | } 132 | Ok(()) 133 | } 134 | } 135 | -------------------------------------------------------------------------------- /rmp/src/decode/bytes.rs: -------------------------------------------------------------------------------- 1 | //! Implementation of the [Bytes] type 2 | 3 | use super::RmpRead; 4 | use crate::decode::RmpReadErr; 5 | use core::fmt::{Display, Formatter}; 6 | 7 | /// Indicates that an error occurred reading from [Bytes] 8 | #[derive(Debug)] 9 | #[non_exhaustive] 10 | // NOTE: We can't use thiserror because of no_std :( 11 | pub enum BytesReadError { 12 | /// Indicates that there were not enough bytes. 13 | InsufficientBytes { 14 | expected: usize, 15 | actual: usize, 16 | position: u64, 17 | }, 18 | } 19 | 20 | impl Display for BytesReadError { 21 | fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { 22 | match *self { 23 | Self::InsufficientBytes { expected, actual, position } => { 24 | write!(f, "Expected at least bytes {expected}, but only got {actual} (pos {position})") 25 | } 26 | } 27 | } 28 | } 29 | #[cfg(feature = "std")] 30 | impl std::error::Error for BytesReadError {} 31 | impl RmpReadErr for BytesReadError {} 32 | 33 | /// A wrapper around `&[u8]` to read more efficiently. 34 | /// 35 | /// This has a specialized implementation of `RmpWrite` 36 | /// and has error type [Infallible](core::convert::Infallible). 37 | /// 38 | /// This has the additional benefit of working on `#[no_std]` (unlike the builtin Read trait) 39 | /// 40 | /// See also [serde_bytes::Bytes](https://docs.rs/serde_bytes/0.11/serde_bytes/struct.Bytes.html) 41 | /// 42 | /// Unlike a plain `&[u8]` this also tracks an internal offset in the input (See [`Self::position`]). 43 | /// 44 | /// This is used for (limited) compatibility with [`std::io::Cursor`]. Unlike a [Cursor](std::io::Cursor) it does 45 | /// not support mark/reset. 46 | #[derive(Debug, Copy, Clone, Default, Eq, PartialEq, Hash, Ord, PartialOrd)] 47 | pub struct Bytes<'a> { 48 | /// The internal position of the input buffer. 49 | /// 50 | /// This is not required for correctness. 51 | /// It is only used for error reporting (and to implement [`Self::position`]) 52 | current_position: u64, 53 | bytes: &'a [u8], 54 | } 55 | impl<'a> Bytes<'a> { 56 | /// Wrap an existing bytes slice. 57 | /// 58 | /// This sets the internal position to zero. 59 | #[inline] 60 | #[must_use] 61 | pub const fn new(bytes: &'a [u8]) -> Self { 62 | Bytes { bytes, current_position: 0 } 63 | } 64 | /// Get a reference to the remaining bytes in the buffer. 65 | #[inline] 66 | #[must_use] 67 | pub const fn remaining_slice(&self) -> &'a [u8] { 68 | self.bytes 69 | } 70 | /// Return the position of the input buffer. 71 | /// 72 | /// This is not required for correctness, it only exists to help mimic 73 | /// [`Cursor::position`](std::io::Cursor::position) 74 | #[inline] 75 | #[must_use] 76 | pub const fn position(&self) -> u64 { 77 | self.current_position 78 | } 79 | } 80 | impl<'a> From<&'a [u8]> for Bytes<'a> { 81 | #[inline] 82 | fn from(bytes: &'a [u8]) -> Self { 83 | Bytes { bytes, current_position: 0 } 84 | } 85 | } 86 | 87 | impl RmpRead for Bytes<'_> { 88 | type Error = BytesReadError; 89 | 90 | #[inline] 91 | fn read_u8(&mut self) -> Result { 92 | if let Some((&first, newly_remaining)) = self.bytes.split_first() { 93 | self.bytes = newly_remaining; 94 | self.current_position += 1; 95 | Ok(first) 96 | } else { 97 | Err(BytesReadError::InsufficientBytes { 98 | expected: 1, 99 | actual: 0, 100 | position: self.current_position, 101 | }) 102 | } 103 | } 104 | 105 | #[inline] 106 | fn read_exact_buf(&mut self, buf: &mut [u8]) -> Result<(), Self::Error> { 107 | let to_read = buf.len(); 108 | if to_read <= self.bytes.len() { 109 | let (src, newly_remaining) = self.bytes.split_at(to_read); 110 | self.bytes = newly_remaining; 111 | self.current_position += to_read as u64; 112 | buf.copy_from_slice(src); 113 | Ok(()) 114 | } else { 115 | Err(BytesReadError::InsufficientBytes { 116 | expected: to_read, 117 | actual: self.bytes.len(), 118 | position: self.current_position, 119 | }) 120 | } 121 | } 122 | } 123 | 124 | #[cfg(not(feature = "std"))] 125 | impl<'a> RmpRead for &'a [u8] { 126 | type Error = BytesReadError; 127 | 128 | fn read_u8(&mut self) -> Result { 129 | if let Some((&first, newly_remaining)) = self.split_first() { 130 | *self = newly_remaining; 131 | Ok(first) 132 | } else { 133 | Err(BytesReadError::InsufficientBytes { 134 | expected: 1, 135 | actual: 0, 136 | position: 0, 137 | }) 138 | } 139 | } 140 | 141 | fn read_exact_buf(&mut self, buf: &mut [u8]) -> Result<(), Self::Error> { 142 | let to_read = buf.len(); 143 | if to_read <= self.len() { 144 | let (src, newly_remaining) = self.split_at(to_read); 145 | *self = newly_remaining; 146 | buf.copy_from_slice(src); 147 | Ok(()) 148 | } else { 149 | Err(BytesReadError::InsufficientBytes { 150 | expected: to_read, 151 | actual: self.len(), 152 | position: 0, 153 | }) 154 | } 155 | } 156 | } 157 | -------------------------------------------------------------------------------- /rmp/src/decode/dec.rs: -------------------------------------------------------------------------------- 1 | use super::{read_marker, RmpRead, ValueReadError}; 2 | use crate::Marker; 3 | 4 | /// Attempts to read exactly 5 bytes from the given reader and to decode them as `f32` value. 5 | /// 6 | /// The first byte should be the marker and the others should represent the data itself. 7 | /// 8 | /// # Errors 9 | /// 10 | /// This function will return `ValueReadError` on any I/O error while reading either the marker or 11 | /// the data. 12 | /// 13 | /// It also returns `ValueReadError::TypeMismatch` if the actual type is not equal with the 14 | /// expected one, indicating you with the actual type. 15 | /// 16 | /// # Note 17 | /// 18 | /// This function will silently retry on every EINTR received from the underlying `Read` until 19 | /// successful read. 20 | pub fn read_f32(rd: &mut R) -> Result> { 21 | match read_marker(rd)? { 22 | Marker::F32 => Ok(rd.read_data_f32()?), 23 | marker => Err(ValueReadError::TypeMismatch(marker)), 24 | } 25 | } 26 | 27 | /// Attempts to read exactly 9 bytes from the given reader and to decode them as `f64` value. 28 | /// 29 | /// The first byte should be the marker and the others should represent the data itself. 30 | /// 31 | /// # Errors 32 | /// 33 | /// This function will return `ValueReadError` on any I/O error while reading either the marker or 34 | /// the data. 35 | /// 36 | /// It also returns `ValueReadError::TypeMismatch` if the actual type is not equal with the 37 | /// expected one, indicating you with the actual type. 38 | /// 39 | /// # Note 40 | /// 41 | /// This function will silently retry on every EINTR received from the underlying `Read` until 42 | /// successful read. 43 | pub fn read_f64(rd: &mut R) -> Result> { 44 | match read_marker(rd)? { 45 | Marker::F64 => Ok(rd.read_data_f64()?), 46 | marker => Err(ValueReadError::TypeMismatch(marker)), 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /rmp/src/decode/ext.rs: -------------------------------------------------------------------------------- 1 | use super::{read_marker, RmpRead, ValueReadError}; 2 | use crate::Marker; 3 | 4 | /// Attempts to read exactly 3 bytes from the given reader and interpret them as a fixext1 type 5 | /// with data attached. 6 | /// 7 | /// According to the MessagePack specification, a fixext1 stores an integer and a byte array whose 8 | /// length is 1 byte. Its marker byte is `0xd4`. 9 | /// 10 | /// Note, that this function copies a byte array from the reader to the output `u8` variable. 11 | /// 12 | /// # Errors 13 | /// 14 | /// This function will return `ValueReadError` on any I/O error while reading either the marker or 15 | /// the data. 16 | /// 17 | /// # Note 18 | /// 19 | /// This function will silently retry on every EINTR received from the underlying `Read` until 20 | /// successful read. 21 | pub fn read_fixext1(rd: &mut R) -> Result<(i8, u8), ValueReadError> { 22 | match read_marker(rd)? { 23 | Marker::FixExt1 => { 24 | let ty = rd.read_data_i8()?; 25 | let data = rd.read_data_u8()?; 26 | Ok((ty, data)) 27 | } 28 | marker => Err(ValueReadError::TypeMismatch(marker)), 29 | } 30 | } 31 | 32 | /// Attempts to read exactly 4 bytes from the given reader and interpret them as a fixext2 type 33 | /// with data attached. 34 | /// 35 | /// According to the MessagePack specification, a fixext2 stores an integer and a byte array whose 36 | /// length is 2 bytes. Its marker byte is `0xd5`. 37 | /// 38 | /// Note, that this function copies a byte array from the reader to the output buffer, which is 39 | /// unlikely if you want zero-copy functionality. 40 | /// 41 | /// # Errors 42 | /// 43 | /// This function will return `ValueReadError` on any I/O error while reading either the marker or 44 | /// the data. 45 | pub fn read_fixext2(rd: &mut R) -> Result<(i8, [u8; 2]), ValueReadError> { 46 | match read_marker(rd)? { 47 | Marker::FixExt2 => { 48 | let mut buf = [0; 2]; 49 | read_fixext_data(rd, &mut buf).map(|ty| (ty, buf)) 50 | } 51 | marker => Err(ValueReadError::TypeMismatch(marker)), 52 | } 53 | } 54 | 55 | /// Attempts to read exactly 6 bytes from the given reader and interpret them as a fixext4 type 56 | /// with data attached. 57 | /// 58 | /// According to the MessagePack specification, a fixext4 stores an integer and a byte array whose 59 | /// length is 4 bytes. Its marker byte is `0xd6`. 60 | /// 61 | /// Note, that this function copies a byte array from the reader to the output buffer, which is 62 | /// unlikely if you want zero-copy functionality. 63 | /// 64 | /// # Errors 65 | /// 66 | /// This function will return `ValueReadError` on any I/O error while reading either the marker or 67 | /// the data. 68 | pub fn read_fixext4(rd: &mut R) -> Result<(i8, [u8; 4]), ValueReadError> { 69 | match read_marker(rd)? { 70 | Marker::FixExt4 => { 71 | let mut buf = [0; 4]; 72 | read_fixext_data(rd, &mut buf).map(|ty| (ty, buf)) 73 | } 74 | marker => Err(ValueReadError::TypeMismatch(marker)), 75 | } 76 | } 77 | 78 | /// Attempts to read exactly 10 bytes from the given reader and interpret them as a fixext8 type 79 | /// with data attached. 80 | /// 81 | /// According to the MessagePack specification, a fixext8 stores an integer and a byte array whose 82 | /// length is 8 bytes. Its marker byte is `0xd7`. 83 | /// 84 | /// Note, that this function copies a byte array from the reader to the output buffer, which is 85 | /// unlikely if you want zero-copy functionality. 86 | /// 87 | /// # Errors 88 | /// 89 | /// This function will return `ValueReadError` on any I/O error while reading either the marker or 90 | /// the data. 91 | pub fn read_fixext8(rd: &mut R) -> Result<(i8, [u8; 8]), ValueReadError> { 92 | match read_marker(rd)? { 93 | Marker::FixExt8 => { 94 | let mut buf = [0; 8]; 95 | read_fixext_data(rd, &mut buf).map(|ty| (ty, buf)) 96 | } 97 | marker => Err(ValueReadError::TypeMismatch(marker)), 98 | } 99 | } 100 | 101 | /// Attempts to read exactly 18 bytes from the given reader and interpret them as a fixext16 type 102 | /// with data attached. 103 | /// 104 | /// According to the MessagePack specification, a fixext16 stores an integer and a byte array whose 105 | /// length is 16 bytes. Its marker byte is `0xd8`. 106 | /// 107 | /// Note, that this function copies a byte array from the reader to the output buffer, which is 108 | /// unlikely if you want zero-copy functionality. 109 | /// 110 | /// # Errors 111 | /// 112 | /// This function will return `ValueReadError` on any I/O error while reading either the marker or 113 | /// the data. 114 | pub fn read_fixext16(rd: &mut R) -> Result<(i8, [u8; 16]), ValueReadError> { 115 | match read_marker(rd)? { 116 | Marker::FixExt16 => { 117 | let mut buf = [0; 16]; 118 | read_fixext_data(rd, &mut buf).map(|ty| (ty, buf)) 119 | } 120 | marker => Err(ValueReadError::TypeMismatch(marker)), 121 | } 122 | } 123 | 124 | fn read_fixext_data(rd: &mut R, buf: &mut [u8]) -> Result> { 125 | let id = rd.read_data_i8()?; 126 | match rd.read_exact_buf(buf) { 127 | Ok(()) => Ok(id), 128 | Err(err) => Err(ValueReadError::InvalidDataRead(err)), 129 | } 130 | } 131 | 132 | /// Extension type meta information. 133 | /// 134 | /// Extension represents a tuple of type information and a byte array where type information is an 135 | /// integer whose meaning is defined by applications. 136 | /// 137 | /// Applications can assign 0 to 127 to store application-specific type information. 138 | /// 139 | /// # Note 140 | /// 141 | /// MessagePack reserves -1 to -128 for future extension to add predefined types which will be 142 | /// described in separated documents. 143 | #[derive(Debug, PartialEq)] 144 | pub struct ExtMeta { 145 | /// Type information. 146 | pub typeid: i8, 147 | /// Byte array size. 148 | pub size: u32, 149 | } 150 | 151 | pub fn read_ext_meta(rd: &mut R) -> Result> { 152 | let size = match read_marker(rd)? { 153 | Marker::FixExt1 => 1, 154 | Marker::FixExt2 => 2, 155 | Marker::FixExt4 => 4, 156 | Marker::FixExt8 => 8, 157 | Marker::FixExt16 => 16, 158 | Marker::Ext8 => u32::from(rd.read_data_u8()?), 159 | Marker::Ext16 => u32::from(rd.read_data_u16()?), 160 | Marker::Ext32 => rd.read_data_u32()?, 161 | marker => return Err(ValueReadError::TypeMismatch(marker)), 162 | }; 163 | 164 | let ty = rd.read_data_i8()?; 165 | let meta = ExtMeta { typeid: ty, size }; 166 | 167 | Ok(meta) 168 | } 169 | -------------------------------------------------------------------------------- /rmp/src/decode/sint.rs: -------------------------------------------------------------------------------- 1 | use super::{read_marker, RmpRead, ValueReadError}; 2 | use crate::Marker; 3 | 4 | /// Attempts to read a single byte from the given reader and to decode it as a negative fixnum 5 | /// value. 6 | /// 7 | /// According to the MessagePack specification, a negative fixed integer value is represented using 8 | /// a single byte in `[0xe0; 0xff]` range inclusively, prepended with a special marker mask. 9 | /// 10 | /// # Errors 11 | /// 12 | /// This function will return `ValueReadError` on any I/O error while reading the marker, 13 | /// except the EINTR, which is handled internally. 14 | /// 15 | /// It also returns `ValueReadError::TypeMismatch` if the actual type is not equal with the 16 | /// expected one, indicating you with the actual type. 17 | /// 18 | /// # Note 19 | /// 20 | /// This function will silently retry on every EINTR received from the underlying `Read` until 21 | /// successful read. 22 | pub fn read_nfix(rd: &mut R) -> Result> { 23 | match read_marker(rd)? { 24 | Marker::FixNeg(val) => Ok(val), 25 | marker => Err(ValueReadError::TypeMismatch(marker)), 26 | } 27 | } 28 | 29 | /// Attempts to read exactly 2 bytes from the given reader and to decode them as `i8` value. 30 | /// 31 | /// The first byte should be the marker and the second one should represent the data itself. 32 | /// 33 | /// # Errors 34 | /// 35 | /// This function will return `ValueReadError` on any I/O error while reading either the marker or 36 | /// the data. 37 | /// 38 | /// It also returns `ValueReadError::TypeMismatch` if the actual type is not equal with the 39 | /// expected one, indicating you with the actual type. 40 | /// 41 | /// # Note 42 | /// 43 | /// This function will silently retry on every EINTR received from the underlying `Read` until 44 | /// successful read. 45 | pub fn read_i8(rd: &mut R) -> Result> { 46 | match read_marker(rd)? { 47 | Marker::I8 => rd.read_data_i8(), 48 | marker => Err(ValueReadError::TypeMismatch(marker)), 49 | } 50 | } 51 | 52 | /// Attempts to read exactly 3 bytes from the given reader and to decode them as `i16` value. 53 | /// 54 | /// The first byte should be the marker and the others should represent the data itself. 55 | /// 56 | /// # Errors 57 | /// 58 | /// This function will return `ValueReadError` on any I/O error while reading either the marker or 59 | /// the data. 60 | /// 61 | /// It also returns `ValueReadError::TypeMismatch` if the actual type is not equal with the 62 | /// expected one, indicating you with the actual type. 63 | /// 64 | /// # Note 65 | /// 66 | /// This function will silently retry on every EINTR received from the underlying `Read` until 67 | /// successful read. 68 | pub fn read_i16(rd: &mut R) -> Result> { 69 | match read_marker(rd)? { 70 | Marker::I16 => rd.read_data_i16(), 71 | marker => Err(ValueReadError::TypeMismatch(marker)), 72 | } 73 | } 74 | 75 | /// Attempts to read exactly 5 bytes from the given reader and to decode them as `i32` value. 76 | /// 77 | /// The first byte should be the marker and the others should represent the data itself. 78 | /// 79 | /// # Errors 80 | /// 81 | /// This function will return `ValueReadError` on any I/O error while reading either the marker or 82 | /// the data. 83 | /// 84 | /// It also returns `ValueReadError::TypeMismatch` if the actual type is not equal with the 85 | /// expected one, indicating you with the actual type. 86 | /// 87 | /// # Note 88 | /// 89 | /// This function will silently retry on every EINTR received from the underlying `Read` until 90 | /// successful read. 91 | pub fn read_i32(rd: &mut R) -> Result> { 92 | match read_marker(rd)? { 93 | Marker::I32 => rd.read_data_i32(), 94 | marker => Err(ValueReadError::TypeMismatch(marker)), 95 | } 96 | } 97 | 98 | /// Attempts to read exactly 9 bytes from the given reader and to decode them as `i64` value. 99 | /// 100 | /// The first byte should be the marker and the others should represent the data itself. 101 | /// 102 | /// # Errors 103 | /// 104 | /// This function will return `ValueReadError` on any I/O error while reading either the marker or 105 | /// the data. 106 | /// 107 | /// It also returns `ValueReadError::TypeMismatch` if the actual type is not equal with the 108 | /// expected one, indicating you with the actual type. 109 | /// 110 | /// # Note 111 | /// 112 | /// This function will silently retry on every EINTR received from the underlying `Read` until 113 | /// successful read. 114 | pub fn read_i64(rd: &mut R) -> Result> { 115 | match read_marker(rd)? { 116 | Marker::I64 => rd.read_data_i64(), 117 | marker => Err(ValueReadError::TypeMismatch(marker)), 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /rmp/src/decode/str.rs: -------------------------------------------------------------------------------- 1 | use core::fmt::{self, Display, Formatter}; 2 | use core::str::{from_utf8, Utf8Error}; 3 | #[cfg(feature = "std")] 4 | use std::error; 5 | 6 | use super::{read_marker, RmpRead, RmpReadErr, ValueReadError}; 7 | use crate::Marker; 8 | 9 | #[derive(Debug)] 10 | #[allow(deprecated)] // Only for compatibility 11 | pub enum DecodeStringError<'a, E: RmpReadErr = super::Error> { 12 | InvalidMarkerRead(E), 13 | InvalidDataRead(E), 14 | TypeMismatch(Marker), 15 | /// The given buffer is not large enough to accumulate the specified amount of bytes. 16 | BufferSizeTooSmall(u32), 17 | InvalidUtf8(&'a [u8], Utf8Error), 18 | } 19 | 20 | #[cfg(feature = "std")] 21 | impl error::Error for DecodeStringError<'_, E> { 22 | #[cold] 23 | fn source(&self) -> Option<&(dyn error::Error + 'static)> { 24 | match *self { 25 | DecodeStringError::InvalidMarkerRead(ref err) | 26 | DecodeStringError::InvalidDataRead(ref err) => Some(err), 27 | DecodeStringError::TypeMismatch(..) | 28 | DecodeStringError::BufferSizeTooSmall(..) => None, 29 | DecodeStringError::InvalidUtf8(_, ref err) => Some(err), 30 | } 31 | } 32 | } 33 | 34 | impl Display for DecodeStringError<'_, E> { 35 | #[cold] 36 | fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), fmt::Error> { 37 | f.write_str("error while decoding string") 38 | } 39 | } 40 | 41 | impl From> for DecodeStringError<'_, E> { 42 | #[cold] 43 | fn from(err: ValueReadError) -> Self { 44 | match err { 45 | ValueReadError::InvalidMarkerRead(err) => DecodeStringError::InvalidMarkerRead(err), 46 | ValueReadError::InvalidDataRead(err) => DecodeStringError::InvalidDataRead(err), 47 | ValueReadError::TypeMismatch(marker) => DecodeStringError::TypeMismatch(marker), 48 | } 49 | } 50 | } 51 | 52 | /// Attempts to read up to 9 bytes from the given reader and to decode them as a string `u32` size 53 | /// value. 54 | /// 55 | /// According to the MessagePack specification, the string format family stores an byte array in 1, 56 | /// 2, 3, or 5 bytes of extra bytes in addition to the size of the byte array. 57 | /// 58 | /// # Errors 59 | /// 60 | /// This function will return `ValueReadError` on any I/O error while reading either the marker or 61 | /// the data. 62 | /// 63 | /// It also returns `ValueReadError::TypeMismatch` if the actual type is not equal with the 64 | /// expected one, indicating you with the actual type. 65 | #[inline] 66 | pub fn read_str_len(rd: &mut R) -> Result> { 67 | Ok(read_str_len_with_nread(rd)?.0) 68 | } 69 | 70 | fn read_str_len_with_nread(rd: &mut R) -> Result<(u32, usize), ValueReadError> 71 | where R: RmpRead 72 | { 73 | match read_marker(rd)? { 74 | Marker::FixStr(size) => Ok((u32::from(size), 1)), 75 | Marker::Str8 => Ok((u32::from(rd.read_data_u8()?), 2)), 76 | Marker::Str16 => Ok((u32::from(rd.read_data_u16()?), 3)), 77 | Marker::Str32 => Ok((rd.read_data_u32()?, 5)), 78 | marker => Err(ValueReadError::TypeMismatch(marker)), 79 | } 80 | } 81 | 82 | /// Attempts to read a string data from the given reader and copy it to the buffer provided. 83 | /// 84 | /// On success returns a borrowed string type, allowing to view the copied bytes as properly utf-8 85 | /// string. 86 | /// According to the spec, the string's data must to be encoded using utf-8. 87 | /// 88 | /// # Errors 89 | /// 90 | /// Returns `Err` in the following cases: 91 | /// 92 | /// - if any IO error (including unexpected EOF) occurs, while reading an `rd`, except the EINTR, 93 | /// which is handled internally. 94 | /// - if the `out` buffer size is not large enough to keep all the data copied. 95 | /// - if the data is not utf-8, with a description as to why the provided data is not utf-8 and 96 | /// with a size of bytes actually copied to be able to get them from `out`. 97 | /// 98 | /// # Examples 99 | /// ``` 100 | /// use rmp::decode::read_str; 101 | /// 102 | /// let buf = [0xaa, 0x6c, 0x65, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65]; 103 | /// let mut out = [0u8; 16]; 104 | /// 105 | /// assert_eq!("le message", read_str(&mut &buf[..], &mut &mut out[..]).unwrap()); 106 | /// ``` 107 | /// 108 | /// # Unstable 109 | /// 110 | /// This function is **unstable**, because it needs review. 111 | // TODO: Stabilize. Mark error values for each error case (in docs). 112 | pub fn read_str<'r, R>(rd: &mut R, buf: &'r mut [u8]) -> Result<&'r str, DecodeStringError<'r, R::Error>> 113 | where 114 | R: RmpRead, 115 | { 116 | let len = read_str_len(rd)?; 117 | let ulen = len as usize; 118 | 119 | if buf.len() < ulen { 120 | return Err(DecodeStringError::BufferSizeTooSmall(len)); 121 | } 122 | 123 | read_str_data(rd, len, &mut buf[0..ulen]) 124 | } 125 | 126 | pub fn read_str_data<'r, R>(rd: &mut R, 127 | len: u32, 128 | buf: &'r mut [u8]) 129 | -> Result<&'r str, DecodeStringError<'r, R::Error>> 130 | where R: RmpRead 131 | { 132 | debug_assert_eq!(len as usize, buf.len()); 133 | 134 | // Trying to copy exact `len` bytes. 135 | match rd.read_exact_buf(buf) { 136 | Ok(()) => match from_utf8(buf) { 137 | Ok(decoded) => Ok(decoded), 138 | Err(err) => Err(DecodeStringError::InvalidUtf8(buf, err)), 139 | }, 140 | Err(err) => Err(DecodeStringError::InvalidDataRead(err)), 141 | } 142 | } 143 | 144 | /// Attempts to read and decode a string value from the reader, returning a borrowed slice from it. 145 | /// 146 | // TODO: Also it's possible to implement all borrowing functions for all `BufRead` implementors. 147 | #[deprecated(since = "0.8.6", note = "useless, use `read_str_from_slice` instead")] 148 | pub fn read_str_ref(rd: &[u8]) -> Result<&[u8], DecodeStringError<'_, super::bytes::BytesReadError>> { 149 | let mut cur = super::Bytes::new(rd); 150 | let len = read_str_len(&mut cur)?; 151 | Ok(&cur.remaining_slice()[..len as usize]) 152 | } 153 | 154 | /// Attempts to read and decode a string value from the reader, returning a borrowed slice from it. 155 | /// 156 | /// # Examples 157 | /// 158 | /// ``` 159 | /// use rmp::encode::write_str; 160 | /// use rmp::decode::read_str_from_slice; 161 | /// 162 | /// let mut buf = Vec::new(); 163 | /// write_str(&mut buf, "Unpacking").unwrap(); 164 | /// write_str(&mut buf, "multiple").unwrap(); 165 | /// write_str(&mut buf, "strings").unwrap(); 166 | /// 167 | /// let mut chunks = Vec::new(); 168 | /// let mut unparsed = &buf[..]; 169 | /// while let Ok((chunk, tail)) = read_str_from_slice(unparsed) { 170 | /// chunks.push(chunk); 171 | /// unparsed = tail; 172 | /// } 173 | /// 174 | /// assert_eq!(vec!["Unpacking", "multiple", "strings"], chunks); 175 | /// ``` 176 | pub fn read_str_from_slice>( 177 | buf: &T, 178 | ) -> Result<(&str, &[u8]), DecodeStringError<'_, super::bytes::BytesReadError>> { 179 | let buf = buf.as_ref(); 180 | let (len, nread) = read_str_len_with_nread(&mut super::Bytes::new(buf))?; 181 | let ulen = len as usize; 182 | 183 | if buf[nread..].len() >= ulen { 184 | let (head, tail) = buf.split_at(nread + ulen); 185 | match from_utf8(&head[nread..]) { 186 | Ok(val) => Ok((val, tail)), 187 | Err(err) => Err(DecodeStringError::InvalidUtf8(buf, err)), 188 | } 189 | } else { 190 | Err(DecodeStringError::BufferSizeTooSmall(len)) 191 | } 192 | } 193 | -------------------------------------------------------------------------------- /rmp/src/decode/uint.rs: -------------------------------------------------------------------------------- 1 | use super::{read_marker, RmpRead, ValueReadError}; 2 | use crate::Marker; 3 | 4 | /// Attempts to read a single byte from the given reader and to decode it as a positive fixnum 5 | /// value. 6 | /// 7 | /// According to the MessagePack specification, a positive fixed integer value is represented using 8 | /// a single byte in `[0x00; 0x7f]` range inclusively, prepended with a special marker mask. 9 | /// 10 | /// # Errors 11 | /// 12 | /// This function will return `ValueReadError` on any I/O error while reading the marker, 13 | /// except the EINTR, which is handled internally. 14 | /// 15 | /// It also returns `ValueReadError::TypeMismatch` if the actual type is not equal with the 16 | /// expected one, indicating you with the actual type. 17 | /// 18 | /// # Note 19 | /// 20 | /// This function will silently retry on every EINTR received from the underlying `Read` until 21 | /// successful read. 22 | pub fn read_pfix(rd: &mut R) -> Result> { 23 | match read_marker(rd)? { 24 | Marker::FixPos(val) => Ok(val), 25 | marker => Err(ValueReadError::TypeMismatch(marker)), 26 | } 27 | } 28 | 29 | /// Attempts to read exactly 2 bytes from the given reader and to decode them as `u8` value. 30 | /// 31 | /// The first byte should be the marker and the second one should represent the data itself. 32 | /// 33 | /// # Errors 34 | /// 35 | /// This function will return `ValueReadError` on any I/O error while reading either the marker or 36 | /// the data. 37 | /// 38 | /// It also returns `ValueReadError::TypeMismatch` if the actual type is not equal with the 39 | /// expected one, indicating you with the actual type. 40 | pub fn read_u8(rd: &mut R) -> Result> { 41 | match read_marker(rd)? { 42 | Marker::U8 => rd.read_data_u8(), 43 | marker => Err(ValueReadError::TypeMismatch(marker)), 44 | } 45 | } 46 | 47 | /// Attempts to read exactly 3 bytes from the given reader and to decode them as `u16` value. 48 | /// 49 | /// The first byte should be the marker and the others should represent the data itself. 50 | /// 51 | /// # Errors 52 | /// 53 | /// This function will return `ValueReadError` on any I/O error while reading either the marker or 54 | /// the data. 55 | /// 56 | /// It also returns `ValueReadError::TypeMismatch` if the actual type is not equal with the 57 | /// expected one, indicating you with the actual type. 58 | /// 59 | /// # Note 60 | /// 61 | /// This function will silently retry on every EINTR received from the underlying `Read` until 62 | /// successful read. 63 | pub fn read_u16(rd: &mut R) -> Result> { 64 | match read_marker(rd)? { 65 | Marker::U16 => rd.read_data_u16(), 66 | marker => Err(ValueReadError::TypeMismatch(marker)), 67 | } 68 | } 69 | 70 | /// Attempts to read exactly 5 bytes from the given reader and to decode them as `u32` value. 71 | /// 72 | /// The first byte should be the marker and the others should represent the data itself. 73 | /// 74 | /// # Errors 75 | /// 76 | /// This function will return `ValueReadError` on any I/O error while reading either the marker or 77 | /// the data. 78 | /// 79 | /// It also returns `ValueReadError::TypeMismatch` if the actual type is not equal with the 80 | /// expected one, indicating you with the actual type. 81 | /// 82 | /// # Note 83 | /// 84 | /// This function will silently retry on every EINTR received from the underlying `Read` until 85 | /// successful read. 86 | pub fn read_u32(rd: &mut R) -> Result> { 87 | match read_marker(rd)? { 88 | Marker::U32 => rd.read_data_u32(), 89 | marker => Err(ValueReadError::TypeMismatch(marker)), 90 | } 91 | } 92 | 93 | /// Attempts to read exactly 9 bytes from the given reader and to decode them as `u64` value. 94 | /// 95 | /// The first byte should be the marker and the others should represent the data itself. 96 | /// 97 | /// # Errors 98 | /// 99 | /// This function will return `ValueReadError` on any I/O error while reading either the marker or 100 | /// the data. 101 | /// 102 | /// It also returns `ValueReadError::TypeMismatch` if the actual type is not equal with the 103 | /// expected one, indicating you with the actual type. 104 | /// 105 | /// # Note 106 | /// 107 | /// This function will silently retry on every EINTR received from the underlying `Read` until 108 | /// successful read. 109 | pub fn read_u64(rd: &mut R) -> Result> { 110 | match read_marker(rd)? { 111 | Marker::U64 => rd.read_data_u64(), 112 | marker => Err(ValueReadError::TypeMismatch(marker)), 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /rmp/src/encode/bin.rs: -------------------------------------------------------------------------------- 1 | use super::RmpWrite; 2 | use crate::encode::{write_marker, ValueWriteError}; 3 | use crate::Marker; 4 | 5 | /// Encodes and attempts to write the most efficient binary array length implementation to the given 6 | /// write, returning the marker used. 7 | /// 8 | /// This function is useful when you want to get full control for writing the data itself, for 9 | /// example, when using non-blocking socket. 10 | /// 11 | /// # Errors 12 | /// 13 | /// This function will return `ValueWriteError` on any I/O error occurred while writing either the 14 | /// marker or the data. 15 | pub fn write_bin_len(wr: &mut W, len: u32) -> Result> { 16 | let marker = if len < 256 { 17 | Marker::Bin8 18 | } else if u16::try_from(len).is_ok() { 19 | Marker::Bin16 20 | } else { 21 | Marker::Bin32 22 | }; 23 | write_marker(&mut *wr, marker)?; 24 | if marker == Marker::Bin8 { 25 | wr.write_data_u8(len as u8)?; 26 | } else if marker == Marker::Bin16 { 27 | wr.write_data_u16(len as u16)?; 28 | } else if marker == Marker::Bin32 { 29 | wr.write_data_u32(len)?; 30 | } 31 | Ok(marker) 32 | } 33 | 34 | /// Encodes and attempts to write the most efficient binary implementation to the given `Write`. 35 | /// 36 | /// # Errors 37 | /// 38 | /// This function will return `ValueWriteError` on any I/O error occurred while writing either the 39 | /// marker or the data. 40 | // TODO: Docs, range check, example, visibility. 41 | pub fn write_bin(wr: &mut W, data: &[u8]) -> Result<(), ValueWriteError> { 42 | write_bin_len(wr, data.len() as u32)?; 43 | wr.write_bytes(data) 44 | .map_err(ValueWriteError::InvalidDataWrite) 45 | } 46 | -------------------------------------------------------------------------------- /rmp/src/encode/buffer.rs: -------------------------------------------------------------------------------- 1 | //! Implementation of the [`ByteBuf`] type 2 | 3 | use super::RmpWrite; 4 | use alloc::vec::Vec; 5 | #[cfg(not(feature = "std"))] 6 | use core::fmt::{self, Display, Formatter}; 7 | 8 | /// An error returned from writing to `&mut [u8]` (a byte buffer of fixed capacity) on no_std 9 | /// 10 | /// In feature="std", capacity overflow in `<&mut [u8] as std::io::Write>::write_exact()` 11 | /// currently returns [`ErrorKind::WriteZero`](https://doc.rust-lang.org/std/io/enum.ErrorKind.html#variant.WriteZero). 12 | /// 13 | /// Since no_std doesn't have std::io::Error we use this instead ;) 14 | /// 15 | /// This is specific to `#[cfg(not(feature = "std"))]` so it is `#[doc(hidden)]` 16 | #[derive(Debug)] 17 | #[cfg(not(feature = "std"))] 18 | #[doc(hidden)] 19 | pub struct FixedBufCapacityOverflow { 20 | _priv: (), 21 | } 22 | 23 | /// An error returned from writing to `&mut [u8]` 24 | /// 25 | /// Aliased for compatibility with `no_std` mode. 26 | #[cfg(feature = "std")] 27 | #[doc(hidden)] 28 | pub type FixedBufCapacityOverflow = std::io::Error; 29 | 30 | #[cfg(not(feature = "std"))] 31 | impl Display for FixedBufCapacityOverflow { 32 | fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { 33 | // This is intentionally vauge because std::io::Error is 34 | // Doesn't make sense for no_std to have bettetr errors than std 35 | f.write_str("Capacity overflow for fixed-size byte buffer") 36 | } 37 | } 38 | #[cfg(not(feature = "std"))] 39 | impl crate::encode::RmpWriteErr for FixedBufCapacityOverflow {} 40 | 41 | /// Fallback implementation for fixed-capacity buffers 42 | /// 43 | /// Only needed for no-std because we don't have 44 | /// the blanket impl for `std::io::Write` 45 | #[cfg(not(feature = "std"))] 46 | impl<'a> RmpWrite for &'a mut [u8] { 47 | type Error = FixedBufCapacityOverflow; 48 | 49 | #[inline] 50 | fn write_bytes(&mut self, buf: &[u8]) -> Result<(), Self::Error> { 51 | let to_write = buf.len(); 52 | let remaining = self.len(); 53 | if to_write <= remaining { 54 | self[..to_write].copy_from_slice(buf); 55 | unsafe { 56 | //Cant use split_at or re-borrowing due to lifetime errors :( 57 | *self = core::slice::from_raw_parts_mut( 58 | self.as_mut_ptr().add(to_write), 59 | remaining - to_write, 60 | ) 61 | } 62 | Ok(()) 63 | } else { 64 | Err(FixedBufCapacityOverflow { _priv: () }) 65 | } 66 | } 67 | } 68 | 69 | /// A wrapper around `Vec` to serialize more efficiently. 70 | /// 71 | /// This has a specialized implementation of `RmpWrite` 72 | /// It gives `std::convert::Infailable` for errors. 73 | /// This is because writing to `Vec` can only fail due to allocation. 74 | /// 75 | /// This has the additional benefit of working on `#[no_std]` 76 | /// 77 | /// See also [serde_bytes::ByteBuf](https://docs.rs/serde_bytes/0.11/serde_bytes/struct.ByteBuf.html) 78 | #[derive(Debug, Clone, Default, Eq, PartialEq, Hash, Ord, PartialOrd)] 79 | pub struct ByteBuf { 80 | bytes: Vec, 81 | } 82 | impl ByteBuf { 83 | /// Construct a new empty buffer 84 | #[inline] 85 | #[must_use] 86 | pub fn new() -> Self { 87 | Self { bytes: Vec::new() } 88 | } 89 | /// Construct a new buffer with the specified capacity 90 | /// 91 | /// See [`Vec::with_capacity`] for details 92 | #[inline] 93 | #[must_use] 94 | pub fn with_capacity(capacity: usize) -> Self { 95 | Self { 96 | bytes: Vec::with_capacity(capacity), 97 | } 98 | } 99 | /// Unwrap the underlying buffer of this vector 100 | #[inline] 101 | #[must_use] 102 | pub fn into_vec(self) -> Vec { 103 | self.bytes 104 | } 105 | /// Wrap the specified vector as a [`ByteBuf`] 106 | #[inline] 107 | #[must_use] 108 | pub fn from_vec(bytes: Vec) -> Self { 109 | Self { bytes } 110 | } 111 | /// Get a reference to this type as a [Vec] 112 | #[inline] 113 | #[must_use] 114 | pub fn as_vec(&self) -> &Vec { 115 | &self.bytes 116 | } 117 | /// Get a mutable reference to this type as a [Vec] 118 | #[inline] 119 | pub fn as_mut_vec(&mut self) -> &mut Vec { 120 | &mut self.bytes 121 | } 122 | /// Get a reference to this type as a slice of bytes (`&[u8]`) 123 | #[inline] 124 | #[must_use] 125 | pub fn as_slice(&self) -> &[u8] { 126 | &self.bytes 127 | } 128 | } 129 | impl AsRef<[u8]> for ByteBuf { 130 | fn as_ref(&self) -> &[u8] { 131 | &self.bytes 132 | } 133 | } 134 | impl AsRef> for ByteBuf { 135 | #[inline] 136 | fn as_ref(&self) -> &Vec { 137 | &self.bytes 138 | } 139 | } 140 | impl AsMut> for ByteBuf { 141 | #[inline] 142 | fn as_mut(&mut self) -> &mut Vec { 143 | &mut self.bytes 144 | } 145 | } 146 | impl From for Vec { 147 | #[inline] 148 | fn from(buf: ByteBuf) -> Self { 149 | buf.bytes 150 | } 151 | } 152 | impl From> for ByteBuf { 153 | #[inline] 154 | fn from(bytes: Vec) -> Self { 155 | Self { bytes } 156 | } 157 | } 158 | 159 | impl RmpWrite for ByteBuf { 160 | type Error = core::convert::Infallible; 161 | 162 | #[inline] 163 | fn write_u8(&mut self, val: u8) -> Result<(), Self::Error> { 164 | self.bytes.push(val); 165 | Ok(()) 166 | } 167 | 168 | #[inline] 169 | fn write_bytes(&mut self, buf: &[u8]) -> Result<(), Self::Error> { 170 | self.bytes.extend_from_slice(buf); 171 | Ok(()) 172 | } 173 | } 174 | #[cfg(not(feature = "std"))] 175 | impl<'a> RmpWrite for Vec { 176 | type Error = core::convert::Infallible; 177 | 178 | #[inline] 179 | fn write_u8(&mut self, val: u8) -> Result<(), Self::Error> { 180 | self.push(val); 181 | Ok(()) 182 | } 183 | 184 | #[inline] 185 | fn write_bytes(&mut self, buf: &[u8]) -> Result<(), Self::Error> { 186 | self.extend_from_slice(buf); 187 | Ok(()) 188 | } 189 | } 190 | -------------------------------------------------------------------------------- /rmp/src/encode/dec.rs: -------------------------------------------------------------------------------- 1 | use super::{write_marker, RmpWrite}; 2 | use crate::encode::ValueWriteError; 3 | use crate::Marker; 4 | 5 | /// Encodes and attempts to write an `f32` value as a 5-byte sequence into the given write. 6 | /// 7 | /// The first byte becomes the `f32` marker and the others will represent the data itself. 8 | /// 9 | /// # Errors 10 | /// 11 | /// This function will return `ValueWriteError` on any I/O error occurred while writing either the 12 | /// marker or the data. 13 | pub fn write_f32(wr: &mut W, val: f32) -> Result<(), ValueWriteError> { 14 | write_marker(wr, Marker::F32)?; 15 | wr.write_data_f32(val)?; 16 | Ok(()) 17 | } 18 | 19 | /// Encodes and attempts to write an `f64` value as a 9-byte sequence into the given write. 20 | /// 21 | /// The first byte becomes the `f64` marker and the others will represent the data itself. 22 | /// 23 | /// # Errors 24 | /// 25 | /// This function will return `ValueWriteError` on any I/O error occurred while writing either the 26 | /// marker or the data. 27 | pub fn write_f64(wr: &mut W, val: f64) -> Result<(), ValueWriteError> { 28 | write_marker(wr, Marker::F64)?; 29 | wr.write_data_f64(val)?; 30 | Ok(()) 31 | } 32 | -------------------------------------------------------------------------------- /rmp/src/encode/ext.rs: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /rmp/src/encode/map.rs: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /rmp/src/encode/sint.rs: -------------------------------------------------------------------------------- 1 | use super::{write_marker, RmpWrite}; 2 | use crate::encode::{write_pfix, write_u16, write_u32, write_u64, write_u8, ValueWriteError}; 3 | use crate::Marker; 4 | 5 | /// Encodes and attempts to write a negative small integer value as a negative fixnum into the 6 | /// given write. 7 | /// 8 | /// According to the MessagePack specification, a negative fixed integer value is represented using 9 | /// a single byte in `[0xe0; 0xff]` range inclusively, prepended with a special marker mask. 10 | /// 11 | /// The function is **strict** with the input arguments - it is the user's responsibility to check 12 | /// if the value fits in the described range, otherwise it will panic. 13 | /// 14 | /// If you are not sure if the value fits in the given range use `write_sint` instead, which 15 | /// automatically selects the most compact integer representation. 16 | /// 17 | /// # Errors 18 | /// 19 | /// This function will return `FixedValueWriteError` on any I/O error occurred while writing the 20 | /// positive integer marker. 21 | /// 22 | /// # Panics 23 | /// 24 | /// Panics if `val` does not fit in `[-32; 0)` range. 25 | #[inline] 26 | #[track_caller] 27 | pub fn write_nfix(wr: &mut W, val: i8) -> Result<(), W::Error> { 28 | assert!(-32 <= val && val < 0); 29 | write_marker(wr, Marker::FixNeg(val)).map_err(|e| e.0)?; 30 | Ok(()) 31 | } 32 | 33 | /// Encodes and attempts to write an `i8` value as a 2-byte sequence into the given write. 34 | /// 35 | /// The first byte becomes the marker and the second one will represent the data itself. 36 | /// 37 | /// Note, that this function will encode the given value in 2-byte sequence no matter what, even if 38 | /// the value can be represented using single byte as a fixnum. Also note, that the first byte will 39 | /// always be the i8 marker (`0xd0`). 40 | /// 41 | /// If you need to fit the given buffer efficiently use `write_sint` instead, which automatically 42 | /// selects the appropriate integer representation. 43 | /// 44 | /// # Errors 45 | /// 46 | /// This function will return `ValueWriteError` on any I/O error occurred while writing either the 47 | /// marker or the data. 48 | /// 49 | /// # Examples 50 | /// 51 | /// ``` 52 | /// let mut buf = [0x00, 0x00]; 53 | /// 54 | /// rmp::encode::write_i8(&mut &mut buf[..], 42).ok().unwrap(); 55 | /// assert_eq!([0xd0, 0x2a], buf); 56 | /// 57 | /// // Note, that -18 can be represented simply as `[0xee]`, but the function emits 2-byte sequence. 58 | /// rmp::encode::write_i8(&mut &mut buf[..], -18).ok().unwrap(); 59 | /// assert_eq!([0xd0, 0xee], buf); 60 | /// ``` 61 | pub fn write_i8(wr: &mut W, val: i8) -> Result<(), ValueWriteError> { 62 | write_marker(wr, Marker::I8)?; 63 | wr.write_data_i8(val)?; 64 | Ok(()) 65 | } 66 | 67 | /// Encodes and attempts to write an `i16` value as a 3-byte sequence into the given write. 68 | /// 69 | /// The first byte becomes the marker and the others will represent the data itself. 70 | /// 71 | /// Note, that this function will encode the given value in 3-byte sequence no matter what, even if 72 | /// the value can be represented using single byte as a fixnum. Also note, that the first byte will 73 | /// always be the i16 marker (`0xd1`). 74 | /// 75 | /// If you need to fit the given buffer efficiently use `write_sint` instead, which automatically 76 | /// selects the appropriate integer representation. 77 | /// 78 | /// # Errors 79 | /// 80 | /// This function will return `ValueWriteError` on any I/O error occurred while writing either the 81 | /// marker or the data. 82 | pub fn write_i16(wr: &mut W, val: i16) -> Result<(), ValueWriteError> { 83 | write_marker(wr, Marker::I16)?; 84 | wr.write_data_i16(val)?; 85 | Ok(()) 86 | } 87 | 88 | /// Encodes and attempts to write an `i32` value as a 5-byte sequence into the given write. 89 | /// 90 | /// The first byte becomes the marker and the others will represent the data itself. 91 | /// 92 | /// Note, that this function will encode the given value in 5-byte sequence no matter what, even if 93 | /// the value can be represented using single byte as a fixnum. Also note, that the first byte will 94 | /// always be the i32 marker (`0xd2`). 95 | /// 96 | /// If you need to fit the given buffer efficiently use `write_sint` instead, which automatically 97 | /// selects the appropriate integer representation. 98 | /// 99 | /// # Errors 100 | /// 101 | /// This function will return `ValueWriteError` on any I/O error occurred while writing either the 102 | /// marker or the data. 103 | pub fn write_i32(wr: &mut W, val: i32) -> Result<(), ValueWriteError> { 104 | write_marker(wr, Marker::I32)?; 105 | wr.write_data_i32(val)?; 106 | Ok(()) 107 | } 108 | 109 | /// Encodes and attempts to write an `i64` value as a 9-byte sequence into the given write. 110 | /// 111 | /// The first byte becomes the marker and the others will represent the data itself. 112 | /// 113 | /// Note, that this function will encode the given value in 9-byte sequence no matter what, even if 114 | /// the value can be represented using single byte as a fixnum. Also note, that the first byte will 115 | /// always be the i16 marker (`0xd3`). 116 | /// 117 | /// If you need to fit the given buffer efficiently use `write_sint` instead, which automatically 118 | /// selects the appropriate integer representation. 119 | /// 120 | /// # Errors 121 | /// 122 | /// This function will return `ValueWriteError` on any I/O error occurred while writing either the 123 | /// marker or the data. 124 | pub fn write_i64(wr: &mut W, val: i64) -> Result<(), ValueWriteError> { 125 | write_marker(wr, Marker::I64)?; 126 | wr.write_data_i64(val)?; 127 | Ok(()) 128 | } 129 | 130 | /// Encodes and attempts to write an `i64` value into the given write using the most efficient 131 | /// representation, returning the marker used. 132 | /// 133 | /// This function obeys the MessagePack specification, which requires that the serializer SHOULD use 134 | /// the format which represents the data in the smallest number of bytes, with the exception of 135 | /// sized/unsized types. 136 | /// 137 | /// Note, that the function will **always** use signed integer representation even if the value can 138 | /// be more efficiently represented using unsigned integer encoding. 139 | /// 140 | /// The first byte becomes the marker and the others (if present, up to 9) will represent the data 141 | /// itself. 142 | /// 143 | /// # Errors 144 | /// 145 | /// This function will return `ValueWriteError` on any I/O error occurred while writing either the 146 | /// marker or the data. 147 | pub fn write_sint(wr: &mut W, val: i64) -> Result> { 148 | match val { 149 | val if -32 <= val && val < 0 => { 150 | write_nfix(wr, val as i8) 151 | .and(Ok(Marker::FixNeg(val as i8))) 152 | .map_err(ValueWriteError::InvalidMarkerWrite) 153 | } 154 | val if -128 <= val && val < -32 => write_i8(wr, val as i8).and(Ok(Marker::I8)), 155 | val if -32768 <= val && val < -128 => write_i16(wr, val as i16).and(Ok(Marker::I16)), 156 | val if -2147483648 <= val && val < -32768 => write_i32(wr, val as i32).and(Ok(Marker::I32)), 157 | val if val < -2147483648 => write_i64(wr, val).and(Ok(Marker::I64)), 158 | val if 0 <= val && val < 128 => { 159 | write_pfix(wr, val as u8) 160 | .and(Ok(Marker::FixPos(val as u8))) 161 | .map_err(ValueWriteError::InvalidMarkerWrite) 162 | } 163 | val if val < 256 => write_u8(wr, val as u8).and(Ok(Marker::U8)), 164 | val if val < 65536 => write_u16(wr, val as u16).and(Ok(Marker::U16)), 165 | val if val < 4294967296 => write_u32(wr, val as u32).and(Ok(Marker::U32)), 166 | val => write_u64(wr, val as u64).and(Ok(Marker::U64)), 167 | } 168 | } 169 | -------------------------------------------------------------------------------- /rmp/src/encode/str.rs: -------------------------------------------------------------------------------- 1 | use super::{write_marker, RmpWrite}; 2 | use crate::encode::ValueWriteError; 3 | use crate::Marker; 4 | 5 | /// Encodes and attempts to write the most efficient string length implementation to the given 6 | /// write, returning the marker used. 7 | /// 8 | /// # Errors 9 | /// 10 | /// This function will return `ValueWriteError` on any I/O error occurred while writing either the 11 | /// marker or the data. 12 | pub fn write_str_len(wr: &mut W, len: u32) -> Result> { 13 | let marker = if len < 32 { 14 | Marker::FixStr(len as u8) 15 | } else if len < 256 { 16 | Marker::Str8 17 | } else if u16::try_from(len).is_ok() { 18 | Marker::Str16 19 | } else { 20 | Marker::Str32 21 | }; 22 | 23 | write_marker(wr, marker)?; 24 | if marker == Marker::Str8 { 25 | wr.write_data_u8(len as u8)?; 26 | } 27 | if marker == Marker::Str16 { 28 | wr.write_data_u16(len as u16)?; 29 | } 30 | if marker == Marker::Str32 { 31 | wr.write_data_u32(len)?; 32 | } 33 | Ok(marker) 34 | } 35 | 36 | /// Encodes and attempts to write the most efficient string binary representation to the 37 | /// given `Write`. 38 | /// 39 | /// # Errors 40 | /// 41 | /// This function will return `ValueWriteError` on any I/O error occurred while writing either the 42 | /// marker or the data. 43 | // TODO: Docs, range check, example, visibility. 44 | pub fn write_str(wr: &mut W, data: &str) -> Result<(), ValueWriteError> { 45 | write_str_len(wr, data.len() as u32)?; 46 | wr.write_bytes(data.as_bytes()).map_err(ValueWriteError::InvalidDataWrite) 47 | } 48 | -------------------------------------------------------------------------------- /rmp/src/encode/uint.rs: -------------------------------------------------------------------------------- 1 | use super::{write_marker, RmpWrite}; 2 | use crate::encode::ValueWriteError; 3 | use crate::Marker; 4 | 5 | /// Encodes and attempts to write an unsigned small integer value as a positive fixint into the 6 | /// given write. 7 | /// 8 | /// According to the MessagePack specification, a positive fixed integer value is represented using 9 | /// a single byte in `[0x00; 0x7f]` range inclusively, prepended with a special marker mask. 10 | /// 11 | /// The function is **strict** with the input arguments - it is the user's responsibility to check 12 | /// if the value fits in the described range, otherwise it will panic. 13 | /// 14 | /// If you are not sure if the value fits in the given range use `write_uint` instead, which 15 | /// automatically selects the most compact integer representation. 16 | /// 17 | /// # Errors 18 | /// 19 | /// This function will return `FixedValueWriteError` on any I/O error occurred while writing the 20 | /// positive integer marker. 21 | /// 22 | /// # Panics 23 | /// 24 | /// Panics if `val` is greater than 127. 25 | #[inline] 26 | pub fn write_pfix(wr: &mut W, val: u8) -> Result<(), W::Error> { 27 | assert!(val < 128); 28 | write_marker(wr, Marker::FixPos(val)).map_err(|e| e.0)?; 29 | Ok(()) 30 | } 31 | 32 | /// Encodes and attempts to write an `u8` value as a 2-byte sequence into the given write. 33 | /// 34 | /// The first byte becomes the marker and the second one will represent the data itself. 35 | /// 36 | /// Note, that this function will encode the given value in 2-byte sequence no matter what, even if 37 | /// the value can be represented using single byte as a positive fixnum. 38 | /// 39 | /// If you need to fit the given buffer efficiently use `write_uint` instead, which automatically 40 | /// selects the appropriate integer representation. 41 | /// 42 | /// # Errors 43 | /// 44 | /// This function will return `ValueWriteError` on any I/O error occurred while writing either the 45 | /// marker or the data. 46 | /// 47 | /// # Examples 48 | /// ``` 49 | /// let mut buf = [0x00, 0x00]; 50 | /// 51 | /// rmp::encode::write_u8(&mut &mut buf[..], 146).ok().unwrap(); 52 | /// assert_eq!([0xcc, 0x92], buf); 53 | /// 54 | /// // Note, that 42 can be represented simply as `[0x2a]`, but the function emits 2-byte sequence. 55 | /// rmp::encode::write_u8(&mut &mut buf[..], 42).ok().unwrap(); 56 | /// assert_eq!([0xcc, 0x2a], buf); 57 | /// ``` 58 | pub fn write_u8(wr: &mut W, val: u8) -> Result<(), ValueWriteError> { 59 | write_marker(wr, Marker::U8)?; 60 | wr.write_data_u8(val)?; 61 | Ok(()) 62 | } 63 | 64 | /// Encodes and attempts to write an `u16` value strictly as a 3-byte sequence into the given write. 65 | /// 66 | /// The first byte becomes the marker and the others will represent the data itself. 67 | /// 68 | /// Note, that this function will encode the given value in 3-byte sequence no matter what, even if 69 | /// the value can be represented using single byte as a positive fixnum. 70 | /// 71 | /// If you need to fit the given buffer efficiently use `write_uint` instead, which automatically 72 | /// selects the appropriate integer representation. 73 | /// 74 | /// # Errors 75 | /// 76 | /// This function will return `ValueWriteError` on any I/O error occurred while writing either the 77 | /// marker or the data. 78 | pub fn write_u16(wr: &mut W, val: u16) -> Result<(), ValueWriteError> { 79 | write_marker(wr, Marker::U16)?; 80 | wr.write_data_u16(val)?; 81 | Ok(()) 82 | } 83 | 84 | /// Encodes and attempts to write an `u32` value strictly as a 5-byte sequence into the given write. 85 | /// 86 | /// The first byte becomes the marker and the others will represent the data itself. 87 | /// 88 | /// Note, that this function will encode the given value in 5-byte sequence no matter what, even if 89 | /// the value can be represented using single byte as a positive fixnum. 90 | /// 91 | /// If you need to fit the given buffer efficiently use `write_uint` instead, which automatically 92 | /// selects the appropriate integer representation. 93 | /// 94 | /// # Errors 95 | /// 96 | /// This function will return `ValueWriteError` on any I/O error occurred while writing either the 97 | /// marker or the data. 98 | pub fn write_u32(wr: &mut W, val: u32) -> Result<(), ValueWriteError> { 99 | write_marker(wr, Marker::U32)?; 100 | wr.write_data_u32(val)?; 101 | Ok(()) 102 | } 103 | 104 | /// Encodes and attempts to write an `u64` value strictly as a 9-byte sequence into the given write. 105 | /// 106 | /// The first byte becomes the marker and the others will represent the data itself. 107 | /// 108 | /// Note, that this function will encode the given value in 9-byte sequence no matter what, even if 109 | /// the value can be represented using single byte as a positive fixnum. 110 | /// 111 | /// If you need to fit the given buffer efficiently use `write_uint` instead, which automatically 112 | /// selects the appropriate integer representation. 113 | /// 114 | /// # Errors 115 | /// 116 | /// This function will return `ValueWriteError` on any I/O error occurred while writing either the 117 | /// marker or the data. 118 | pub fn write_u64(wr: &mut W, val: u64) -> Result<(), ValueWriteError> { 119 | write_marker(wr, Marker::U64)?; 120 | wr.write_data_u64(val)?; 121 | Ok(()) 122 | } 123 | 124 | /// Encodes and attempts to write an `u8` value into the given write using the most efficient 125 | /// representation, returning the marker used. 126 | /// 127 | /// See [`write_uint`] for more info. 128 | pub fn write_uint8(wr: &mut W, val: u8) -> Result> { 129 | if val < 128 { 130 | write_pfix(wr, val) 131 | .and(Ok(Marker::FixPos(val))) 132 | .map_err(ValueWriteError::InvalidMarkerWrite) 133 | } else { 134 | write_u8(wr, val).and(Ok(Marker::U8)) 135 | } 136 | } 137 | 138 | /// Encodes and attempts to write an `u64` value into the given write using the most efficient 139 | /// representation, returning the marker used. 140 | /// 141 | /// This function obeys the MessagePack specification, which requires that the serializer SHOULD use 142 | /// the format which represents the data in the smallest number of bytes. 143 | /// 144 | /// The first byte becomes the marker and the others (if present, up to 9) will represent the data 145 | /// itself. 146 | /// 147 | /// # Errors 148 | /// 149 | /// This function will return `ValueWriteError` on any I/O error occurred while writing either the 150 | /// marker or the data. 151 | pub fn write_uint(wr: &mut W, val: u64) -> Result> { 152 | if val < 256 { 153 | write_uint8(wr, val as u8) 154 | } else if val < 65536 { 155 | write_u16(wr, val as u16).and(Ok(Marker::U16)) 156 | } else if val < 4294967296 { 157 | write_u32(wr, val as u32).and(Ok(Marker::U32)) 158 | } else { 159 | write_u64(wr, val).and(Ok(Marker::U64)) 160 | } 161 | } 162 | -------------------------------------------------------------------------------- /rmp/src/encode/vec.rs: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /rmp/src/errors.rs: -------------------------------------------------------------------------------- 1 | //! Internal error handling code, shared between encoding and decoding. 2 | //! 3 | //! This is used mainly for backwards compatibility and abstraction over std/no_std. 4 | 5 | /// An alias to the "default" error handling type. 6 | /// 7 | /// This is problematic because when working on `#[no_std]`, because there is no [`std::error::Error`] trait and also no [`std::io::Error`] type. 8 | /// 9 | /// Furthermore, this doesn't abstract over the differences between different implementations of [`RmpRead`](crate::decode::RmpRead)/[`RmpWrite`](crate::encode::RmpWrite). 10 | /// 11 | /// When working directly with bytes streams, the error type is actually [Infallible](core::convert::Infallible). 12 | /// 13 | /// For these two reasons, this type is deprecated 14 | #[cfg(feature = "std")] 15 | #[deprecated(note = "Doesn't abstract over RmpRead/RmpWrite (or work on no_std), use RmpRead::Error/RmpWrite::Error and RmpReadErr/RmpWriteErr instead")] 16 | pub type Error = ::std::io::Error; 17 | 18 | #[cfg(not(feature = "std"))] 19 | #[deprecated(note = "Doesn't work meaningfully on no_std")] 20 | pub type Error = ::core::convert::Infallible; 21 | 22 | /// Internal type used to abstract over the [`std::error::Error`] trait 23 | /// 24 | /// This is a nop in no-std environments. 25 | #[cfg(feature = "std")] 26 | #[doc(hidden)] 27 | pub trait MaybeErrBound: std::error::Error {} 28 | #[cfg(feature = "std")] 29 | impl MaybeErrBound for T {} 30 | #[cfg(not(feature = "std"))] 31 | #[doc(hidden)] 32 | pub trait MaybeErrBound {} 33 | #[cfg(not(feature = "std"))] 34 | impl MaybeErrBound for T {} 35 | -------------------------------------------------------------------------------- /rmp/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![doc = include_str!("../README.md")] 2 | #![cfg_attr(not(feature = "std"), no_std)] 3 | 4 | extern crate alloc; 5 | 6 | pub mod decode; 7 | pub mod encode; 8 | mod errors; 9 | mod marker; 10 | 11 | pub use crate::marker::Marker; 12 | 13 | /// Version of the MessagePack [spec](http://github.com/msgpack/msgpack/blob/master/spec.md). 14 | pub const MSGPACK_VERSION: u32 = 5; 15 | -------------------------------------------------------------------------------- /rmp/src/marker.rs: -------------------------------------------------------------------------------- 1 | const FIXSTR_SIZE : u8 = 0x1f; 2 | const FIXARRAY_SIZE : u8 = 0x0f; 3 | const FIXMAP_SIZE : u8 = 0x0f; 4 | 5 | /// Format markers. 6 | #[derive(Clone, Copy, Debug, PartialEq)] 7 | #[repr(u8)] 8 | pub enum Marker { 9 | FixPos(u8) = 0x00, 10 | FixMap(u8) = 0x80, 11 | FixArray(u8) = 0x90, 12 | FixStr(u8) = 0xa0, 13 | Null = 0xc0, 14 | /// Marked in MessagePack spec as never used. 15 | Reserved, 16 | False, 17 | True, 18 | Bin8, 19 | Bin16, 20 | Bin32, 21 | Ext8, 22 | Ext16, 23 | Ext32, 24 | F32, 25 | F64, 26 | U8, 27 | U16, 28 | U32, 29 | U64, 30 | I8, 31 | I16, 32 | I32, 33 | I64, 34 | FixExt1, 35 | FixExt2, 36 | FixExt4, 37 | FixExt8, 38 | FixExt16, 39 | Str8, 40 | Str16, 41 | Str32, 42 | Array16, 43 | Array32, 44 | Map16, 45 | Map32, 46 | FixNeg(i8) = 0xe0, 47 | } 48 | 49 | impl Marker { 50 | /// Construct a msgpack marker from a single byte. 51 | #[must_use] 52 | #[inline] 53 | pub const fn from_u8(n: u8) -> Self { 54 | match n { 55 | 0x00..=0x7f => Self::FixPos(n), 56 | 0x80..=0x8f => Self::FixMap(n & FIXMAP_SIZE), 57 | 0x90..=0x9f => Self::FixArray(n & FIXARRAY_SIZE), 58 | 0xa0..=0xbf => Self::FixStr(n & FIXSTR_SIZE), 59 | 0xc0 => Self::Null, 60 | // Marked in MessagePack spec as never used. 61 | 0xc1 => Self::Reserved, 62 | 0xc2 => Self::False, 63 | 0xc3 => Self::True, 64 | 0xc4 => Self::Bin8, 65 | 0xc5 => Self::Bin16, 66 | 0xc6 => Self::Bin32, 67 | 0xc7 => Self::Ext8, 68 | 0xc8 => Self::Ext16, 69 | 0xc9 => Self::Ext32, 70 | 0xca => Self::F32, 71 | 0xcb => Self::F64, 72 | 0xcc => Self::U8, 73 | 0xcd => Self::U16, 74 | 0xce => Self::U32, 75 | 0xcf => Self::U64, 76 | 0xd0 => Self::I8, 77 | 0xd1 => Self::I16, 78 | 0xd2 => Self::I32, 79 | 0xd3 => Self::I64, 80 | 0xd4 => Self::FixExt1, 81 | 0xd5 => Self::FixExt2, 82 | 0xd6 => Self::FixExt4, 83 | 0xd7 => Self::FixExt8, 84 | 0xd8 => Self::FixExt16, 85 | 0xd9 => Self::Str8, 86 | 0xda => Self::Str16, 87 | 0xdb => Self::Str32, 88 | 0xdc => Self::Array16, 89 | 0xdd => Self::Array32, 90 | 0xde => Self::Map16, 91 | 0xdf => Self::Map32, 92 | 0xe0..=0xff => Self::FixNeg(n as i8), 93 | } 94 | } 95 | 96 | /// Converts a marker object into a single-byte representation. 97 | #[must_use] 98 | #[inline] 99 | pub const fn to_u8(&self) -> u8 { 100 | match *self { 101 | Self::FixPos(val) => val, 102 | Self::FixNeg(val) => val as u8, 103 | 104 | Self::Null => 0xc0, 105 | 106 | Self::True => 0xc3, 107 | Self::False => 0xc2, 108 | 109 | Self::U8 => 0xcc, 110 | Self::U16 => 0xcd, 111 | Self::U32 => 0xce, 112 | Self::U64 => 0xcf, 113 | 114 | Self::I8 => 0xd0, 115 | Self::I16 => 0xd1, 116 | Self::I32 => 0xd2, 117 | Self::I64 => 0xd3, 118 | 119 | Self::F32 => 0xca, 120 | Self::F64 => 0xcb, 121 | 122 | Self::FixStr(len) => 0xa0 | (len & FIXSTR_SIZE), 123 | Self::Str8 => 0xd9, 124 | Self::Str16 => 0xda, 125 | Self::Str32 => 0xdb, 126 | 127 | Self::Bin8 => 0xc4, 128 | Self::Bin16 => 0xc5, 129 | Self::Bin32 => 0xc6, 130 | 131 | Self::FixArray(len) => 0x90 | (len & FIXARRAY_SIZE), 132 | Self::Array16 => 0xdc, 133 | Self::Array32 => 0xdd, 134 | 135 | Self::FixMap(len) => 0x80 | (len & FIXMAP_SIZE), 136 | Self::Map16 => 0xde, 137 | Self::Map32 => 0xdf, 138 | 139 | Self::FixExt1 => 0xd4, 140 | Self::FixExt2 => 0xd5, 141 | Self::FixExt4 => 0xd6, 142 | Self::FixExt8 => 0xd7, 143 | Self::FixExt16 => 0xd8, 144 | Self::Ext8 => 0xc7, 145 | Self::Ext16 => 0xc8, 146 | Self::Ext32 => 0xc9, 147 | 148 | Self::Reserved => 0xc1, 149 | } 150 | } 151 | } 152 | 153 | impl From for Marker { 154 | #[inline(always)] 155 | fn from(val: u8) -> Self { 156 | Self::from_u8(val) 157 | } 158 | } 159 | 160 | impl From for u8 { 161 | #[inline(always)] 162 | fn from(val: Marker) -> Self { 163 | val.to_u8() 164 | } 165 | } 166 | -------------------------------------------------------------------------------- /rmp/tests/func/decode/array.rs: -------------------------------------------------------------------------------- 1 | use super::Cursor; 2 | 3 | use rmp::decode::*; 4 | use rmp::Marker; 5 | 6 | #[test] 7 | fn from_empty_array_read_size() { 8 | let buf: &[u8] = &[0x90]; 9 | let mut cur = Cursor::new(buf); 10 | 11 | assert_eq!(0, read_array_len(&mut cur).unwrap()); 12 | assert_eq!(1, cur.position()); 13 | } 14 | 15 | #[test] 16 | fn from_fixarray_max_read_size() { 17 | let buf: &[u8] = &[ 18 | 0x9f, 19 | 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e 20 | ]; 21 | let mut cur = Cursor::new(buf); 22 | 23 | assert_eq!(15, read_array_len(&mut cur).unwrap()); 24 | assert_eq!(1, cur.position()); 25 | } 26 | 27 | #[test] 28 | fn from_array16_min_read_size() { 29 | let buf: &[u8] = &[0xdc, 0x00, 0x10]; 30 | let mut cur = Cursor::new(buf); 31 | 32 | assert_eq!(16, read_array_len(&mut cur).unwrap()); 33 | assert_eq!(3, cur.position()); 34 | } 35 | 36 | #[test] 37 | fn from_array16_max_read_size() { 38 | let buf: &[u8] = &[0xdc, 0xff, 0xff]; 39 | let mut cur = Cursor::new(buf); 40 | 41 | assert_eq!(65535, read_array_len(&mut cur).unwrap()); 42 | assert_eq!(3, cur.position()); 43 | } 44 | 45 | #[test] 46 | fn from_array16_unexpected_eof_read_size() { 47 | let buf: &[u8] = &[0xdc, 0xff]; 48 | let mut cur = Cursor::new(buf); 49 | 50 | read_array_len(&mut cur).err().unwrap(); 51 | assert!(cur.position() >= 1); 52 | } 53 | 54 | #[test] 55 | fn from_array32_min_read_size() { 56 | let buf: &[u8] = &[0xdd, 0x00, 0x00, 0x00, 0x00]; 57 | let mut cur = Cursor::new(buf); 58 | 59 | assert_eq!(0, read_array_len(&mut cur).unwrap()); 60 | assert_eq!(5, cur.position()); 61 | } 62 | 63 | #[test] 64 | fn from_array32_max_read_size() { 65 | let buf: &[u8] = &[0xdd, 0xff, 0xff, 0xff, 0xff]; 66 | let mut cur = Cursor::new(buf); 67 | 68 | assert_eq!(4294967295, read_array_len(&mut cur).unwrap()); 69 | assert_eq!(5, cur.position()); 70 | } 71 | 72 | #[test] 73 | fn from_array32_unexpected_eof_read_size() { 74 | let buf: &[u8] = &[0xdd, 0xff, 0xff, 0xff]; 75 | let mut cur = Cursor::new(buf); 76 | 77 | read_array_len(&mut cur).err().unwrap(); 78 | assert!(cur.position() >= 1); 79 | } 80 | 81 | #[test] 82 | fn from_null_read_array_len() { 83 | let buf: &[u8] = &[0xc0]; 84 | let mut cur = Cursor::new(buf); 85 | 86 | match read_array_len(&mut cur) { 87 | Err(ValueReadError::TypeMismatch(Marker::Null)) => (), 88 | other => panic!("unexpected result: {other:?}"), 89 | } 90 | assert_eq!(1, cur.position()); 91 | } 92 | -------------------------------------------------------------------------------- /rmp/tests/func/decode/bin.rs: -------------------------------------------------------------------------------- 1 | use super::Cursor; 2 | 3 | use rmp::decode::*; 4 | use rmp::Marker; 5 | 6 | #[test] 7 | fn from_bin8_min_read_len() { 8 | let buf: &[u8] = &[0xc4, 0x00]; 9 | let mut cur = Cursor::new(buf); 10 | 11 | assert_eq!(0, read_bin_len(&mut cur).unwrap()); 12 | assert_eq!(2, cur.position()); 13 | } 14 | 15 | #[test] 16 | fn from_bin8_max_read_len() { 17 | let buf: &[u8] = &[0xc4, 0xff]; 18 | let mut cur = Cursor::new(buf); 19 | 20 | assert_eq!(255, read_bin_len(&mut cur).unwrap()); 21 | assert_eq!(2, cur.position()); 22 | } 23 | 24 | #[test] 25 | fn from_bin8_eof_read_len() { 26 | let buf: &[u8] = &[0xc4]; 27 | let mut cur = Cursor::new(buf); 28 | 29 | read_bin_len(&mut cur).err().unwrap(); 30 | assert_eq!(1, cur.position()); 31 | } 32 | 33 | #[test] 34 | fn from_null_read_len() { 35 | let buf: &[u8] = &[0xc0]; 36 | let mut cur = Cursor::new(buf); 37 | 38 | match read_bin_len(&mut cur) { 39 | Err(ValueReadError::TypeMismatch(Marker::Null)) => (), 40 | other => panic!("unexpected result: {other:?}"), 41 | } 42 | assert_eq!(1, cur.position()); 43 | } 44 | 45 | #[test] 46 | fn from_bin16_max_read_len() { 47 | let buf: &[u8] = &[0xc5, 0xff, 0xff]; 48 | let mut cur = Cursor::new(buf); 49 | 50 | assert_eq!(65535, read_bin_len(&mut cur).unwrap()); 51 | assert_eq!(3, cur.position()); 52 | } 53 | 54 | #[test] 55 | fn from_bin32_max_read_len() { 56 | let buf: &[u8] = &[0xc6, 0xff, 0xff, 0xff, 0xff]; 57 | let mut cur = Cursor::new(buf); 58 | 59 | assert_eq!(4294967295, read_bin_len(&mut cur).unwrap()); 60 | assert_eq!(5, cur.position()); 61 | } 62 | -------------------------------------------------------------------------------- /rmp/tests/func/decode/bool.rs: -------------------------------------------------------------------------------- 1 | use super::Cursor; 2 | 3 | use rmp::decode::*; 4 | 5 | #[test] 6 | fn from_bool_false() { 7 | let buf = [0xc2]; 8 | let mut cur = Cursor::new(&buf[..]); 9 | 10 | assert!(!read_bool(&mut cur).unwrap()); 11 | assert_eq!(1, cur.position()); 12 | } 13 | 14 | #[test] 15 | fn from_bool_true() { 16 | let buf = [0xc3]; 17 | let mut cur = Cursor::new(&buf[..]); 18 | 19 | assert!(read_bool(&mut cur).unwrap()); 20 | assert_eq!(1, cur.position()); 21 | } 22 | -------------------------------------------------------------------------------- /rmp/tests/func/decode/ext.rs: -------------------------------------------------------------------------------- 1 | use super::Cursor; 2 | 3 | use rmp::decode::*; 4 | 5 | #[test] 6 | fn from_fixext1_read_fixext1() { 7 | let buf: &[u8] = &[0xd4, 0x01, 0x02]; 8 | let mut cur = Cursor::new(buf); 9 | 10 | assert_eq!((1, 2), read_fixext1(&mut cur).unwrap()); 11 | assert_eq!(3, cur.position()); 12 | } 13 | 14 | #[test] 15 | fn from_fixext2_read_fixext2() { 16 | let buf = [0xd5, 0x01, 0x00, 0x02]; 17 | let mut cur = Cursor::new(&buf[..]); 18 | 19 | assert_eq!((1, [0x00, 0x02]), read_fixext2(&mut cur).unwrap()); 20 | assert_eq!(4, cur.position()); 21 | } 22 | 23 | #[test] 24 | fn from_fixext4_read_fixext4() { 25 | let buf = [0xd6, 0x01, 0x00, 0x00, 0x00, 0x02]; 26 | let mut cur = Cursor::new(&buf[..]); 27 | 28 | assert_eq!( 29 | (1, [0x00, 0x00, 0x00, 0x02]), 30 | read_fixext4(&mut cur).unwrap() 31 | ); 32 | assert_eq!(6, cur.position()); 33 | } 34 | 35 | #[test] 36 | fn from_fixext8_read_fixext8() { 37 | let buf = [0xd7, 0x01, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08]; 38 | let mut cur = Cursor::new(&buf[..]); 39 | 40 | assert_eq!( 41 | (1, [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08]), 42 | read_fixext8(&mut cur).unwrap() 43 | ); 44 | assert_eq!(10, cur.position()); 45 | } 46 | 47 | #[test] 48 | fn from_fixext16_read_fixext16() { 49 | let buf = [ 50 | 0xd8, 51 | 0x01, 52 | 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 53 | 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 54 | ]; 55 | let mut cur = Cursor::new(&buf[..]); 56 | 57 | assert_eq!((1, [0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 58 | 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08]), 59 | read_fixext16(&mut cur).unwrap()); 60 | assert_eq!(18, cur.position()); 61 | } 62 | 63 | #[test] 64 | fn from_fixext1_read_ext_meta() { 65 | let buf: &[u8] = &[0xd4, 0x01]; 66 | let mut cur = Cursor::new(buf); 67 | 68 | assert_eq!( 69 | ExtMeta { typeid: 1, size: 1 }, 70 | read_ext_meta(&mut cur).unwrap() 71 | ); 72 | assert_eq!(2, cur.position()); 73 | } 74 | 75 | #[test] 76 | fn from_fixext2_read_ext_meta() { 77 | let buf: &[u8] = &[0xd5, 0x01]; 78 | let mut cur = Cursor::new(buf); 79 | 80 | assert_eq!( 81 | ExtMeta { typeid: 1, size: 2 }, 82 | read_ext_meta(&mut cur).unwrap() 83 | ); 84 | assert_eq!(2, cur.position()); 85 | } 86 | 87 | #[test] 88 | fn from_fixext4_read_ext_meta() { 89 | let buf: &[u8] = &[0xd6, 0x01]; 90 | let mut cur = Cursor::new(buf); 91 | 92 | assert_eq!( 93 | ExtMeta { typeid: 1, size: 4 }, 94 | read_ext_meta(&mut cur).unwrap() 95 | ); 96 | assert_eq!(2, cur.position()); 97 | } 98 | 99 | #[test] 100 | fn from_fixext8_read_ext_meta() { 101 | let buf: &[u8] = &[0xd7, 0x01]; 102 | let mut cur = Cursor::new(buf); 103 | 104 | assert_eq!( 105 | ExtMeta { typeid: 1, size: 8 }, 106 | read_ext_meta(&mut cur).unwrap() 107 | ); 108 | assert_eq!(2, cur.position()); 109 | } 110 | 111 | #[test] 112 | fn from_fixext16_read_ext_meta() { 113 | let buf: &[u8] = &[0xd8, 0x01]; 114 | let mut cur = Cursor::new(buf); 115 | 116 | assert_eq!(ExtMeta { typeid: 1, size: 16 }, read_ext_meta(&mut cur).unwrap()); 117 | assert_eq!(2, cur.position()); 118 | } 119 | 120 | #[test] 121 | fn from_ext8_read_ext_meta() { 122 | let buf: &[u8] = &[0xc7, 0xff, 0x01]; 123 | let mut cur = Cursor::new(buf); 124 | 125 | assert_eq!(ExtMeta { typeid: 1, size: 255 }, read_ext_meta(&mut cur).unwrap()); 126 | assert_eq!(3, cur.position()); 127 | } 128 | 129 | #[test] 130 | fn from_ext16_read_ext_meta() { 131 | let buf: &[u8] = &[0xc8, 0xff, 0xff, 0x01]; 132 | let mut cur = Cursor::new(buf); 133 | 134 | assert_eq!(ExtMeta { typeid: 1, size: 65535 }, read_ext_meta(&mut cur).unwrap()); 135 | assert_eq!(4, cur.position()); 136 | } 137 | 138 | #[test] 139 | fn from_ext32_read_ext_meta() { 140 | let buf: &[u8] = &[0xc9, 0xff, 0xff, 0xff, 0xff, 0x01]; 141 | let mut cur = Cursor::new(buf); 142 | 143 | assert_eq!(ExtMeta { typeid: 1, size: 4294967295 }, read_ext_meta(&mut cur).unwrap()); 144 | assert_eq!(6, cur.position()); 145 | } 146 | -------------------------------------------------------------------------------- /rmp/tests/func/decode/float.rs: -------------------------------------------------------------------------------- 1 | use super::Cursor; 2 | 3 | use rmp::decode::*; 4 | use rmp::Marker; 5 | 6 | #[test] 7 | fn from_f32_zero_plus() { 8 | let buf: &[u8] = &[0xca, 0x00, 0x00, 0x00, 0x00]; 9 | let mut cur = Cursor::new(buf); 10 | 11 | assert_eq!(0.0, read_f32(&mut cur).unwrap()); 12 | assert_eq!(5, cur.position()); 13 | } 14 | 15 | #[test] 16 | fn from_f32_max() { 17 | let buf: &[u8] = &[0xca, 0x7f, 0x7f, 0xff, 0xff]; 18 | let mut cur = Cursor::new(buf); 19 | 20 | assert_eq!(3.4028234e38_f32, read_f32(&mut cur).unwrap()); 21 | assert_eq!(5, cur.position()); 22 | } 23 | 24 | #[test] 25 | fn from_f32_inf() { 26 | use std::f32; 27 | 28 | let buf: &[u8] = &[0xca, 0x7f, 0x80, 0x00, 0x00]; 29 | let mut cur = Cursor::new(buf); 30 | 31 | assert_eq!(f32::INFINITY, read_f32(&mut cur).unwrap()); 32 | assert_eq!(5, cur.position()); 33 | } 34 | 35 | #[test] 36 | fn from_f32_neg_inf() { 37 | use std::f32; 38 | 39 | let buf: &[u8] = &[0xca, 0xff, 0x80, 0x00, 0x00]; 40 | let mut cur = Cursor::new(buf); 41 | 42 | assert_eq!(f32::NEG_INFINITY, read_f32(&mut cur).unwrap()); 43 | assert_eq!(5, cur.position()); 44 | } 45 | 46 | #[test] 47 | fn from_null_read_f32() { 48 | let buf: &[u8] = &[0xc0]; 49 | let mut cur = Cursor::new(buf); 50 | 51 | match read_f32(&mut cur) { 52 | Err(ValueReadError::TypeMismatch(Marker::Null)) => (), 53 | other => panic!("unexpected result: {other:?}"), 54 | } 55 | assert_eq!(1, cur.position()); 56 | } 57 | 58 | #[test] 59 | fn from_f64_zero_plus() { 60 | let buf: &[u8] = &[0xcb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; 61 | let mut cur = Cursor::new(buf); 62 | 63 | assert_eq!(0.0, read_f64(&mut cur).unwrap()); 64 | assert_eq!(9, cur.position()); 65 | } 66 | 67 | #[test] 68 | fn from_f64_zero_minus() { 69 | let buf: &[u8] = &[0xcb, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; 70 | let mut cur = Cursor::new(buf); 71 | 72 | assert_eq!(-0.0, read_f64(&mut cur).unwrap()); 73 | assert_eq!(9, cur.position()); 74 | } 75 | 76 | #[test] 77 | fn from_f64_inf() { 78 | use std::f64; 79 | 80 | let buf: &[u8] = &[0xcb, 0x7f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; 81 | let mut cur = Cursor::new(buf); 82 | 83 | assert_eq!(f64::INFINITY, read_f64(&mut cur).unwrap()); 84 | assert_eq!(9, cur.position()); 85 | } 86 | 87 | #[test] 88 | fn from_f64_neg_inf() { 89 | use std::f64; 90 | 91 | let buf: &[u8] = &[0xcb, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; 92 | let mut cur = Cursor::new(buf); 93 | 94 | assert_eq!(f64::NEG_INFINITY, read_f64(&mut cur).unwrap()); 95 | assert_eq!(9, cur.position()); 96 | } 97 | 98 | #[test] 99 | fn from_null_read_f64() { 100 | let buf: &[u8] = &[0xc0]; 101 | let mut cur = Cursor::new(buf); 102 | 103 | match read_f64(&mut cur) { 104 | Err(ValueReadError::TypeMismatch(Marker::Null)) => (), 105 | other => panic!("unexpected result: {other:?}"), 106 | } 107 | assert_eq!(1, cur.position()); 108 | } 109 | -------------------------------------------------------------------------------- /rmp/tests/func/decode/map.rs: -------------------------------------------------------------------------------- 1 | use super::Cursor; 2 | 3 | use rmp::decode::*; 4 | use rmp::Marker; 5 | 6 | #[test] 7 | fn from_fixmap_min_read_size() { 8 | let buf: &[u8] = &[0x80]; 9 | let mut cur = Cursor::new(buf); 10 | 11 | assert_eq!(0, read_map_len(&mut cur).unwrap()); 12 | assert_eq!(1, cur.position()); 13 | } 14 | 15 | #[test] 16 | fn from_fixmap_max_read_size() { 17 | let buf: &[u8] = &[0x8f]; 18 | let mut cur = Cursor::new(buf); 19 | 20 | assert_eq!(15, read_map_len(&mut cur).unwrap()); 21 | assert_eq!(1, cur.position()); 22 | } 23 | 24 | #[test] 25 | fn from_map16_min_read_size() { 26 | let buf: &[u8] = &[0xde, 0x00, 0x00]; 27 | let mut cur = Cursor::new(buf); 28 | 29 | assert_eq!(0, read_map_len(&mut cur).unwrap()); 30 | assert_eq!(3, cur.position()); 31 | } 32 | 33 | #[test] 34 | fn from_map16_max_read_size() { 35 | let buf: &[u8] = &[0xde, 0xff, 0xff]; 36 | let mut cur = Cursor::new(buf); 37 | 38 | assert_eq!(65535, read_map_len(&mut cur).unwrap()); 39 | assert_eq!(3, cur.position()); 40 | } 41 | 42 | #[test] 43 | fn from_map32_min_read_size() { 44 | let buf: &[u8] = &[0xdf, 0x00, 0x00, 0x00, 0x00]; 45 | let mut cur = Cursor::new(buf); 46 | 47 | assert_eq!(0, read_map_len(&mut cur).unwrap()); 48 | assert_eq!(5, cur.position()); 49 | } 50 | 51 | #[test] 52 | fn from_null_read_map_len() { 53 | let buf: &[u8] = &[0xc0, 0x00, 0x00, 0x00, 0x00]; 54 | let mut cur = Cursor::new(buf); 55 | 56 | match read_map_len(&mut cur) { 57 | Err(ValueReadError::TypeMismatch(Marker::Null)) => (), 58 | other => panic!("unexpected result: {other:?}"), 59 | } 60 | assert_eq!(1, cur.position()); 61 | } 62 | -------------------------------------------------------------------------------- /rmp/tests/func/decode/mod.rs: -------------------------------------------------------------------------------- 1 | mod array; 2 | mod bin; 3 | mod bool; 4 | mod ext; 5 | mod float; 6 | mod map; 7 | mod null; 8 | mod sint; 9 | mod string; 10 | mod uint; 11 | 12 | #[cfg(feature = "std")] 13 | pub type Cursor<'a> = std::io::Cursor<&'a [u8]>; 14 | #[cfg(not(feature = "std"))] 15 | pub type Cursor<'a> = rmp::decode::Bytes<'a>; 16 | -------------------------------------------------------------------------------- /rmp/tests/func/decode/null.rs: -------------------------------------------------------------------------------- 1 | use super::Cursor; 2 | 3 | use rmp::decode::*; 4 | 5 | #[test] 6 | fn pass() { 7 | let buf = [0xc0]; 8 | let mut cur = Cursor::new(&buf[..]); 9 | 10 | assert_eq!((), read_nil(&mut cur).unwrap()); 11 | assert_eq!(1, cur.position()); 12 | } 13 | 14 | #[test] 15 | fn fail_invalid_marker() { 16 | let buf = [0xc1]; 17 | let mut cur = Cursor::new(&buf[..]); 18 | 19 | match read_nil(&mut cur) { 20 | Err(ValueReadError::TypeMismatch(..)) => (), 21 | other => panic!("unexpected result: {other:?}"), 22 | } 23 | assert_eq!(1, cur.position()); 24 | } 25 | 26 | #[test] 27 | fn fail_unexpected_eof() { 28 | let buf = []; 29 | let mut cur = Cursor::new(&buf[..]); 30 | 31 | read_nil(&mut cur).err().unwrap(); 32 | assert_eq!(0, cur.position()); 33 | } 34 | 35 | #[test] 36 | #[cfg(feature = "std")] 37 | fn interrupt_safe() { 38 | use std::io::{Error, ErrorKind, Read}; 39 | 40 | struct MockRead { state_: u8 } 41 | 42 | impl MockRead { 43 | fn state(&self) -> u8 { self.state_ } 44 | } 45 | 46 | impl Read for MockRead { 47 | fn read(&mut self, buf: &mut [u8]) -> Result { 48 | if self.state_ == 0 { 49 | self.state_ = 1; 50 | Err(Error::new(ErrorKind::Interrupted, "interrupted")) 51 | } else { 52 | assert!(!buf.is_empty()); 53 | 54 | buf[0] = 0xc0; 55 | Ok(1) 56 | } 57 | } 58 | } 59 | 60 | let mut cur = MockRead { state_: 0 }; 61 | 62 | // The function is interruption-safe, the first read should succeed. 63 | read_nil(&mut cur).unwrap(); 64 | 65 | assert_eq!(1, cur.state()); 66 | } 67 | -------------------------------------------------------------------------------- /rmp/tests/func/decode/sint.rs: -------------------------------------------------------------------------------- 1 | use super::Cursor; 2 | 3 | use rmp::decode::*; 4 | use rmp::Marker; 5 | 6 | #[test] 7 | fn from_nfix_min() { 8 | let buf = [0xe0]; 9 | let mut cur = Cursor::new(&buf[..]); 10 | 11 | assert_eq!(-32, read_nfix(&mut cur).unwrap()); 12 | assert_eq!(1, cur.position()); 13 | } 14 | 15 | #[test] 16 | fn from_nfix_max() { 17 | let buf = [0xff]; 18 | let mut cur = Cursor::new(&buf[..]); 19 | 20 | assert_eq!(-1, read_nfix(&mut cur).unwrap()); 21 | assert_eq!(1, cur.position()); 22 | } 23 | 24 | #[test] 25 | fn from_nfix_type_mismatch() { 26 | let buf = &[0xc0]; 27 | let mut cur = Cursor::new(&buf[..]); 28 | 29 | match read_nfix(&mut cur) { 30 | Err(ValueReadError::TypeMismatch(..)) => (), 31 | other => panic!("unexpected result: {other:?}"), 32 | } 33 | assert_eq!(1, cur.position()); 34 | } 35 | 36 | #[test] 37 | fn from_i8_min() { 38 | let buf = [0xd0, 0x80]; 39 | let mut cur = Cursor::new(&buf[..]); 40 | 41 | assert_eq!(-128, read_i8(&mut cur).unwrap()); 42 | assert_eq!(2, cur.position()); 43 | } 44 | 45 | #[test] 46 | fn from_i8_max() { 47 | let buf = [0xd0, 0x7f]; 48 | let mut cur = Cursor::new(&buf[..]); 49 | 50 | assert_eq!(127, read_i8(&mut cur).unwrap()); 51 | assert_eq!(2, cur.position()); 52 | } 53 | 54 | #[test] 55 | fn from_i8_type_mismatch() { 56 | let buf = [0xc0, 0x80]; 57 | let mut cur = Cursor::new(&buf[..]); 58 | 59 | match read_i8(&mut cur) { 60 | Err(ValueReadError::TypeMismatch(Marker::Null)) => (), 61 | other => panic!("unexpected result: {other:?}"), 62 | } 63 | assert_eq!(1, cur.position()); 64 | } 65 | 66 | #[test] 67 | fn from_i8_unexpected_eof() { 68 | let buf = [0xd0]; 69 | let mut cur = Cursor::new(&buf[..]); 70 | 71 | read_i8(&mut cur).err().unwrap(); 72 | assert_eq!(1, cur.position()); 73 | } 74 | 75 | #[test] 76 | fn from_i16_min() { 77 | let buf = [0xd1, 0x80, 0x00]; 78 | let mut cur = Cursor::new(&buf[..]); 79 | 80 | assert_eq!(-32768, read_i16(&mut cur).unwrap()); 81 | assert_eq!(3, cur.position()); 82 | } 83 | 84 | #[test] 85 | fn from_i16_max() { 86 | let buf = [0xd1, 0x7f, 0xff]; 87 | let mut cur = Cursor::new(&buf[..]); 88 | 89 | assert_eq!(32767, read_i16(&mut cur).unwrap()); 90 | assert_eq!(3, cur.position()); 91 | } 92 | 93 | #[test] 94 | fn from_i16_type_mismatch() { 95 | let buf = [0xc0, 0x80, 0x00]; 96 | let mut cur = Cursor::new(&buf[..]); 97 | 98 | match read_i16(&mut cur) { 99 | Err(ValueReadError::TypeMismatch(Marker::Null)) => (), 100 | other => panic!("unexpected result: {other:?}"), 101 | } 102 | assert_eq!(1, cur.position()); 103 | } 104 | 105 | #[test] 106 | fn from_i16_unexpected_eof() { 107 | let buf = [0xd1, 0x7f]; 108 | let mut cur = Cursor::new(&buf[..]); 109 | 110 | read_i16(&mut cur).err().unwrap(); 111 | assert!(cur.position() >= 1); 112 | } 113 | 114 | #[test] 115 | fn from_i32_min() { 116 | let buf = [0xd2, 0x80, 0x00, 0x00, 0x00]; 117 | let mut cur = Cursor::new(&buf[..]); 118 | 119 | assert_eq!(-2_147_483_648, read_i32(&mut cur).unwrap()); 120 | assert_eq!(5, cur.position()); 121 | } 122 | 123 | #[test] 124 | fn from_i32_max() { 125 | let buf = &[0xd2, 0x7f, 0xff, 0xff, 0xff]; 126 | let mut cur = Cursor::new(&buf[..]); 127 | 128 | assert_eq!(2147483647, read_i32(&mut cur).unwrap()); 129 | assert_eq!(5, cur.position()); 130 | } 131 | 132 | #[test] 133 | fn from_i32_type_mismatch() { 134 | let buf = &[0xc0, 0x80, 0x00, 0x00, 0x00]; 135 | let mut cur = Cursor::new(&buf[..]); 136 | 137 | match read_i32(&mut cur) { 138 | Err(ValueReadError::TypeMismatch(Marker::Null)) => (), 139 | other => panic!("unexpected result: {other:?}"), 140 | } 141 | assert_eq!(1, cur.position()); 142 | } 143 | 144 | #[test] 145 | fn from_i32_unexpected_eof() { 146 | let buf = &[0xd2, 0x7f, 0xff, 0xff]; 147 | let mut cur = Cursor::new(&buf[..]); 148 | 149 | read_i32(&mut cur).err().unwrap(); 150 | assert!(cur.position() >= 1); 151 | } 152 | 153 | #[test] 154 | fn from_i64_min() { 155 | let buf = [0xd3, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; 156 | let mut cur = Cursor::new(&buf[..]); 157 | 158 | assert_eq!(-9223372036854775808, read_i64(&mut cur).unwrap()); 159 | assert_eq!(9, cur.position()); 160 | } 161 | 162 | #[test] 163 | fn from_i64_max() { 164 | let buf = [0xd3, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]; 165 | let mut cur = Cursor::new(&buf[..]); 166 | 167 | assert_eq!(9223372036854775807, read_i64(&mut cur).unwrap()); 168 | assert_eq!(9, cur.position()); 169 | } 170 | 171 | #[test] 172 | fn from_i64_type_mismatch() { 173 | let buf = [0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; 174 | let mut cur = Cursor::new(&buf[..]); 175 | 176 | match read_i64(&mut cur) { 177 | Err(ValueReadError::TypeMismatch(Marker::Null)) => (), 178 | other => panic!("unexpected result: {other:?}"), 179 | } 180 | assert_eq!(1, cur.position()); 181 | } 182 | 183 | #[test] 184 | fn from_i64_unexpected_eof() { 185 | let buf = [0xd3, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]; 186 | let mut cur = Cursor::new(&buf[..]); 187 | 188 | read_i64(&mut cur).err().unwrap(); 189 | assert!(cur.position() >= 1); 190 | } 191 | 192 | #[test] 193 | fn from_nfix_min_read_int() { 194 | let buf: &[u8] = &[0xe0]; 195 | let mut cur = Cursor::new(buf); 196 | 197 | assert_eq!(-32, read_int(&mut cur).unwrap()); 198 | assert_eq!(1, cur.position()); 199 | } 200 | 201 | #[test] 202 | fn from_nfix_max_read_int() { 203 | let buf: &[u8] = &[0xff]; 204 | let mut cur = Cursor::new(buf); 205 | 206 | assert_eq!(-1, read_int(&mut cur).unwrap()); 207 | assert_eq!(1, cur.position()); 208 | } 209 | 210 | #[test] 211 | fn from_i8_min_read_int() { 212 | let buf: &[u8] = &[0xd0, 0x80]; 213 | let mut cur = Cursor::new(buf); 214 | 215 | assert_eq!(-128, read_int(&mut cur).unwrap()); 216 | assert_eq!(2, cur.position()); 217 | } 218 | 219 | #[test] 220 | fn from_i8_max_read_int() { 221 | let buf: &[u8] = &[0xd0, 0x7f]; 222 | let mut cur = Cursor::new(buf); 223 | 224 | assert_eq!(127, read_int(&mut cur).unwrap()); 225 | assert_eq!(2, cur.position()); 226 | } 227 | 228 | #[test] 229 | fn from_i16_min_read_int() { 230 | let buf: &[u8] = &[0xd1, 0x80, 0x00]; 231 | let mut cur = Cursor::new(buf); 232 | 233 | assert_eq!(-32768, read_int(&mut cur).unwrap()); 234 | assert_eq!(3, cur.position()); 235 | } 236 | 237 | #[test] 238 | fn from_i16_max_read_int() { 239 | let buf: &[u8] = &[0xd1, 0x7f, 0xff]; 240 | let mut cur = Cursor::new(buf); 241 | 242 | assert_eq!(32767, read_int(&mut cur).unwrap()); 243 | assert_eq!(3, cur.position()); 244 | } 245 | 246 | #[test] 247 | fn from_i32_min_read_int() { 248 | let buf: &[u8] = &[0xd2, 0x80, 0x00, 0x00, 0x00]; 249 | let mut cur = Cursor::new(buf); 250 | 251 | assert_eq!(-2147483648, read_int(&mut cur).unwrap()); 252 | assert_eq!(5, cur.position()); 253 | } 254 | 255 | #[test] 256 | fn from_i32_max_read_int() { 257 | let buf: &[u8] = &[0xd2, 0x7f, 0xff, 0xff, 0xff]; 258 | let mut cur = Cursor::new(buf); 259 | 260 | assert_eq!(2147483647, read_int(&mut cur).unwrap()); 261 | assert_eq!(5, cur.position()); 262 | } 263 | 264 | #[test] 265 | fn from_i64_min_read_int() { 266 | let buf: &[u8] = &[0xd3, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; 267 | let mut cur = Cursor::new(buf); 268 | 269 | assert_eq!(-9223372036854775808i64, read_int(&mut cur).unwrap()); 270 | assert_eq!(9, cur.position()); 271 | } 272 | 273 | #[test] 274 | fn from_i64_max_read_int() { 275 | let buf: &[u8] = &[0xd3, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]; 276 | let mut cur = Cursor::new(buf); 277 | 278 | assert_eq!(9223372036854775807i64, read_int(&mut cur).unwrap()); 279 | assert_eq!(9, cur.position()); 280 | } 281 | -------------------------------------------------------------------------------- /rmp/tests/func/decode/string.rs: -------------------------------------------------------------------------------- 1 | use super::Cursor; 2 | 3 | use rmp::decode::*; 4 | use rmp::Marker; 5 | 6 | #[test] 7 | fn from_fixstr_min_read_str_len() { 8 | let buf: &[u8] = &[0xa0]; 9 | let mut cur = Cursor::new(buf); 10 | 11 | assert_eq!(0, read_str_len(&mut cur).unwrap()); 12 | assert_eq!(1, cur.position()); 13 | } 14 | 15 | #[test] 16 | fn from_fixstr_rnd_read_str_len() { 17 | let buf: &[u8] = &[0xaa]; 18 | let mut cur = Cursor::new(buf); 19 | 20 | assert_eq!(10, read_str_len(&mut cur).unwrap()); 21 | assert_eq!(1, cur.position()); 22 | } 23 | 24 | #[test] 25 | fn from_fixstr_max_read_str_len() { 26 | let buf: &[u8] = &[0xbf]; 27 | let mut cur = Cursor::new(buf); 28 | 29 | assert_eq!(31, read_str_len(&mut cur).unwrap()); 30 | assert_eq!(1, cur.position()); 31 | } 32 | 33 | #[test] 34 | fn from_str8_min_read_str_len() { 35 | let buf: &[u8] = &[0xd9, 0x00]; 36 | let mut cur = Cursor::new(buf); 37 | 38 | assert_eq!(0, read_str_len(&mut cur).unwrap()); 39 | assert_eq!(2, cur.position()); 40 | } 41 | 42 | #[test] 43 | fn from_str8_rnd_read_str_len() { 44 | let buf: &[u8] = &[0xd9, 0x0a]; 45 | let mut cur = Cursor::new(buf); 46 | 47 | assert_eq!(10, read_str_len(&mut cur).unwrap()); 48 | assert_eq!(2, cur.position()); 49 | } 50 | 51 | #[test] 52 | fn from_str8_read_str_len_eof() { 53 | let buf: &[u8] = &[0xd9]; 54 | let mut cur = Cursor::new(buf); 55 | 56 | read_str_len(&mut cur).err().unwrap(); 57 | assert_eq!(1, cur.position()); 58 | } 59 | 60 | #[test] 61 | fn from_str8_max_read_str_len() { 62 | let buf: &[u8] = &[0xd9, 0xff]; 63 | let mut cur = Cursor::new(buf); 64 | 65 | assert_eq!(255, read_str_len(&mut cur).unwrap()); 66 | assert_eq!(2, cur.position()); 67 | } 68 | 69 | #[test] 70 | fn from_str16_min_read_str_len() { 71 | let buf: &[u8] = &[0xda, 0x00, 0x00]; 72 | let mut cur = Cursor::new(buf); 73 | 74 | assert_eq!(0, read_str_len(&mut cur).unwrap()); 75 | assert_eq!(3, cur.position()); 76 | } 77 | 78 | #[test] 79 | fn from_str16_max_read_str_len() { 80 | let buf: &[u8] = &[0xda, 0xff, 0xff]; 81 | let mut cur = Cursor::new(buf); 82 | 83 | assert_eq!(65535, read_str_len(&mut cur).unwrap()); 84 | assert_eq!(3, cur.position()); 85 | } 86 | 87 | #[test] 88 | fn from_str16_read_str_len_eof() { 89 | let buf: &[u8] = &[0xda, 0x00]; 90 | let mut cur = Cursor::new(buf); 91 | 92 | read_str_len(&mut cur).err().unwrap(); 93 | assert!(cur.position() >= 1); 94 | } 95 | 96 | #[test] 97 | fn from_str32_min_read_str_len() { 98 | let buf: &[u8] = &[0xdb, 0x00, 0x00, 0x00, 0x00]; 99 | let mut cur = Cursor::new(buf); 100 | 101 | assert_eq!(0, read_str_len(&mut cur).unwrap()); 102 | assert_eq!(5, cur.position()); 103 | } 104 | 105 | #[test] 106 | fn from_str32_max_read_str_len() { 107 | let buf: &[u8] = &[0xdb, 0xff, 0xff, 0xff, 0xff]; 108 | let mut cur = Cursor::new(buf); 109 | 110 | assert_eq!(4294967295, read_str_len(&mut cur).unwrap()); 111 | assert_eq!(5, cur.position()); 112 | } 113 | 114 | #[test] 115 | fn from_str32_read_str_len_eof() { 116 | let buf: &[u8] = &[0xdb, 0x00, 0x00, 0x00]; 117 | let mut cur = Cursor::new(buf); 118 | 119 | read_str_len(&mut cur).err().unwrap(); 120 | assert!(cur.position() >= 1); 121 | } 122 | 123 | #[test] 124 | fn from_null_read_str_len() { 125 | let buf: &[u8] = &[0xc0]; 126 | let mut cur = Cursor::new(buf); 127 | 128 | match read_str_len(&mut cur) { 129 | Err(ValueReadError::TypeMismatch(Marker::Null)) => (), 130 | other => panic!("unexpected result: {other:?}"), 131 | } 132 | assert_eq!(1, cur.position()); 133 | } 134 | 135 | #[test] 136 | fn from_str_strfix() { 137 | let buf: &[u8] = &[0xaa, 0x6c, 0x65, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65]; 138 | let mut cur = Cursor::new(buf); 139 | 140 | let out: &mut [u8] = &mut [0u8; 16]; 141 | 142 | assert_eq!("le message", read_str(&mut cur, out).unwrap()); 143 | assert_eq!(11, cur.position()); 144 | } 145 | 146 | #[test] 147 | fn from_str_strfix_extra_data() { 148 | let buf: &[u8] = &[0xaa, 0x6c, 0x65, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x00]; 149 | let mut cur = Cursor::new(buf); 150 | 151 | let out: &mut [u8] = &mut [0u8; 16]; 152 | 153 | assert_eq!("le message", read_str(&mut cur, out).unwrap()); 154 | assert_eq!(11, cur.position()); 155 | } 156 | 157 | #[test] 158 | fn from_str_strfix_exact_buffer() { 159 | let buf: &[u8] = &[0xaa, 0x6c, 0x65, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65]; 160 | let mut cur = Cursor::new(buf); 161 | 162 | let out: &mut [u8] = &mut [0u8; 10]; 163 | 164 | assert_eq!("le message", read_str(&mut cur, out).unwrap()); 165 | assert_eq!(11, cur.position()); 166 | } 167 | 168 | #[test] 169 | fn from_str_strfix_invalid_utf8() { 170 | // Invalid 2 Octet Sequence. 171 | let buf: &[u8] = &[0xa2, 0xc3, 0x28]; 172 | let mut cur = Cursor::new(buf); 173 | 174 | let out: &mut [u8] = &mut [0u8; 16]; 175 | 176 | match read_str(&mut cur, out) { 177 | Err(DecodeStringError::InvalidUtf8(raw, _)) => { 178 | assert_eq!(&[0xc3, 0x28], raw); 179 | } 180 | other => panic!("unexpected result: {other:?}"), 181 | } 182 | 183 | assert_eq!(3, cur.position()); 184 | } 185 | 186 | #[test] 187 | fn from_str_strfix_buffer_too_small() { 188 | let buf: &[u8] = &[0xaa, 0x6c, 0x65, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65]; 189 | let mut cur = Cursor::new(buf); 190 | 191 | let out: &mut [u8] = &mut [0u8; 9]; 192 | 193 | match read_str(&mut cur, out) { 194 | Err(DecodeStringError::BufferSizeTooSmall(10)) => (), 195 | other => panic!("unexpected result: {other:?}"), 196 | } 197 | assert_eq!(1, cur.position()); 198 | } 199 | 200 | #[test] 201 | fn from_str_strfix_decode_from_slice() { 202 | // Wrap an incomplete buffer into the Cursor to see how many bytes were consumed. 203 | let mut buf = vec![0xaa, 0x6c, 0x65, 0x20, 0x6d, 0x65, 0x73]; 204 | assert!(read_str_from_slice(&buf).is_err()); 205 | 206 | // ... complete the buffer and try to parse again. 207 | buf.append(&mut vec![0x73, 0x61, 0x67, 0x65]); 208 | assert_eq!(("le message", &[][..]), read_str_from_slice(&buf).unwrap()); 209 | } 210 | 211 | #[test] 212 | fn from_str_strfix_decode_from_slice_with_trailing_bytes() { 213 | let buf = vec![ 214 | 0xaa, 0x6c, 0x65, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x01, 0x02, 0x03, 215 | ]; 216 | 217 | assert_eq!( 218 | ("le message", &[0x01, 0x02, 0x03][..]), 219 | read_str_from_slice(&buf).unwrap() 220 | ); 221 | } 222 | 223 | #[test] 224 | fn example_process_sequence_of_strings() { 225 | // Encoded: 'Unpacking', 'multiple', 'strings'. 226 | let vec = [ 227 | 0xa9, 0x55, 0x6e, 0x70, 0x61, 0x63, 0x6b, 0x69, 0x6e, 0x67, 228 | 0xa8, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0xa7, 229 | 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x73 230 | ]; 231 | 232 | let mut chunks = Vec::new(); 233 | let mut unparsed = &vec[..]; 234 | loop { 235 | match read_str_from_slice(unparsed) { 236 | Ok((chunk, tail)) => { 237 | chunks.push(chunk); 238 | unparsed = tail; 239 | } 240 | Err(..) => break, 241 | } 242 | } 243 | 244 | assert_eq!(["Unpacking", "multiple", "strings"], chunks[..]); 245 | } 246 | -------------------------------------------------------------------------------- /rmp/tests/func/decode/uint.rs: -------------------------------------------------------------------------------- 1 | use super::Cursor; 2 | 3 | use rmp::decode::*; 4 | use rmp::Marker; 5 | 6 | #[test] 7 | fn from_positive_fixnum() { 8 | let buf = [0x00, 0x7f, 0x20]; 9 | let mut cur = Cursor::new(&buf[..]); 10 | 11 | assert_eq!(0u8, read_pfix(&mut cur).unwrap()); 12 | assert_eq!(1, cur.position()); 13 | 14 | assert_eq!(127u8, read_pfix(&mut cur).unwrap()); 15 | assert_eq!(2, cur.position()); 16 | 17 | assert_eq!(32u8, read_pfix(&mut cur).unwrap()); 18 | assert_eq!(3, cur.position()); 19 | } 20 | 21 | #[test] 22 | fn from_u8_min() { 23 | let buf = [0xcc, 0x00]; 24 | let mut cur = Cursor::new(&buf[..]); 25 | 26 | assert_eq!(0, read_u8(&mut cur).unwrap()); 27 | assert_eq!(2, cur.position()); 28 | } 29 | 30 | #[test] 31 | fn from_u8_max() { 32 | let buf = [0xcc, 0xff]; 33 | let mut cur = Cursor::new(&buf[..]); 34 | 35 | assert_eq!(255, read_u8(&mut cur).unwrap()); 36 | assert_eq!(2, cur.position()); 37 | } 38 | 39 | #[test] 40 | fn from_u8_type_mismatch() { 41 | let buf = [0xc0, 0x80]; 42 | let mut cur = Cursor::new(&buf[..]); 43 | 44 | match read_u8(&mut cur) { 45 | Err(ValueReadError::TypeMismatch(Marker::Null)) => (), 46 | other => panic!("unexpected result: {other:?}"), 47 | } 48 | assert_eq!(1, cur.position()); 49 | } 50 | 51 | #[test] 52 | fn from_u8_unexpected_eof() { 53 | let buf = [0xcc]; 54 | let mut cur = Cursor::new(&buf[..]); 55 | 56 | read_u8(&mut cur).err().unwrap(); 57 | assert_eq!(1, cur.position()); 58 | } 59 | 60 | #[test] 61 | fn from_u16_min() { 62 | let buf = [0xcd, 0x00, 0x00]; 63 | let mut cur = Cursor::new(&buf[..]); 64 | 65 | assert_eq!(0, read_u16(&mut cur).unwrap()); 66 | assert_eq!(3, cur.position()); 67 | } 68 | 69 | #[test] 70 | fn from_u32_max() { 71 | let buf = [0xce, 0xff, 0xff, 0xff, 0xff]; 72 | let mut cur = Cursor::new(&buf[..]); 73 | 74 | assert_eq!(4294967295, read_u32(&mut cur).unwrap()); 75 | assert_eq!(5, cur.position()); 76 | } 77 | 78 | #[test] 79 | fn from_unsigned_fixnum_read_int() { 80 | let buf = [0x00, 0x7f, 0x20]; 81 | let mut cur = Cursor::new(&buf[..]); 82 | 83 | assert_eq!(0u64, read_int(&mut cur).unwrap()); 84 | assert_eq!(1, cur.position()); 85 | 86 | assert_eq!(127u64, read_int(&mut cur).unwrap()); 87 | assert_eq!(2, cur.position()); 88 | 89 | assert_eq!(32u64, read_int(&mut cur).unwrap()); 90 | assert_eq!(3, cur.position()); 91 | } 92 | 93 | #[test] 94 | fn from_unsigned_u8_read_int() { 95 | let buf = [0xcc, 0x80, 0xcc, 0xff]; 96 | let mut cur = Cursor::new(&buf[..]); 97 | 98 | assert_eq!(128u64, read_int(&mut cur).unwrap()); 99 | assert_eq!(2, cur.position()); 100 | 101 | assert_eq!(255u64, read_int(&mut cur).unwrap()); 102 | assert_eq!(4, cur.position()); 103 | } 104 | 105 | #[test] 106 | fn from_unsigned_u8_incomplete_read_int() { 107 | let buf = [0xcc]; 108 | let mut cur = Cursor::new(&buf[..]); 109 | 110 | read_int::(&mut cur).err().unwrap(); 111 | assert_eq!(1, cur.position()); 112 | } 113 | 114 | #[test] 115 | fn from_unsigned_u16_read_int() { 116 | let buf = [0xcd, 0x01, 0x00, 0xcd, 0xff, 0xff]; 117 | let mut cur = Cursor::new(&buf[..]); 118 | 119 | assert_eq!(256u64, read_int(&mut cur).unwrap()); 120 | assert_eq!(3, cur.position()); 121 | 122 | assert_eq!(65535u64, read_int(&mut cur).unwrap()); 123 | assert_eq!(6, cur.position()); 124 | } 125 | 126 | #[test] 127 | fn from_unsigned_u16_incomplete_read_int() { 128 | let buf = [0xcd]; 129 | let mut cur = Cursor::new(&buf[..]); 130 | 131 | read_int::(&mut cur).err().unwrap(); 132 | assert_eq!(1, cur.position()); 133 | } 134 | 135 | #[test] 136 | fn from_unsigned_u32_read_int() { 137 | let buf = [0xce, 0x00, 0x01, 0x00, 0x00, 0xce, 0xff, 0xff, 0xff, 0xff]; 138 | let mut cur = Cursor::new(&buf[..]); 139 | 140 | assert_eq!(65536u64, read_int(&mut cur).unwrap()); 141 | assert_eq!(5, cur.position()); 142 | 143 | assert_eq!(4294967295u64, read_int(&mut cur).unwrap()); 144 | assert_eq!(10, cur.position()); 145 | } 146 | 147 | #[test] 148 | fn from_unsigned_u32_incomplete_read_int() { 149 | let buf = [0xce]; 150 | let mut cur = Cursor::new(&buf[..]); 151 | 152 | read_int::(&mut cur).err().unwrap(); 153 | assert_eq!(1, cur.position()); 154 | } 155 | 156 | #[test] 157 | fn from_unsigned_u64_read_int() { 158 | let buf = [ 159 | 0xcf, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 160 | 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff 161 | ]; 162 | let mut cur = Cursor::new(&buf[..]); 163 | 164 | assert_eq!(4294967296u64, read_int(&mut cur).unwrap()); 165 | assert_eq!(9, cur.position()); 166 | 167 | assert_eq!(18446744073709551615u64, read_int(&mut cur).unwrap()); 168 | assert_eq!(18, cur.position()); 169 | } 170 | 171 | #[test] 172 | fn from_unsigned_u64_incomplete_read_int() { 173 | let buf = [0xcf]; 174 | let mut cur = Cursor::new(&buf[..]); 175 | 176 | read_int::(&mut cur).err().unwrap(); 177 | assert_eq!(1, cur.position()); 178 | } 179 | 180 | #[test] 181 | fn from_unsigned_invalid_marker_read_int() { 182 | let buf = [0xc0]; 183 | let mut cur = Cursor::new(&buf[..]); 184 | 185 | match read_int::(&mut cur) { 186 | Err(NumValueReadError::TypeMismatch(Marker::Null)) => (), 187 | other => panic!("unexpected result: {other:?}"), 188 | } 189 | assert_eq!(1, cur.position()); 190 | } 191 | 192 | #[test] 193 | fn from_unsigned_invalid_unknown_marker_read_int() { 194 | let buf = [0xc1]; 195 | let mut cur = Cursor::new(&buf[..]); 196 | 197 | match read_int::(&mut cur) { 198 | Err(NumValueReadError::TypeMismatch(Marker::Reserved)) => (), 199 | other => panic!("unexpected result: {other:?}"), 200 | } 201 | assert_eq!(1, cur.position()); 202 | } 203 | -------------------------------------------------------------------------------- /rmp/tests/func/encode/array.rs: -------------------------------------------------------------------------------- 1 | use rmp::encode::*; 2 | use rmp::Marker; 3 | 4 | #[test] 5 | fn pass_pack_len_fix() { 6 | let mut buf = [0x00]; 7 | 8 | assert_eq!( 9 | Marker::FixArray(15), 10 | write_array_len(&mut &mut buf[..], 15).unwrap() 11 | ); 12 | 13 | assert_eq!([0x9f], buf); 14 | } 15 | 16 | #[test] 17 | fn pass_pack_len_u16() { 18 | let mut buf = [0x00, 0x00, 0x00]; 19 | 20 | assert_eq!( 21 | Marker::Array16, 22 | write_array_len(&mut &mut buf[..], 65535).unwrap() 23 | ); 24 | 25 | assert_eq!([0xdc, 0xff, 0xff], buf); 26 | } 27 | 28 | #[test] 29 | fn pass_pack_len_u32() { 30 | let mut buf = [0x00, 0x00, 0x00, 0x00, 0x00]; 31 | 32 | assert_eq!( 33 | Marker::Array32, 34 | write_array_len(&mut &mut buf[..], 4294967295).unwrap() 35 | ); 36 | 37 | assert_eq!([0xdd, 0xff, 0xff, 0xff, 0xff], buf); 38 | } 39 | -------------------------------------------------------------------------------- /rmp/tests/func/encode/bin.rs: -------------------------------------------------------------------------------- 1 | use rmp::encode::*; 2 | use rmp::Marker; 3 | 4 | #[test] 5 | fn pass_pack_len_u8() { 6 | let mut buf = [0x00, 0x00]; 7 | 8 | assert_eq!(Marker::Bin8, write_bin_len(&mut &mut buf[..], 255).unwrap()); 9 | 10 | assert_eq!([0xc4, 0xff], buf); 11 | } 12 | 13 | #[test] 14 | fn pass_pack_len_u16() { 15 | let mut buf = [0x00, 0x00, 0x00]; 16 | 17 | assert_eq!( 18 | Marker::Bin16, 19 | write_bin_len(&mut &mut buf[..], 65535).unwrap() 20 | ); 21 | 22 | assert_eq!([0xc5, 0xff, 0xff], buf); 23 | } 24 | 25 | #[test] 26 | fn pass_pack_len_u32() { 27 | let mut buf = [0x00, 0x00, 0x00, 0x00, 0x00]; 28 | 29 | assert_eq!( 30 | Marker::Bin32, 31 | write_bin_len(&mut &mut buf[..], 4294967295).unwrap() 32 | ); 33 | 34 | assert_eq!([0xc6, 0xff, 0xff, 0xff, 0xff], buf); 35 | } 36 | -------------------------------------------------------------------------------- /rmp/tests/func/encode/bool.rs: -------------------------------------------------------------------------------- 1 | use rmp::encode::*; 2 | 3 | #[test] 4 | fn pass_pack_true() { 5 | let mut buf = [0x00]; 6 | 7 | write_bool(&mut &mut buf[..], true).unwrap(); 8 | 9 | assert_eq!([0xc3], buf); 10 | } 11 | 12 | #[test] 13 | fn pass_pack_false() { 14 | let mut buf = [0x00]; 15 | 16 | write_bool(&mut &mut buf[..], false).unwrap(); 17 | 18 | assert_eq!([0xc2], buf); 19 | } 20 | -------------------------------------------------------------------------------- /rmp/tests/func/encode/ext.rs: -------------------------------------------------------------------------------- 1 | use rmp::encode::*; 2 | use rmp::Marker; 3 | 4 | #[test] 5 | fn pass_pack_meta_fix1() { 6 | let mut buf = [0x00, 0x00]; 7 | 8 | assert_eq!(Marker::FixExt1, write_ext_meta(&mut &mut buf[..], 1, 16).unwrap()); 9 | 10 | assert_eq!([0xd4, 0x10], buf); 11 | } 12 | 13 | #[test] 14 | fn pass_pack_meta_fix2() { 15 | let mut buf = [0x00, 0x00]; 16 | 17 | assert_eq!(Marker::FixExt2, write_ext_meta(&mut &mut buf[..], 2, 16).unwrap()); 18 | 19 | assert_eq!([0xd5, 0x10], buf); 20 | } 21 | 22 | #[test] 23 | fn pass_pack_meta_fix4() { 24 | let mut buf = [0x00, 0x00]; 25 | 26 | assert_eq!(Marker::FixExt4, write_ext_meta(&mut &mut buf[..], 4, 16).unwrap()); 27 | 28 | assert_eq!([0xd6, 0x10], buf); 29 | } 30 | 31 | #[test] 32 | fn pass_pack_meta_fix4_timesamp() { 33 | let mut buf = [0x00, 0x00]; 34 | assert_eq!(Marker::FixExt4, write_ext_meta(&mut &mut buf[..], 4, -1).unwrap()); 35 | assert_eq!([0xd6, 0xff], buf); 36 | } 37 | 38 | #[test] 39 | fn pass_pack_meta_fix8() { 40 | let mut buf = [0x00, 0x00]; 41 | 42 | assert_eq!(Marker::FixExt8, write_ext_meta(&mut &mut buf[..], 8, 16).unwrap()); 43 | 44 | assert_eq!([0xd7, 0x10], buf); 45 | } 46 | 47 | #[test] 48 | fn pass_pack_meta_fix16() { 49 | let mut buf = [0x00, 0x00]; 50 | 51 | assert_eq!(Marker::FixExt16, write_ext_meta(&mut &mut buf[..], 16, 16).unwrap()); 52 | 53 | assert_eq!([0xd8, 0x10], buf); 54 | } 55 | 56 | #[test] 57 | fn pass_pack_meta_8() { 58 | let mut buf = [0x00, 0x00, 0x00]; 59 | 60 | assert_eq!(Marker::Ext8, write_ext_meta(&mut &mut buf[..], 255, 16).unwrap()); 61 | 62 | assert_eq!([0xc7, 0xff, 0x10], buf); 63 | } 64 | 65 | #[test] 66 | fn pass_pack_meta_16() { 67 | let mut buf = [0x00, 0x00, 0x00, 0x00]; 68 | 69 | assert_eq!(Marker::Ext16, write_ext_meta(&mut &mut buf[..], 65535, 16).unwrap()); 70 | 71 | assert_eq!([0xc8, 0xff, 0xff, 0x10], buf); 72 | } 73 | 74 | #[test] 75 | fn pass_pack_meta_32() { 76 | let mut buf = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; 77 | 78 | assert_eq!(Marker::Ext32, write_ext_meta(&mut &mut buf[..], 4294967295, 16).unwrap()); 79 | 80 | assert_eq!([0xc9, 0xff, 0xff, 0xff, 0xff, 0x10], buf); 81 | } 82 | -------------------------------------------------------------------------------- /rmp/tests/func/encode/float.rs: -------------------------------------------------------------------------------- 1 | use rmp::encode::*; 2 | 3 | #[test] 4 | fn pass_pack_f32() { 5 | let mut buf = [0x00, 0x00, 0x00, 0x00, 0x00]; 6 | 7 | write_f32(&mut &mut buf[..], 3.4028234e38_f32).ok().unwrap(); 8 | 9 | assert_eq!([0xca, 0x7f, 0x7f, 0xff, 0xff], buf); 10 | } 11 | 12 | #[test] 13 | fn pass_pack_f64() { 14 | use std::f64; 15 | 16 | let mut buf = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; 17 | 18 | write_f64(&mut &mut buf[..], f64::INFINITY).ok().unwrap(); 19 | 20 | assert_eq!([0xcb, 0x7f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], buf); 21 | } 22 | -------------------------------------------------------------------------------- /rmp/tests/func/encode/int.rs: -------------------------------------------------------------------------------- 1 | use rmp::encode::*; 2 | use rmp::Marker; 3 | 4 | #[test] 5 | fn pass_pack_pfix() { 6 | let mut buf = [0x00]; 7 | 8 | write_pfix(&mut &mut buf[..], 127).ok().unwrap(); 9 | 10 | assert_eq!([0x7f], buf); 11 | } 12 | 13 | #[test] 14 | fn fail_pack_pfix_too_small_buffer() { 15 | let mut buf = []; 16 | 17 | write_pfix(&mut &mut buf[..], 127).err().unwrap(); 18 | } 19 | 20 | #[test] 21 | #[should_panic(expected = "assertion failed")] 22 | fn fail_pack_pfix_too_large() { 23 | let mut buf = [0x00]; 24 | 25 | write_pfix(&mut &mut buf[..], 128).ok().unwrap(); 26 | } 27 | 28 | #[test] 29 | fn pass_pack_u8() { 30 | let mut buf = [0x00, 0x00]; 31 | 32 | write_u8(&mut &mut buf[..], 255).ok().unwrap(); 33 | 34 | assert_eq!([0xcc, 0xff], buf); 35 | } 36 | 37 | #[test] 38 | fn pass_pack_u16() { 39 | let mut buf = [0x00, 0x00, 0x00]; 40 | 41 | write_u16(&mut &mut buf[..], 65535).ok().unwrap(); 42 | 43 | assert_eq!([0xcd, 0xff, 0xff], buf); 44 | } 45 | 46 | #[test] 47 | fn pass_pack_u32() { 48 | let mut buf = [0x00, 0x00, 0x00, 0x00, 0x00]; 49 | 50 | write_u32(&mut &mut buf[..], 4294967295).ok().unwrap(); 51 | 52 | assert_eq!([0xce, 0xff, 0xff, 0xff, 0xff], buf); 53 | } 54 | 55 | #[test] 56 | fn pass_pack_u64() { 57 | let mut buf = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; 58 | 59 | write_u64(&mut &mut buf[..], 18446744073709551615).ok().unwrap(); 60 | 61 | assert_eq!([0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff], buf); 62 | } 63 | 64 | #[test] 65 | fn pass_pack_nfix() { 66 | let mut buf = [0x00]; 67 | 68 | write_nfix(&mut &mut buf[..], -32).ok().unwrap(); 69 | 70 | assert_eq!([0xe0], buf); 71 | } 72 | 73 | #[test] 74 | #[should_panic(expected = "assertion failed")] 75 | fn fail_pack_nfix_too_large() { 76 | let mut buf = [0x00]; 77 | 78 | write_nfix(&mut &mut buf[..], 0).ok().unwrap(); 79 | } 80 | 81 | #[test] 82 | #[should_panic(expected = "assertion failed")] 83 | fn fail_pack_nfix_too_small() { 84 | let mut buf = [0x00]; 85 | 86 | write_nfix(&mut &mut buf[..], -33).ok().unwrap(); 87 | } 88 | 89 | #[test] 90 | fn pass_pack_i8() { 91 | let mut buf = [0x00, 0x00]; 92 | 93 | write_i8(&mut &mut buf[..], -128).ok().unwrap(); 94 | 95 | assert_eq!([0xd0, 0x80], buf); 96 | } 97 | 98 | #[test] 99 | fn pass_pack_i16() { 100 | let mut buf = [0x00, 0x00, 0x00]; 101 | 102 | write_i16(&mut &mut buf[..], -32768).ok().unwrap(); 103 | 104 | assert_eq!([0xd1, 0x80, 0x00], buf); 105 | } 106 | 107 | #[test] 108 | fn pass_pack_i32() { 109 | let mut buf = [0x00, 0x00, 0x00, 0x00, 0x00]; 110 | 111 | write_i32(&mut &mut buf[..], -2147483648).ok().unwrap(); 112 | 113 | assert_eq!([0xd2, 0x80, 0x00, 0x00, 0x00], buf); 114 | } 115 | 116 | #[test] 117 | fn pass_pack_i64() { 118 | let mut buf = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; 119 | 120 | write_i64(&mut &mut buf[..], -9223372036854775808).ok().unwrap(); 121 | 122 | assert_eq!([0xd3, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], buf); 123 | } 124 | 125 | #[test] 126 | fn pass_pack_uint_fix() { 127 | let mut buf = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; 128 | 129 | assert_eq!(Marker::FixPos(127), write_uint(&mut &mut buf[..], 127).ok().unwrap()); 130 | 131 | assert_eq!([0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], buf); 132 | } 133 | 134 | #[test] 135 | fn pass_pack_uint_u8() { 136 | let mut buf = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; 137 | 138 | assert_eq!(Marker::U8, write_uint(&mut &mut buf[..], 255).ok().unwrap()); 139 | 140 | assert_eq!([0xcc, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], buf); 141 | } 142 | 143 | #[test] 144 | fn pass_pack_uint_u16() { 145 | let mut buf = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; 146 | 147 | assert_eq!( 148 | Marker::U16, 149 | write_uint(&mut &mut buf[..], 65535).ok().unwrap() 150 | ); 151 | 152 | assert_eq!([0xcd, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], buf); 153 | } 154 | 155 | #[test] 156 | fn pass_pack_uint_u32() { 157 | let mut buf = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; 158 | 159 | assert_eq!( 160 | Marker::U32, 161 | write_uint(&mut &mut buf[..], 4294967295).ok().unwrap() 162 | ); 163 | 164 | assert_eq!([0xce, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00], buf); 165 | } 166 | 167 | #[test] 168 | fn pass_pack_uint_u64() { 169 | let mut buf = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; 170 | 171 | assert_eq!(Marker::U64, write_uint(&mut &mut buf[..], 18446744073709551615).ok().unwrap()); 172 | 173 | assert_eq!([0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff], buf); 174 | } 175 | 176 | #[test] 177 | fn pass_pack_sint_fix() { 178 | let mut buf = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; 179 | 180 | assert_eq!( 181 | Marker::FixNeg(-32), 182 | write_sint(&mut &mut buf[..], -32).ok().unwrap() 183 | ); 184 | 185 | assert_eq!([0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], buf); 186 | } 187 | 188 | #[test] 189 | fn pass_pack_sint_i8_min() { 190 | let mut buf = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; 191 | 192 | assert_eq!( 193 | Marker::I8, 194 | write_sint(&mut &mut buf[..], -128).ok().unwrap() 195 | ); 196 | 197 | assert_eq!([0xd0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], buf); 198 | } 199 | 200 | #[test] 201 | fn pass_pack_sint_i16_min() { 202 | let mut buf = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; 203 | 204 | assert_eq!(Marker::I16, write_sint(&mut &mut buf[..], -32768).ok().unwrap()); 205 | 206 | assert_eq!([0xd1, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], buf); 207 | } 208 | 209 | #[test] 210 | fn pass_pack_sint_i16_max() { 211 | let mut buf = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; 212 | 213 | assert_eq!(Marker::U16, write_sint(&mut &mut buf[..], 32767).ok().unwrap()); 214 | 215 | assert_eq!([0xcd, 0x7f, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], buf); 216 | } 217 | 218 | #[test] 219 | fn pass_pack_sint_i32_min() { 220 | let mut buf = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; 221 | 222 | assert_eq!(Marker::I32, write_sint(&mut &mut buf[..], -2147483648).ok().unwrap()); 223 | 224 | assert_eq!([0xd2, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], buf); 225 | } 226 | 227 | #[test] 228 | fn pass_pack_sint_i32_max() { 229 | let mut buf = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; 230 | 231 | assert_eq!(Marker::U32, write_sint(&mut &mut buf[..], 2147483647).ok().unwrap()); 232 | 233 | assert_eq!([0xce, 0x7f, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00], buf); 234 | } 235 | 236 | #[test] 237 | fn pass_pack_sint_i64_min() { 238 | let mut buf = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; 239 | 240 | assert_eq!(Marker::I64, write_sint(&mut &mut buf[..], -9223372036854775808).ok().unwrap()); 241 | 242 | assert_eq!([0xd3, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], buf); 243 | } 244 | 245 | #[test] 246 | fn pass_pack_sint_i64_max() { 247 | let mut buf = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; 248 | 249 | assert_eq!(Marker::U64, write_sint(&mut &mut buf[..], 9223372036854775807).ok().unwrap()); 250 | 251 | assert_eq!([0xcf, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff], buf); 252 | } 253 | -------------------------------------------------------------------------------- /rmp/tests/func/encode/map.rs: -------------------------------------------------------------------------------- 1 | use rmp::encode::*; 2 | use rmp::Marker; 3 | 4 | #[test] 5 | fn pass_pack_len_fix() { 6 | let mut buf = [0x00]; 7 | 8 | assert_eq!(Marker::FixMap(15), write_map_len(&mut &mut buf[..], 15).unwrap()); 9 | 10 | assert_eq!([0x8f], buf); 11 | } 12 | 13 | #[test] 14 | fn pass_pack_len_u16() { 15 | let mut buf = [0x00, 0x00, 0x00]; 16 | 17 | assert_eq!(Marker::Map16, write_map_len(&mut &mut buf[..], 65535).unwrap()); 18 | 19 | assert_eq!([0xde, 0xff, 0xff], buf); 20 | } 21 | 22 | #[test] 23 | fn pass_pack_len_u32() { 24 | let mut buf = [0x00, 0x00, 0x00, 0x00, 0x00]; 25 | 26 | assert_eq!(Marker::Map32, write_map_len(&mut &mut buf[..], 4294967295).unwrap()); 27 | 28 | assert_eq!([0xdf, 0xff, 0xff, 0xff, 0xff], buf); 29 | } 30 | -------------------------------------------------------------------------------- /rmp/tests/func/encode/mod.rs: -------------------------------------------------------------------------------- 1 | mod array; 2 | mod bin; 3 | mod bool; 4 | mod ext; 5 | mod float; 6 | mod int; 7 | mod map; 8 | mod null; 9 | mod string; 10 | -------------------------------------------------------------------------------- /rmp/tests/func/encode/null.rs: -------------------------------------------------------------------------------- 1 | use rmp::encode::*; 2 | 3 | #[test] 4 | fn pass_pack() { 5 | let mut buf = [0x00]; 6 | 7 | write_nil(&mut &mut buf[..]).unwrap(); 8 | 9 | assert_eq!([0xc0], buf); 10 | } 11 | 12 | #[test] 13 | fn fail_pack_too_small_buffer() { 14 | let mut buf = []; 15 | write_nil(&mut &mut buf[..]).err().unwrap(); 16 | } 17 | -------------------------------------------------------------------------------- /rmp/tests/func/encode/string.rs: -------------------------------------------------------------------------------- 1 | use rmp::encode::*; 2 | use rmp::Marker; 3 | 4 | #[test] 5 | fn pass_pack_len_fix() { 6 | let mut buf = [0x00]; 7 | 8 | assert_eq!(Marker::FixStr(31), write_str_len(&mut &mut buf[..], 31).unwrap()); 9 | 10 | assert_eq!([0xbf], buf); 11 | } 12 | 13 | #[test] 14 | fn pass_pack_len_u8() { 15 | let mut buf = [0x00, 0x00]; 16 | 17 | assert_eq!(Marker::Str8, write_str_len(&mut &mut buf[..], 255).unwrap()); 18 | 19 | assert_eq!([0xd9, 0xff], buf); 20 | } 21 | 22 | #[test] 23 | fn pass_pack_len_u16() { 24 | let mut buf = [0x00, 0x00, 0x00]; 25 | 26 | assert_eq!(Marker::Str16, write_str_len(&mut &mut buf[..], 65535).unwrap()); 27 | 28 | assert_eq!([0xda, 0xff, 0xff], buf); 29 | } 30 | 31 | #[test] 32 | fn pass_pack_len_u32() { 33 | let mut buf = [0x00, 0x00, 0x00, 0x00, 0x00]; 34 | 35 | assert_eq!(Marker::Str32, write_str_len(&mut &mut buf[..], 4294967295).unwrap()); 36 | 37 | assert_eq!([0xdb, 0xff, 0xff, 0xff, 0xff], buf); 38 | } 39 | -------------------------------------------------------------------------------- /rmp/tests/func/est.rs: -------------------------------------------------------------------------------- 1 | use rmp::Marker; 2 | use rmp::decode::MessageLen; 3 | use rmp::decode::LenError; 4 | use rmp::encode::*; 5 | 6 | #[track_caller] 7 | fn check_estimates(msg: &[u8], expected: &[i32]) { 8 | assert_eq!(msg.len()+1, expected.len(), "off by {}", msg.len() as isize + 1 - expected.len() as isize); 9 | 10 | fn take_res(r: Result) -> (i32, usize) { 11 | match r { 12 | Err(r) => (r.len() as i32, r.len()), 13 | Ok(r) => (-(r as i32), r), 14 | } 15 | } 16 | 17 | let predicted = (0..=msg.len()) 18 | .map(|partial_len| { 19 | let partial_msg = &msg[..partial_len]; 20 | let (res, predicted) = take_res(MessageLen::len_of(partial_msg)); 21 | assert!(predicted > partial_len.min(msg.len()-1), "{predicted} > {partial_len}/{}", msg.len()); 22 | res 23 | }) 24 | .collect::>(); 25 | assert_eq!(expected, predicted, "quadratic"); 26 | assert_eq!(msg.len(), MessageLen::len_of(&msg).expect("complete message")); 27 | 28 | let mut incremental = MessageLen::with_limits(1024, 1<<16); 29 | let predicted = [&[][..]].into_iter().chain(msg.chunks(1)).map(|mut chunk| { 30 | let (res, _) = take_res(incremental.incremental_len(&mut chunk)); 31 | res 32 | }).collect::>(); 33 | assert_eq!(expected, predicted, "incremental"); 34 | 35 | for frag_len in [1, 2, 3, 5, 7] { 36 | let mut incremental = MessageLen::with_limits(1024, msg.len()); 37 | let predicted = [&[][..]].into_iter().chain(msg.chunks(frag_len)).map(|mut chunk| { 38 | match incremental.incremental_len(&mut chunk) { 39 | Err(r) => r.len(), 40 | Ok(r) => r, 41 | } 42 | }).max().unwrap_or(usize::MAX); 43 | assert_eq!(msg.len(), predicted, "incremental {frag_len}"); 44 | } 45 | } 46 | 47 | #[test] 48 | fn array() { 49 | assert_eq!(1, MessageLen::len_of(&[]).unwrap_err().len()); 50 | 51 | let mut out = [0u8; 1]; 52 | write_bool(&mut out.as_mut_slice(), true).unwrap(); 53 | assert_eq!(1, MessageLen::len_of(&out).unwrap()); 54 | 55 | let mut out = Vec::new(); 56 | write_array_len(&mut out, 4).unwrap(); 57 | write_u16(&mut out, 333).unwrap(); 58 | write_bool(&mut out, true).unwrap(); 59 | write_u64(&mut out, 1<<33).unwrap(); 60 | write_bin_len(&mut out, 5).unwrap(); 61 | out.extend(b"hello"); 62 | 63 | check_estimates(&out, &[1, 5, 5, 5, 7, 7, 14, 14, 14, 14, 14, 14, 14, 14, 15, 16, 21, 21, 21, 21, 21, -21]); 64 | } 65 | 66 | #[test] 67 | fn map() { 68 | let mut out = Vec::new(); 69 | write_map_len(&mut out, 3).unwrap(); 70 | write_u16(&mut out, 333).unwrap(); 71 | write_bool(&mut out, true).unwrap(); 72 | 73 | write_str_len(&mut out, 5).unwrap(); 74 | out.extend(b"hello"); 75 | write_nil(&mut out).unwrap(); 76 | 77 | write_f64(&mut out, 1.23).unwrap(); 78 | write_map_len(&mut out, 2).unwrap(); 79 | write_nil(&mut out).unwrap(); 80 | out.push(Marker::Array32.to_u8()); 81 | out.extend_from_slice(&1u32.to_be_bytes()); 82 | write_uint8(&mut out, 3).unwrap(); 83 | write_nil(&mut out).unwrap(); 84 | write_u32(&mut out, 1).unwrap(); 85 | 86 | 87 | check_estimates(&out, &[1, 7, 7, 7, 9, 9, 11, 11, 11, 11, 11, 14, 14, 21, 21, 21, 21, 21, 21, 21, 21, 22, 26, 26, 28, 28, 28, 28, 29, 31, 31, 35, 35, 35, 35, -35]); 88 | } 89 | 90 | #[test] 91 | fn nested() { 92 | let mut out = Vec::new(); 93 | write_array_len(&mut out, 1).unwrap(); 94 | write_array_len(&mut out, 1).unwrap(); 95 | write_array_len(&mut out, 1).unwrap(); 96 | out.push(Marker::Array32.to_u8()); 97 | out.extend_from_slice(&1u32.to_be_bytes()); 98 | write_array_len(&mut out, 1).unwrap(); 99 | write_array_len(&mut out, 1).unwrap(); 100 | write_array_len(&mut out, 1).unwrap(); 101 | write_array_len(&mut out, 2).unwrap(); 102 | write_array_len(&mut out, 1).unwrap(); 103 | out.push(Marker::Array16.to_u8()); 104 | out.extend_from_slice(&1u16.to_be_bytes()); 105 | write_array_len(&mut out, 1).unwrap(); 106 | write_array_len(&mut out, 1).unwrap(); 107 | write_array_len(&mut out, 1).unwrap(); 108 | write_array_len(&mut out, 1).unwrap(); 109 | write_nil(&mut out).unwrap(); 110 | write_nil(&mut out).unwrap(); 111 | 112 | check_estimates(&out, &[1, 2, 3, 4, 8, 8, 8, 8, 9, 10, 11, 12, 14, 14, 16, 16, 17, 18, 19, 20, 21, 22, -22]); 113 | 114 | assert!(MessageLen::with_limits(4, 1<<16).incremental_len(&mut out.as_slice()).is_err()); 115 | assert!(MessageLen::with_limits(14, 1<<16).incremental_len(&mut out.as_slice()).is_ok()); 116 | } 117 | -------------------------------------------------------------------------------- /rmp/tests/func/mirror.rs: -------------------------------------------------------------------------------- 1 | use rmp::decode::Bytes; 2 | use rmp::encode::ByteBuf; 3 | use rmp::{decode, encode}; 4 | 5 | quickcheck! { 6 | fn mirror_uint(xs: u64) -> bool { 7 | let mut buf = ByteBuf::new(); 8 | encode::write_uint(&mut buf, xs).unwrap(); 9 | 10 | xs == decode::read_int(&mut Bytes::new(buf.as_slice())).unwrap() 11 | } 12 | 13 | fn mirror_sint(xs: i64) -> bool { 14 | let mut buf = ByteBuf::new(); 15 | encode::write_sint(&mut buf, xs).unwrap(); 16 | 17 | xs == decode::read_int(&mut Bytes::new(buf.as_slice())).unwrap() 18 | } 19 | 20 | fn mirror_f32(xs: f32) -> bool { 21 | let mut buf = ByteBuf::new(); 22 | encode::write_f32(&mut buf, xs).unwrap(); 23 | 24 | let res = decode::read_f32(&mut Bytes::new(buf.as_slice())).unwrap(); 25 | xs == res || (xs.is_nan() && res.is_nan()) 26 | } 27 | 28 | fn mirror_f64(xs: f64) -> bool { 29 | let mut buf = ByteBuf::new(); 30 | encode::write_f64(&mut buf, xs).expect("write"); 31 | 32 | let res = decode::read_f64(&mut Bytes::new(buf.as_slice())).expect("read"); 33 | true || xs == res || (xs.is_nan() && res.is_nan()) 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /rmp/tests/lib.rs: -------------------------------------------------------------------------------- 1 | #[cfg(test)] 2 | #[macro_use] 3 | extern crate quickcheck; 4 | 5 | mod func { 6 | mod decode; 7 | mod encode; 8 | mod mirror; 9 | mod est; 10 | } 11 | -------------------------------------------------------------------------------- /rmpv-tests/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "rmpv-tests" 3 | version = "0.0.0" 4 | authors = ["Evgeny Safronov "] 5 | publish = false 6 | edition = "2018" 7 | 8 | [dependencies] 9 | serde = { version = "1.0.130", features = ["derive"] } 10 | rmp-serde = { path = "../rmp-serde" } 11 | rmpv = { features = ["with-serde"], path = "../rmpv" } 12 | 13 | [dev-dependencies] 14 | serde_bytes = "0.11.5" 15 | -------------------------------------------------------------------------------- /rmpv-tests/LICENSE: -------------------------------------------------------------------------------- 1 | ../LICENSE -------------------------------------------------------------------------------- /rmpv-tests/benches/value.rs: -------------------------------------------------------------------------------- 1 | #![feature(test)] 2 | extern crate test; 3 | 4 | use test::Bencher; 5 | 6 | use rmpv::ValueRef; 7 | 8 | // Encoded value: [1, 0, [[["127.0.0.1", 59074]], 1, {0: ["read", {}, {0: ["value", {}], 1: ["error", {}]}], 1: ["write", {}, {0: ["value", {}], 1: ["error", {}]}], 2: ["remove", {}, {0: ["value", {}], 1: ["error", {}]}], 3: ["find", {}, {0: ["value", {}], 1: ["error", {}]}]}], [[80, 81, 82]]]. 9 | const COMPLEX: &[u8] = &[ 10 | 0x94, 0x01, 0x00, 0x93, 0x91, 0x92, 0xa9, 0x31, 11 | 0x32, 0x37, 0x2e, 0x30, 0x2e, 0x30, 0x2e, 0x31, 12 | 0xcd, 0xe6, 0xc2, 0x01, 0x84, 0x00, 0x93, 0xa4, 13 | 0x72, 0x65, 0x61, 0x64, 0x80, 0x82, 0x00, 0x92, 14 | 0xa5, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x80, 0x01, 15 | 0x92, 0xa5, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x80, 16 | 0x01, 0x93, 0xa5, 0x77, 0x72, 0x69, 0x74, 0x65, 17 | 0x80, 0x82, 0x00, 0x92, 0xa5, 0x76, 0x61, 0x6c, 18 | 0x75, 0x65, 0x80, 0x01, 0x92, 0xa5, 0x65, 0x72, 19 | 0x72, 0x6f, 0x72, 0x80, 0x02, 0x93, 0xa6, 0x72, 20 | 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x80, 0x82, 0x00, 21 | 0x92, 0xa5, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x80, 22 | 0x01, 0x92, 0xa5, 0x65, 0x72, 0x72, 0x6f, 0x72, 23 | 0x80, 0x03, 0x93, 0xa4, 0x66, 0x69, 0x6e, 0x64, 24 | 0x80, 0x82, 0x00, 0x92, 0xa5, 0x76, 0x61, 0x6c, 25 | 0x75, 0x65, 0x80, 0x01, 0x92, 0xa5, 0x65, 0x72, 26 | 0x72, 0x6f, 0x72, 0x80, 0x91, 0x93, 0x50, 0x51, 27 | 0x52, 28 | ]; 29 | 30 | #[bench] 31 | fn from_complex_read_value_ref(b: &mut Bencher) { 32 | b.iter(|| { 33 | let res = rmpv::decode::read_value_ref(&mut &COMPLEX[..]).unwrap(); 34 | test::black_box(res); 35 | }); 36 | b.bytes = COMPLEX.len() as u64; 37 | } 38 | 39 | #[bench] 40 | fn from_complex_zero_copy_decode(b: &mut Bencher) { 41 | b.iter(|| { 42 | let res: ValueRef<'_> = rmp_serde::from_slice(COMPLEX).unwrap(); 43 | test::black_box(res); 44 | }); 45 | b.bytes = COMPLEX.len() as u64; 46 | } 47 | -------------------------------------------------------------------------------- /rmpv-tests/tests/round.rs: -------------------------------------------------------------------------------- 1 | use std::fmt::Debug; 2 | 3 | use serde::de::DeserializeOwned; 4 | use serde::Deserialize; 5 | use serde::Serialize; 6 | use serde_bytes::ByteBuf; 7 | 8 | use rmpv::Value; 9 | 10 | /// Tests that the following round-trip conditions are met: 11 | /// - `T` -> `[u8]` == `Value` -> `[u8]`. 12 | /// - `T` -> `Value` == `Value`. 13 | /// - `[u8]` -> `T` == `T`. 14 | /// - `[u8]` -> `Value` == `Value`. 15 | /// - `Value` -> `T` == `T`. 16 | fn test_round<'de, T>(var: T, val: Value) 17 | where T: Debug + PartialEq + Serialize + DeserializeOwned 18 | { 19 | // Serialize part. 20 | // Test that `T` -> `[u8]` equals with serialization from `Value` -> `[u8]`. 21 | let buf_from_var = rmp_serde::to_vec(&var).unwrap(); 22 | let buf_from_val = rmp_serde::to_vec(&val).unwrap(); 23 | assert_eq!(buf_from_var, buf_from_val); 24 | 25 | // Test that `T` -> `Value` equals with the given `Value`. 26 | let val_from_var = rmpv::ext::to_value(&var).unwrap(); 27 | assert_eq!(val, val_from_var); 28 | 29 | // Deserialize part. 30 | // Test that `[u8]` -> `T` equals with the given `T`. 31 | let var_from_buf: T = rmp_serde::from_slice(buf_from_var.as_slice()).unwrap(); 32 | assert_eq!(var, var_from_buf); 33 | 34 | // Test that `[u8]` -> `Value` equals with the given `Value`. 35 | let val_from_buf: Value = rmp_serde::from_slice(buf_from_var.as_slice()).unwrap(); 36 | assert_eq!(val, val_from_buf); 37 | 38 | // Test that `Value` -> `T` equals with the given `T`. 39 | let var_from_val: T = rmpv::ext::from_value(val_from_buf).unwrap(); 40 | assert_eq!(var, var_from_val); 41 | } 42 | 43 | #[test] 44 | fn pass_nil() { 45 | test_round((), Value::Nil); 46 | } 47 | 48 | #[test] 49 | fn pass_bool() { 50 | test_round(true, Value::Boolean(true)); 51 | test_round(false, Value::Boolean(false)); 52 | } 53 | 54 | #[test] 55 | fn pass_uint() { 56 | test_round(u8::min_value(), Value::from(u8::min_value())); 57 | test_round(u8::MAX, Value::from(u8::MAX)); 58 | test_round(u16::MAX, Value::from(u16::MAX)); 59 | test_round(u32::MAX, Value::from(u32::MAX)); 60 | test_round(u64::MAX, Value::from(u64::MAX)); 61 | } 62 | 63 | #[test] 64 | fn pass_sint() { 65 | test_round(i8::min_value(), Value::from(i8::min_value())); 66 | test_round(i8::MAX, Value::from(i8::MAX)); 67 | test_round(i16::min_value(), Value::from(i16::min_value())); 68 | test_round(i16::MAX, Value::from(i16::MAX)); 69 | test_round(i32::min_value(), Value::from(i32::min_value())); 70 | test_round(i32::MAX, Value::from(i32::MAX)); 71 | test_round(i64::min_value(), Value::from(i64::min_value())); 72 | test_round(i64::MAX, Value::from(i64::MAX)); 73 | } 74 | 75 | #[test] 76 | fn pass_f32() { 77 | test_round(std::f32::MAX, Value::from(std::f32::MAX)); 78 | } 79 | 80 | #[test] 81 | fn pass_f64() { 82 | test_round(0.00, Value::from(0.00)); 83 | test_round(42.0, Value::from(42.0)); 84 | } 85 | 86 | #[test] 87 | fn pass_str() { 88 | test_round("John".to_string(), Value::from("John")); 89 | } 90 | 91 | #[test] 92 | fn pass_bin() { 93 | test_round(ByteBuf::from(&[0xcc, 0x80][..]), Value::from(&[0xcc, 0x80][..])); 94 | } 95 | 96 | #[test] 97 | fn pass_vec() { 98 | test_round([0, 42], Value::from(vec![Value::from(0), Value::from(42)])); 99 | test_round(vec![0, 42], Value::from(vec![Value::from(0), Value::from(42)])); 100 | } 101 | 102 | #[test] 103 | fn pass_newtype_struct() { 104 | #[derive(Debug, PartialEq, Serialize, Deserialize)] 105 | struct Newtype(String); 106 | 107 | test_round(Newtype("John".into()), Value::from("John")); 108 | } 109 | 110 | #[test] 111 | fn pass_ext_struct() { 112 | #[derive(Debug, PartialEq)] 113 | enum ExtStruct { 114 | One(u8), 115 | Two(u8), 116 | } 117 | 118 | struct ExtStructVisitor; 119 | 120 | use serde::de::Unexpected; 121 | use serde_bytes::ByteBuf; 122 | 123 | impl Serialize for ExtStruct { 124 | fn serialize(&self, s: S) -> Result 125 | where S: serde::ser::Serializer 126 | { 127 | let value = match self { 128 | ExtStruct::One(data) => { 129 | let tag = 1_i8; 130 | let byte_buf = ByteBuf::from(vec![*data]); 131 | 132 | (tag, byte_buf) 133 | } 134 | ExtStruct::Two(data) => { 135 | let tag = 2_i8; 136 | let byte_buf = ByteBuf::from(vec![*data]); 137 | 138 | (tag, byte_buf) 139 | } 140 | }; 141 | s.serialize_newtype_struct(rmp_serde::MSGPACK_EXT_STRUCT_NAME, &value) 142 | } 143 | } 144 | 145 | impl<'de> serde::de::Visitor<'de> for ExtStructVisitor { 146 | type Value = ExtStruct; 147 | 148 | fn expecting(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 149 | write!(fmt, "a sequence of tag & binary") 150 | } 151 | 152 | fn visit_newtype_struct(self, deserializer: D) -> Result 153 | where D: serde::de::Deserializer<'de>, 154 | { 155 | deserializer.deserialize_tuple(2, self) 156 | } 157 | 158 | fn visit_seq(self, mut seq: A) -> Result 159 | where A: serde::de::SeqAccess<'de> 160 | { 161 | let tag: i8 = seq.next_element()? 162 | .ok_or_else(|| serde::de::Error::invalid_length(0, &self))?; 163 | let data: ByteBuf = seq.next_element()? 164 | .ok_or_else(|| serde::de::Error::invalid_length(1, &self))?; 165 | 166 | if tag == 1 { 167 | Ok(ExtStruct::One(data[0])) 168 | } else if tag == 2 { 169 | Ok(ExtStruct::Two(data[0])) 170 | } else { 171 | let unexp = Unexpected::Signed(i64::from(tag)); 172 | Err(serde::de::Error::invalid_value(unexp, &self)) 173 | } 174 | } 175 | } 176 | 177 | impl<'de> serde::de::Deserialize<'de> for ExtStruct { 178 | fn deserialize(deserializer: D) -> Result 179 | where D: serde::Deserializer<'de>, 180 | { 181 | let visitor = ExtStructVisitor; 182 | deserializer.deserialize_newtype_struct(rmp_serde::MSGPACK_EXT_STRUCT_NAME, visitor) 183 | } 184 | } 185 | 186 | test_round(ExtStruct::One(5), Value::Ext(1, vec![5])); 187 | } 188 | 189 | #[test] 190 | fn pass_derive_serde_ext_struct() { 191 | #[derive(Debug, PartialEq, Serialize, Deserialize)] 192 | #[serde(rename = "_ExtStruct")] 193 | struct ExtStruct((i8, serde_bytes::ByteBuf)); 194 | 195 | test_round( 196 | ExtStruct((2, serde_bytes::ByteBuf::from(vec![5]))), 197 | Value::Ext(2, vec![5]), 198 | ); 199 | } 200 | -------------------------------------------------------------------------------- /rmpv/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | All notable changes to this project will be documented in this file. 3 | This project adheres to [Semantic Versioning](http://semver.org/). 4 | 5 | ## Unreleased 6 | ## 0.4.1 - 2017-06-27 7 | ### Added 8 | - Add `as_ref()` to `Value` and `Utf8String` (#139). 9 | 10 | ### Changed 11 | - (Breaking) Serialize newtype structs by serializing its inner type without wrapping into a tuple. (#146). 12 | 13 | ## 0.4.0 - 2017-04-24 14 | ### Added 15 | - Implement `Deserialize` for `ValueRef<'de>`. 16 | - Implement `Deserializer` for `ValueRef<'de>`. 17 | - Implement `Deserializer` for `&'de ValueRef<'de>`. 18 | - Zero-copy deserialization from `ValueRef`. 19 | 20 | ### Changed 21 | - Adapt with serde 1.0. 22 | 23 | ## 0.3.4 - 2017-03-26 24 | ### Fixed 25 | - Fix compilation on rustc 1.13. 26 | 27 | ## 0.3.3 - 2017-03-26 28 | ### Changed 29 | - Enum deserializer can now deserialize newtype variants with more than one element nested. 30 | 31 | ## 0.3.2 - 2017-03-13 32 | ### Fixed 33 | - Fixed double-quoting for strings when formatting a `ValueRef` using `Display` trait. 34 | 35 | ## 0.3.1 - 2017-03-11 36 | ### Added 37 | - Implement `From` for `std::io::Error`. 38 | 39 | ## 0.3.0 - 2017-03-09 40 | ### Added 41 | - Implement `Deserializer` and `Serializer` for `Value`. 42 | - Add `kind()` method for `rmpv::decode::Error`. 43 | - Implement `Error` and `Display` traits for `rmpv::decode::Error`. 44 | - Implement `From` trait for `Value` and `ValueRef` from all integral types, strings, slices and other more. 45 | 46 | ### Changed 47 | - Reserved markers are now decoded as nil instead of raising `Error::TypeMismatch`. 48 | - Integer representation for `Value` and `ValueRef` has been changed and hidden from the user to be able to fully match the spec and to fix round-trip cases. 49 | - Invalid UTF-8 strings can now be properly decoded into `Value` and `ValueRef` to match the spec. An untouched bytes can also be returned on demand as like as `Utf8Error` with description where invalid byte-sequence happened. 50 | - Error enums for decoding `Value` and `ValueRef` has been merged into the single one, which is located at `rmpv::decode::Error`. 51 | 52 | ### Removed 53 | - Remove `TypeMismatch` variant from `value::decode::Error`, because there is no way to obtain it. 54 | - Remove `FromUtf8Error` variant from `value::decode::Error`, because there invalid UTF-8 sequences are now supported. 55 | 56 | ## 0.2.0 - 2017-02-09 57 | ### Added 58 | - `Serde` 0.9 support. 59 | - `ValueRef` can now be displayed. 60 | - `ValueRef` can be indexed using special `index(..)` method. Implementing `Index` trait is not possible due to conflicting signature - `ValueRef` requires explicit lifetime. 61 | - It's now possible to obtain `ErrorKind` for Errors. 62 | 63 | ## 0.1.0 - 2017-01-05 64 | ### Removed 65 | - Value now saves integer and floating point numbers directly without intermediate `Integer` and `Float` enums. As a result, they were removed. 66 | -------------------------------------------------------------------------------- /rmpv/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "rmpv" 3 | version = "1.3.0" 4 | authors = ["Evgeny Safronov "] 5 | license = "MIT" 6 | description = "Value variant for RMP" 7 | repository = "https://github.com/3Hren/msgpack-rust" 8 | documentation = "https://docs.rs/rmpv" 9 | readme = "README.md" 10 | keywords = ["msgpack", "MessagePack", "serialization"] 11 | categories = ["encoding"] 12 | edition = "2021" 13 | rust-version = "1.70" 14 | 15 | [features] 16 | with-serde = ["serde", "serde_bytes"] 17 | 18 | [dependencies] 19 | serde_bytes = { version = "0.11.5", optional = true } 20 | rmp = { version = "0.8.14", path = "../rmp" } 21 | serde = { version = "1.0.197", optional = true } 22 | 23 | [dev-dependencies] 24 | quickcheck = "1.0.2" 25 | 26 | [package.metadata.release] 27 | tag-prefix = "{{crate_name}}/" 28 | 29 | [badges] 30 | maintenance = { status = "looking-for-maintainer" } 31 | -------------------------------------------------------------------------------- /rmpv/LICENSE: -------------------------------------------------------------------------------- 1 | ../LICENSE -------------------------------------------------------------------------------- /rmpv/README.md: -------------------------------------------------------------------------------- 1 | ../README.md -------------------------------------------------------------------------------- /rmpv/benches/value.rs: -------------------------------------------------------------------------------- 1 | #![feature(test)] 2 | 3 | extern crate test; 4 | 5 | use test::Bencher; 6 | 7 | use rmpv::decode::*; 8 | 9 | // Encoded value: [1, 0, [[["127.0.0.1", 59074]], 1, {0: ["read", {}, {0: ["value", {}], 1: ["error", {}]}], 1: ["write", {}, {0: ["value", {}], 1: ["error", {}]}], 2: ["remove", {}, {0: ["value", {}], 1: ["error", {}]}], 3: ["find", {}, {0: ["value", {}], 1: ["error", {}]}]}], [[80, 81, 82]]]. 10 | const COMPLEX: [u8; 137] = [ 11 | 0x94, 0x01, 0x00, 0x93, 0x91, 0x92, 0xa9, 0x31, 12 | 0x32, 0x37, 0x2e, 0x30, 0x2e, 0x30, 0x2e, 0x31, 13 | 0xcd, 0xe6, 0xc2, 0x01, 0x84, 0x00, 0x93, 0xa4, 14 | 0x72, 0x65, 0x61, 0x64, 0x80, 0x82, 0x00, 0x92, 15 | 0xa5, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x80, 0x01, 16 | 0x92, 0xa5, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x80, 17 | 0x01, 0x93, 0xa5, 0x77, 0x72, 0x69, 0x74, 0x65, 18 | 0x80, 0x82, 0x00, 0x92, 0xa5, 0x76, 0x61, 0x6c, 19 | 0x75, 0x65, 0x80, 0x01, 0x92, 0xa5, 0x65, 0x72, 20 | 0x72, 0x6f, 0x72, 0x80, 0x02, 0x93, 0xa6, 0x72, 21 | 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x80, 0x82, 0x00, 22 | 0x92, 0xa5, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x80, 23 | 0x01, 0x92, 0xa5, 0x65, 0x72, 0x72, 0x6f, 0x72, 24 | 0x80, 0x03, 0x93, 0xa4, 0x66, 0x69, 0x6e, 0x64, 25 | 0x80, 0x82, 0x00, 0x92, 0xa5, 0x76, 0x61, 0x6c, 26 | 0x75, 0x65, 0x80, 0x01, 0x92, 0xa5, 0x65, 0x72, 27 | 0x72, 0x6f, 0x72, 0x80, 0x91, 0x93, 0x50, 0x51, 28 | 0x52, 29 | ]; 30 | 31 | #[bench] 32 | fn from_string_read_value(b: &mut Bencher) { 33 | // Lorem ipsum dolor sit amet. 34 | let buf = [ 35 | 0xbb, 0x4c, 0x6f, 0x72, 0x65, 0x6d, 0x20, 0x69, 0x70, 0x73, 0x75, 36 | 0x6d, 0x20, 0x64, 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x73, 0x69, 0x74, 37 | 0x20, 0x61, 0x6d, 0x65, 0x74, 0x2e 38 | ]; 39 | 40 | b.iter(|| { 41 | let res = read_value(&mut &buf[..]).unwrap(); 42 | test::black_box(res); 43 | }); 44 | } 45 | 46 | #[bench] 47 | fn from_string_read_value_ref(b: &mut Bencher) { 48 | // Lorem ipsum dolor sit amet. 49 | let buf = [ 50 | 0xbb, 0x4c, 0x6f, 0x72, 0x65, 0x6d, 0x20, 0x69, 0x70, 0x73, 0x75, 51 | 0x6d, 0x20, 0x64, 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x73, 0x69, 0x74, 52 | 0x20, 0x61, 0x6d, 0x65, 0x74, 0x2e 53 | ]; 54 | 55 | b.iter(|| { 56 | let res = read_value_ref(&mut &buf[..]).unwrap(); 57 | test::black_box(res); 58 | }); 59 | } 60 | 61 | #[bench] 62 | fn from_complex_read_value(b: &mut Bencher) { 63 | b.iter(|| { 64 | let res = read_value(&mut &COMPLEX[..]).unwrap(); 65 | test::black_box(res); 66 | }); 67 | b.bytes = COMPLEX.len() as u64; 68 | } 69 | 70 | #[bench] 71 | fn from_complex_read_value_ref(b: &mut Bencher) { 72 | b.iter(|| { 73 | let res = read_value_ref(&mut &COMPLEX[..]).unwrap(); 74 | test::black_box(res); 75 | }); 76 | b.bytes = COMPLEX.len() as u64; 77 | } 78 | 79 | #[bench] 80 | fn from_complex_write_value_ref(b: &mut Bencher) { 81 | use rmpv::encode::write_value_ref; 82 | use rmpv::ValueRef::*; 83 | 84 | let val = Array(vec![ 85 | Nil, 86 | Integer(42.into()), 87 | F64(3.1415), 88 | String("Lorem ipsum dolor sit amet.".into()), 89 | Map(vec![ 90 | (String("key".into()), String("value".into())), 91 | ]), 92 | ]); 93 | 94 | let mut buf = [0u8; 64]; 95 | 96 | b.iter(|| { 97 | write_value_ref(&mut &mut buf[..], &val).unwrap(); 98 | }); 99 | b.bytes = buf.len() as u64; 100 | } 101 | 102 | #[bench] 103 | fn from_complex_read_value_ref_to_owned(b: &mut Bencher) { 104 | let buf = [ 105 | 0x95, // Fixed array with 5 len. 106 | 0xc0, // Nil. 107 | 0x2a, // 42. 108 | 0xcb, 0x40, 0x9, 0x21, 0xca, 0xc0, 0x83, 0x12, 0x6f, // 3.1415 109 | // Fixed string with "Lorem ipsum dolor sit amet." content. 110 | 0xbb, 0x4c, 0x6f, 0x72, 0x65, 0x6d, 0x20, 0x69, 0x70, 0x73, 0x75, 111 | 0x6d, 0x20, 0x64, 0x6f, 0x6c, 0x6f, 0x72, 0x20, 0x73, 0x69, 0x74, 112 | 0x20, 0x61, 0x6d, 0x65, 0x74, 0x2e, 113 | 0x81, // Fixed map with 1 len. 114 | 0xa3, 0x6b, 0x65, 0x79, // Key "key". 115 | 0xa5, 0x76, 0x61, 0x6c, 0x75, 0x65 // Value: "value". 116 | ]; 117 | 118 | b.iter(|| { 119 | let res = read_value_ref(&mut &buf[..]).unwrap().to_owned(); 120 | test::black_box(res); 121 | }); 122 | b.bytes = buf.len() as u64; 123 | } 124 | 125 | /// Read a single large bin32 value. 126 | fn read_large_bin32(b: &mut Bencher, size: u32) { 127 | // Creat buffer, fill it with bytes 128 | let mut buf = Vec::with_capacity(size as usize); 129 | buf.resize(size as usize, 42); 130 | 131 | // Write header (bin32 format family containing size-5 bytes) 132 | let size_bytes: [u8; 4] = (size - 5).to_be_bytes(); 133 | buf[0] = 0xc6; 134 | buf[1] = size_bytes[0]; 135 | buf[2] = size_bytes[1]; 136 | buf[3] = size_bytes[2]; 137 | buf[4] = size_bytes[3]; 138 | 139 | // Read value 140 | b.iter(|| { 141 | let res = read_value(&mut &buf[..]).unwrap(); 142 | test::black_box(res); 143 | }); 144 | b.bytes = u64::from(size); 145 | } 146 | 147 | #[bench] 148 | fn read_bin32_50kib(b: &mut Bencher) { 149 | read_large_bin32(b, 50 * 1024); 150 | } 151 | 152 | #[bench] 153 | fn read_bin32_100kib(b: &mut Bencher) { 154 | read_large_bin32(b, 100 * 1024); 155 | } 156 | 157 | #[bench] 158 | fn read_bin32_1mib(b: &mut Bencher) { 159 | read_large_bin32(b, 1024 * 1024); 160 | } 161 | 162 | #[bench] 163 | fn read_bin32_20mib(b: &mut Bencher) { 164 | read_large_bin32(b, 20 * 1024 * 1024); 165 | } 166 | 167 | #[bench] 168 | fn read_bin32_100mib(b: &mut Bencher) { 169 | read_large_bin32(b, 100 * 1024 * 1024); 170 | } 171 | 172 | /// Read a flat array containing positive 32-bit unsigned integers. 173 | fn read_large_array(b: &mut Bencher, element_count: usize) { 174 | // Creat buffer, fill it with bytes 175 | let size = element_count * 5 /* uint32 size */ + 5 /* array overhead */; 176 | let mut buf = Vec::with_capacity(size); 177 | buf.resize(size, 0); 178 | 179 | // Write header 180 | let size_bytes: [u8; 4] = (size as u32 - 5).to_be_bytes(); 181 | buf[0] = 0xc6; 182 | buf[1] = size_bytes[0]; 183 | buf[2] = size_bytes[1]; 184 | buf[3] = size_bytes[2]; 185 | buf[4] = size_bytes[3]; 186 | 187 | // Write elements 188 | let elements = &mut buf[5..]; 189 | for i in 0..element_count { 190 | let offset = i * 5; 191 | let value_bytes = 42u32.to_be_bytes(); 192 | elements[offset] = 0xce; // u32 193 | elements[offset + 1] = value_bytes[0]; 194 | elements[offset + 2] = value_bytes[1]; 195 | elements[offset + 3] = value_bytes[2]; 196 | elements[offset + 4] = value_bytes[3]; 197 | } 198 | 199 | // Read value 200 | b.iter(|| { 201 | let res = read_value(&mut &buf[..]).unwrap(); 202 | test::black_box(res); 203 | }); 204 | b.bytes = size as u64; 205 | } 206 | 207 | #[bench] 208 | fn read_array_50kib(b: &mut Bencher) { 209 | read_large_array(b, 50 * 1024); 210 | } 211 | 212 | #[bench] 213 | fn read_array_100kib(b: &mut Bencher) { 214 | read_large_array(b, 100 * 1024); 215 | } 216 | 217 | #[bench] 218 | fn read_array_1mib(b: &mut Bencher) { 219 | read_large_array(b, 1024 * 1024); 220 | } 221 | 222 | #[bench] 223 | fn read_array_20mib(b: &mut Bencher) { 224 | read_large_array(b, 20 * 1024 * 1024); 225 | } 226 | -------------------------------------------------------------------------------- /rmpv/src/decode/mod.rs: -------------------------------------------------------------------------------- 1 | use std::error; 2 | use std::fmt::{self, Display, Formatter}; 3 | use std::io::{self, ErrorKind}; 4 | 5 | use rmp::decode::{MarkerReadError, ValueReadError}; 6 | 7 | pub mod value; 8 | pub mod value_ref; 9 | 10 | pub use self::value::{read_value, read_value_with_max_depth}; 11 | pub use self::value_ref::{read_value_ref, read_value_ref_with_max_depth}; 12 | 13 | /// The maximum recursion depth before [`Error::DepthLimitExceeded`] is returned. 14 | pub const MAX_DEPTH: usize = 1024; 15 | 16 | /// This type represents all possible errors that can occur when deserializing a value. 17 | #[derive(Debug)] 18 | pub enum Error { 19 | /// Error while reading marker byte. 20 | InvalidMarkerRead(io::Error), 21 | /// Error while reading data. 22 | InvalidDataRead(io::Error), 23 | /// The depth limit [`MAX_DEPTH`] was exceeded. 24 | DepthLimitExceeded, 25 | } 26 | 27 | #[inline] 28 | fn decrement_depth(depth: u16) -> Result { 29 | depth.checked_sub(1).ok_or(Error::DepthLimitExceeded) 30 | } 31 | 32 | impl Error { 33 | #[cold] 34 | #[must_use] 35 | pub fn kind(&self) -> ErrorKind { 36 | match *self { 37 | Self::InvalidMarkerRead(ref err) => err.kind(), 38 | Self::InvalidDataRead(ref err) => err.kind(), 39 | Self::DepthLimitExceeded => ErrorKind::Unsupported, 40 | } 41 | } 42 | } 43 | 44 | impl error::Error for Error { 45 | #[cold] 46 | fn source(&self) -> Option<&(dyn error::Error + 'static)> { 47 | match *self { 48 | Self::InvalidMarkerRead(ref err) => Some(err), 49 | Self::InvalidDataRead(ref err) => Some(err), 50 | Self::DepthLimitExceeded => None, 51 | } 52 | } 53 | } 54 | 55 | impl Display for Error { 56 | #[cold] 57 | fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), fmt::Error> { 58 | match *self { 59 | Self::InvalidMarkerRead(ref err) => { 60 | write!(fmt, "I/O error while reading marker byte: {err}") 61 | } 62 | Self::InvalidDataRead(ref err) => { 63 | write!(fmt, "I/O error while reading non-marker bytes: {err}") 64 | } 65 | Self::DepthLimitExceeded => { 66 | write!(fmt, "depth limit exceeded") 67 | } 68 | } 69 | } 70 | } 71 | 72 | impl From for Error { 73 | #[cold] 74 | fn from(err: MarkerReadError) -> Self { 75 | Self::InvalidMarkerRead(err.0) 76 | } 77 | } 78 | 79 | impl From for Error { 80 | #[cold] 81 | fn from(err: ValueReadError) -> Self { 82 | match err { 83 | ValueReadError::InvalidMarkerRead(err) => Self::InvalidMarkerRead(err), 84 | ValueReadError::InvalidDataRead(err) => Self::InvalidDataRead(err), 85 | ValueReadError::TypeMismatch(..) => { 86 | Self::InvalidMarkerRead(io::Error::new(ErrorKind::Other, "type mismatch")) 87 | } 88 | } 89 | } 90 | } 91 | 92 | impl From for io::Error { 93 | #[cold] 94 | fn from(val: Error) -> Self { 95 | match val { 96 | Error::InvalidMarkerRead(err) | 97 | Error::InvalidDataRead(err) => err, 98 | Error::DepthLimitExceeded => Self::new(val.kind(), val), 99 | } 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /rmpv/src/decode/value.rs: -------------------------------------------------------------------------------- 1 | use std::cmp::min; 2 | use std::io::{self, Read}; 3 | 4 | use rmp::decode::{read_marker, RmpRead}; 5 | use rmp::Marker; 6 | 7 | use super::Error; 8 | use crate::{Utf8String, Value}; 9 | 10 | // See https://github.com/3Hren/msgpack-rust/issues/151 11 | const PREALLOC_MAX: usize = 64 * 1024; // 64 KiB 12 | 13 | fn read_array_data(rd: &mut R, mut len: usize, depth: u16) -> Result, Error> { 14 | let depth = super::decrement_depth(depth)?; 15 | 16 | // Note: Do not preallocate a Vec of size `len`. 17 | // See https://github.com/3Hren/msgpack-rust/issues/151 18 | let mut vec = Vec::new(); 19 | 20 | while len > 0 { 21 | vec.push(read_value_inner(rd, depth)?); 22 | len -= 1; 23 | } 24 | 25 | Ok(vec) 26 | } 27 | 28 | fn read_map_data(rd: &mut R, mut len: usize, depth: u16) -> Result, Error> { 29 | let depth = super::decrement_depth(depth)?; 30 | 31 | // Note: Do not preallocate a Vec of size `len`. 32 | // See https://github.com/3Hren/msgpack-rust/issues/151 33 | let mut vec = Vec::new(); 34 | 35 | while len > 0 { 36 | vec.push((read_value_inner(rd, depth)?, read_value_inner(rd, depth)?)); 37 | len -= 1; 38 | } 39 | 40 | Ok(vec) 41 | } 42 | 43 | fn read_str_data(rd: &mut R, len: usize, depth: u16) -> Result { 44 | let depth = super::decrement_depth(depth)?; 45 | 46 | match String::from_utf8(read_bin_data(rd, len, depth)?) { 47 | Ok(s) => Ok(Utf8String::from(s)), 48 | Err(err) => { 49 | let e = err.utf8_error(); 50 | let s = Utf8String { 51 | s: Err((err.into_bytes(), e)), 52 | }; 53 | Ok(s) 54 | } 55 | } 56 | } 57 | 58 | fn read_bin_data(rd: &mut R, len: usize, depth: u16) -> Result, Error> { 59 | let _depth = super::decrement_depth(depth)?; 60 | 61 | let mut buf = Vec::with_capacity(min(len, PREALLOC_MAX)); 62 | let bytes_read = rd.take(len as u64).read_to_end(&mut buf).map_err(Error::InvalidDataRead)?; 63 | if bytes_read != len { 64 | return Err(Error::InvalidDataRead(io::Error::new( 65 | io::ErrorKind::UnexpectedEof, 66 | format!("Expected {len} bytes, read {bytes_read} bytes"), 67 | ))); 68 | } 69 | 70 | Ok(buf) 71 | } 72 | 73 | fn read_ext_body(rd: &mut R, len: usize, depth: u16) -> Result<(i8, Vec), Error> { 74 | let depth = super::decrement_depth(depth)?; 75 | 76 | let ty = rd.read_data_i8()?; 77 | let vec = read_bin_data(rd, len, depth)?; 78 | 79 | Ok((ty, vec)) 80 | } 81 | 82 | #[inline(never)] 83 | fn read_value_inner(rd: &mut R, depth: u16) -> Result where R: Read { 84 | let depth = super::decrement_depth(depth)?; 85 | let val = match read_marker(rd)? { 86 | Marker::Null => Value::Nil, 87 | Marker::True => Value::Boolean(true), 88 | Marker::False => Value::Boolean(false), 89 | Marker::FixPos(val) => Value::from(val), 90 | Marker::FixNeg(val) => Value::from(val), 91 | Marker::U8 => Value::from(rd.read_data_u8()?), 92 | Marker::U16 => Value::from(rd.read_data_u16()?), 93 | Marker::U32 => Value::from(rd.read_data_u32()?), 94 | Marker::U64 => Value::from(rd.read_data_u64()?), 95 | Marker::I8 => Value::from(rd.read_data_i8()?), 96 | Marker::I16 => Value::from(rd.read_data_i16()?), 97 | Marker::I32 => Value::from(rd.read_data_i32()?), 98 | Marker::I64 => Value::from(rd.read_data_i64()?), 99 | Marker::F32 => Value::F32(rd.read_data_f32()?), 100 | Marker::F64 => Value::F64(rd.read_data_f64()?), 101 | Marker::FixStr(len) => { 102 | let res = read_str_data(rd, len as usize, depth)?; 103 | Value::String(res) 104 | } 105 | Marker::Str8 => { 106 | let len = rd.read_data_u8()?; 107 | let res = read_str_data(rd, len as usize, depth)?; 108 | Value::String(res) 109 | } 110 | Marker::Str16 => { 111 | let len = rd.read_data_u16()?; 112 | let res = read_str_data(rd, len as usize, depth)?; 113 | Value::String(res) 114 | } 115 | Marker::Str32 => { 116 | let len = rd.read_data_u32()?; 117 | let res = read_str_data(rd, len as usize, depth)?; 118 | Value::String(res) 119 | } 120 | Marker::FixArray(len) => { 121 | let vec = read_array_data(rd, len as usize, depth)?; 122 | Value::Array(vec) 123 | } 124 | Marker::Array16 => { 125 | let len = rd.read_data_u16()?; 126 | let vec = read_array_data(rd, len as usize, depth)?; 127 | Value::Array(vec) 128 | } 129 | Marker::Array32 => { 130 | let len = rd.read_data_u32()?; 131 | let vec = read_array_data(rd, len as usize, depth)?; 132 | Value::Array(vec) 133 | } 134 | Marker::FixMap(len) => { 135 | let map = read_map_data(rd, len as usize, depth)?; 136 | Value::Map(map) 137 | } 138 | Marker::Map16 => { 139 | let len = rd.read_data_u16()?; 140 | let map = read_map_data(rd, len as usize, depth)?; 141 | Value::Map(map) 142 | } 143 | Marker::Map32 => { 144 | let len = rd.read_data_u32()?; 145 | let map = read_map_data(rd, len as usize, depth)?; 146 | Value::Map(map) 147 | } 148 | Marker::Bin8 => { 149 | let len = rd.read_data_u8()?; 150 | let vec = read_bin_data(rd, len as usize, depth)?; 151 | Value::Binary(vec) 152 | } 153 | Marker::Bin16 => { 154 | let len = rd.read_data_u16()?; 155 | let vec = read_bin_data(rd, len as usize, depth)?; 156 | Value::Binary(vec) 157 | } 158 | Marker::Bin32 => { 159 | let len = rd.read_data_u32()?; 160 | let vec = read_bin_data(rd, len as usize, depth)?; 161 | Value::Binary(vec) 162 | } 163 | Marker::FixExt1 => { 164 | let len = 1_usize; 165 | let (ty, vec) = read_ext_body(rd, len, depth)?; 166 | Value::Ext(ty, vec) 167 | } 168 | Marker::FixExt2 => { 169 | let len = 2_usize; 170 | let (ty, vec) = read_ext_body(rd, len, depth)?; 171 | Value::Ext(ty, vec) 172 | } 173 | Marker::FixExt4 => { 174 | let len = 4_usize; 175 | let (ty, vec) = read_ext_body(rd, len, depth)?; 176 | Value::Ext(ty, vec) 177 | } 178 | Marker::FixExt8 => { 179 | let len = 8_usize; 180 | let (ty, vec) = read_ext_body(rd, len, depth)?; 181 | Value::Ext(ty, vec) 182 | } 183 | Marker::FixExt16 => { 184 | let len = 16_usize; 185 | let (ty, vec) = read_ext_body(rd, len, depth)?; 186 | Value::Ext(ty, vec) 187 | } 188 | Marker::Ext8 => { 189 | let len = rd.read_data_u8()? as usize; 190 | let (ty, vec) = read_ext_body(rd, len, depth)?; 191 | Value::Ext(ty, vec) 192 | } 193 | Marker::Ext16 => { 194 | let len = rd.read_data_u16()? as usize; 195 | let (ty, vec) = read_ext_body(rd, len, depth)?; 196 | Value::Ext(ty, vec) 197 | } 198 | Marker::Ext32 => { 199 | let len = rd.read_data_u32()? as usize; 200 | let (ty, vec) = read_ext_body(rd, len, depth)?; 201 | Value::Ext(ty, vec) 202 | } 203 | Marker::Reserved => Value::Nil, 204 | }; 205 | 206 | Ok(val) 207 | } 208 | 209 | /// Attempts to read bytes from the given reader and interpret them as a [`Value`]. 210 | /// 211 | /// # Errors 212 | /// 213 | /// This function will return [`Error`] on any I/O error while either reading or decoding a [`Value`]. 214 | /// All instances of [`ErrorKind::Interrupted`](io::ErrorKind) are handled by this function and the 215 | /// underlying operation is retried. 216 | /// 217 | /// [`Error::DepthLimitExceeded`] is returned if this function recurses 218 | /// [`MAX_DEPTH`](super::MAX_DEPTH) times. To configure the maximum recursion depth, use 219 | /// [`read_value_with_max_depth`] instead. 220 | #[inline] 221 | pub fn read_value(rd: &mut R) -> Result 222 | where R: Read 223 | { 224 | read_value_inner(rd, super::MAX_DEPTH as _) 225 | } 226 | 227 | /// Attempts to read bytes from the given reader and interpret them as a [`Value`]. 228 | /// 229 | /// # Errors 230 | /// 231 | /// This function will return [`Error`] on any I/O error while either reading or decoding a [`Value`]. 232 | /// All instances of [`ErrorKind::Interrupted`](io::ErrorKind) are handled by this function and the 233 | /// underlying operation is retried. 234 | /// 235 | /// [`Error::DepthLimitExceeded`] is returned if this function recurses 236 | /// `max_depth` times. If the default [`MAX_DEPTH`](super::MAX_DEPTH) is sufficient or you do not 237 | /// need recursion depth checking for your data, consider using [`read_value`] instead. 238 | #[inline] 239 | pub fn read_value_with_max_depth(rd: &mut R, max_depth: usize) -> Result 240 | where R: Read 241 | { 242 | read_value_inner(rd, max_depth.min(u16::MAX as usize) as u16) 243 | } 244 | -------------------------------------------------------------------------------- /rmpv/src/encode/mod.rs: -------------------------------------------------------------------------------- 1 | pub use rmp::encode::ValueWriteError as Error; 2 | 3 | mod value; 4 | mod value_ref; 5 | 6 | pub use self::value::write_value; 7 | pub use self::value_ref::write_value_ref; 8 | -------------------------------------------------------------------------------- /rmpv/src/encode/value.rs: -------------------------------------------------------------------------------- 1 | use std::io::Write; 2 | 3 | use rmp::encode::{ 4 | write_array_len, write_bin, write_bool, write_ext_meta, write_f32, write_f64, write_map_len, 5 | write_nil, write_sint, write_str, write_uint, 6 | }; 7 | 8 | use super::Error; 9 | use crate::{IntPriv, Integer, Utf8String, Value}; 10 | 11 | /// Encodes and attempts to write the most efficient representation of the given Value. 12 | /// 13 | /// # Note 14 | /// 15 | /// All instances of `ErrorKind::Interrupted` are handled by this function and the underlying 16 | /// operation is retried. 17 | pub fn write_value(wr: &mut W, val: &Value) -> Result<(), Error> 18 | where W: Write 19 | { 20 | match *val { 21 | Value::Nil => { 22 | write_nil(wr).map_err(Error::InvalidMarkerWrite)?; 23 | } 24 | Value::Boolean(val) => { 25 | write_bool(wr, val).map_err(Error::InvalidMarkerWrite)?; 26 | } 27 | Value::Integer(Integer { n }) => match n { 28 | IntPriv::PosInt(n) => { 29 | write_uint(wr, n)?; 30 | } 31 | IntPriv::NegInt(n) => { 32 | write_sint(wr, n)?; 33 | } 34 | }, 35 | Value::F32(val) => { 36 | write_f32(wr, val)?; 37 | } 38 | Value::F64(val) => { 39 | write_f64(wr, val)?; 40 | } 41 | Value::String(Utf8String { ref s }) => match *s { 42 | Ok(ref val) => write_str(wr, val)?, 43 | Err(ref err) => write_bin(wr, &err.0)?, 44 | }, 45 | Value::Binary(ref val) => { 46 | write_bin(wr, val)?; 47 | } 48 | Value::Array(ref vec) => { 49 | write_array_len(wr, vec.len() as u32)?; 50 | for v in vec { 51 | write_value(wr, v)?; 52 | } 53 | } 54 | Value::Map(ref map) => { 55 | write_map_len(wr, map.len() as u32)?; 56 | for (key, val) in map { 57 | write_value(wr, key)?; 58 | write_value(wr, val)?; 59 | } 60 | } 61 | Value::Ext(ty, ref data) => { 62 | write_ext_meta(wr, data.len() as u32, ty)?; 63 | wr.write_all(data).map_err(Error::InvalidDataWrite)?; 64 | } 65 | } 66 | 67 | Ok(()) 68 | } 69 | -------------------------------------------------------------------------------- /rmpv/src/encode/value_ref.rs: -------------------------------------------------------------------------------- 1 | use std::io::Write; 2 | 3 | use rmp::encode::{ 4 | write_array_len, write_bin, write_bool, write_ext_meta, write_f32, write_f64, write_map_len, 5 | write_nil, write_sint, write_str, write_uint, 6 | }; 7 | 8 | use super::Error; 9 | use crate::{IntPriv, Integer, Utf8StringRef, ValueRef}; 10 | 11 | /// Encodes and attempts to write the given non-owning `ValueRef` into the Write. 12 | /// 13 | /// # Errors 14 | /// 15 | /// This function returns Error with an underlying I/O error if unable to properly write entire 16 | /// value. Interruption errors are handled internally by silent operation restarting. 17 | /// 18 | /// # Examples 19 | /// ``` 20 | /// use rmpv::ValueRef; 21 | /// use rmpv::encode::write_value_ref; 22 | /// 23 | /// let mut buf = Vec::new(); 24 | /// let val = ValueRef::from("le message"); 25 | /// 26 | /// write_value_ref(&mut buf, &val).unwrap(); 27 | /// assert_eq!(vec![0xaa, 0x6c, 0x65, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65], buf); 28 | /// ``` 29 | pub fn write_value_ref(wr: &mut W, val: &ValueRef<'_>) -> Result<(), Error> 30 | where W: Write 31 | { 32 | match *val { 33 | ValueRef::Nil => { 34 | write_nil(wr).map_err(Error::InvalidMarkerWrite)?; 35 | } 36 | ValueRef::Boolean(val) => { 37 | write_bool(wr, val).map_err(Error::InvalidMarkerWrite)?; 38 | } 39 | ValueRef::Integer(Integer { n }) => match n { 40 | IntPriv::PosInt(n) => { 41 | write_uint(wr, n)?; 42 | } 43 | IntPriv::NegInt(n) => { 44 | write_sint(wr, n)?; 45 | } 46 | }, 47 | ValueRef::F32(val) => { 48 | write_f32(wr, val)?; 49 | } 50 | ValueRef::F64(val) => { 51 | write_f64(wr, val)?; 52 | } 53 | ValueRef::String(Utf8StringRef { s }) => match s { 54 | Ok(val) => write_str(wr, val)?, 55 | Err(err) => write_bin(wr, err.0)?, 56 | }, 57 | ValueRef::Binary(val) => { 58 | write_bin(wr, val)?; 59 | } 60 | ValueRef::Array(ref vec) => { 61 | write_array_len(wr, vec.len() as u32)?; 62 | for v in vec { 63 | write_value_ref(wr, v)?; 64 | } 65 | } 66 | ValueRef::Map(ref map) => { 67 | write_map_len(wr, map.len() as u32)?; 68 | for (key, val) in map { 69 | write_value_ref(wr, key)?; 70 | write_value_ref(wr, val)?; 71 | } 72 | } 73 | ValueRef::Ext(ty, data) => { 74 | write_ext_meta(wr, data.len() as u32, ty)?; 75 | wr.write_all(data).map_err(Error::InvalidDataWrite)?; 76 | } 77 | } 78 | 79 | Ok(()) 80 | } 81 | -------------------------------------------------------------------------------- /rmpv/src/ext/mod.rs: -------------------------------------------------------------------------------- 1 | use std::error; 2 | use std::fmt::{self, Display, Formatter}; 3 | 4 | use serde::de::Unexpected; 5 | 6 | use crate::{IntPriv, Integer, Value, ValueRef}; 7 | 8 | pub use self::de::{deserialize_from, from_value, EnumRefDeserializer}; 9 | pub use self::se::to_value; 10 | 11 | mod de; 12 | mod se; 13 | 14 | #[derive(Debug)] 15 | pub enum Error { 16 | Syntax(String), 17 | } 18 | 19 | impl Display for Error { 20 | #[cold] 21 | fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), fmt::Error> { 22 | match *self { 23 | Self::Syntax(ref err) => write!(fmt, "error while decoding value: {err}"), 24 | } 25 | } 26 | } 27 | 28 | impl error::Error for Error {} 29 | 30 | trait ValueExt { 31 | fn unexpected(&self) -> Unexpected<'_>; 32 | } 33 | 34 | impl ValueExt for Value { 35 | #[cold] 36 | fn unexpected(&self) -> Unexpected<'_> { 37 | match *self { 38 | Self::Nil => Unexpected::Unit, 39 | Self::Boolean(v) => Unexpected::Bool(v), 40 | Self::Integer(Integer { n }) => match n { 41 | IntPriv::PosInt(v) => Unexpected::Unsigned(v), 42 | IntPriv::NegInt(v) => Unexpected::Signed(v), 43 | }, 44 | Self::F32(v) => Unexpected::Float(f64::from(v)), 45 | Self::F64(v) => Unexpected::Float(v), 46 | Self::String(ref v) => match v.s { 47 | Ok(ref v) => Unexpected::Str(v), 48 | Err(ref v) => Unexpected::Bytes(&v.0[..]), 49 | }, 50 | Self::Binary(ref v) => Unexpected::Bytes(v), 51 | Self::Array(..) => Unexpected::Seq, 52 | Self::Map(..) => Unexpected::Map, 53 | Self::Ext(..) => Unexpected::Seq, 54 | } 55 | } 56 | } 57 | 58 | impl ValueExt for ValueRef<'_> { 59 | #[cold] 60 | fn unexpected(&self) -> Unexpected<'_> { 61 | match *self { 62 | ValueRef::Nil => Unexpected::Unit, 63 | ValueRef::Boolean(v) => Unexpected::Bool(v), 64 | ValueRef::Integer(Integer { n }) => match n { 65 | IntPriv::PosInt(v) => Unexpected::Unsigned(v), 66 | IntPriv::NegInt(v) => Unexpected::Signed(v), 67 | }, 68 | ValueRef::F32(v) => Unexpected::Float(f64::from(v)), 69 | ValueRef::F64(v) => Unexpected::Float(v), 70 | ValueRef::String(ref v) => match v.s { 71 | Ok(v) => Unexpected::Str(v), 72 | Err(ref v) => Unexpected::Bytes(v.0), 73 | }, 74 | ValueRef::Binary(v) => Unexpected::Bytes(v), 75 | ValueRef::Array(..) => Unexpected::Seq, 76 | ValueRef::Map(..) => Unexpected::Map, 77 | ValueRef::Ext(..) => Unexpected::Seq, 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /rmpv/tests/encode_ref.rs: -------------------------------------------------------------------------------- 1 | use rmpv::encode::write_value_ref; 2 | use rmpv::ValueRef; 3 | 4 | #[test] 5 | fn pack_nil() { 6 | let mut buf = [0x00]; 7 | 8 | let val = ValueRef::Nil; 9 | 10 | write_value_ref(&mut &mut buf[..], &val).unwrap(); 11 | 12 | assert_eq!([0xc0], buf); 13 | } 14 | 15 | #[test] 16 | fn pack_nil_when_buffer_is_tool_small() { 17 | let mut buf = []; 18 | 19 | let val = ValueRef::Nil; 20 | 21 | match write_value_ref(&mut &mut buf[..], &val) { 22 | Err(..) => (), 23 | other => panic!("unexpected result: {other:?}"), 24 | } 25 | } 26 | 27 | #[test] 28 | fn pass_pack_true() { 29 | let mut buf = [0x00]; 30 | 31 | let val = ValueRef::Boolean(true); 32 | 33 | write_value_ref(&mut &mut buf[..], &val).unwrap(); 34 | 35 | assert_eq!([0xc3], buf); 36 | } 37 | 38 | #[test] 39 | fn pass_pack_uint_u16() { 40 | let mut buf = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; 41 | 42 | let val = ValueRef::from(65535); 43 | 44 | write_value_ref(&mut &mut buf[..], &val).unwrap(); 45 | 46 | assert_eq!([0xcd, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], buf); 47 | } 48 | 49 | #[test] 50 | fn pass_pack_i64() { 51 | let mut buf = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]; 52 | 53 | let val = ValueRef::from(-9223372036854775808i64); 54 | 55 | write_value_ref(&mut &mut buf[..], &val).unwrap(); 56 | 57 | assert_eq!([0xd3, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], buf); 58 | } 59 | 60 | fn check_packed_eq(expected: &Vec, actual: &ValueRef<'_>) { 61 | let mut buf = Vec::new(); 62 | 63 | write_value_ref(&mut buf, actual).unwrap(); 64 | 65 | assert_eq!(*expected, buf); 66 | } 67 | 68 | #[test] 69 | fn pass_pack_f32() { 70 | check_packed_eq( 71 | &vec![0xca, 0x7f, 0x7f, 0xff, 0xff], 72 | &ValueRef::F32(3.4028234e38_f32), 73 | ); 74 | } 75 | 76 | #[test] 77 | fn pass_pack_f64() { 78 | use std::f64; 79 | check_packed_eq( 80 | &vec![0xcb, 0x7f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00], 81 | &ValueRef::F64(f64::INFINITY), 82 | ); 83 | } 84 | 85 | #[test] 86 | fn pass_pack_string() { 87 | check_packed_eq( 88 | &vec![0xaa, 0x6c, 0x65, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65], 89 | &ValueRef::from("le message") 90 | ); 91 | } 92 | 93 | #[test] 94 | fn pass_pack_bin() { 95 | check_packed_eq( 96 | &vec![0xc4, 0x0a, 0x6c, 0x65, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65], 97 | &ValueRef::Binary(&[0x6c, 0x65, 0x20, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65]) 98 | ); 99 | } 100 | 101 | #[test] 102 | fn pass_pack_array() { 103 | check_packed_eq( 104 | &vec![0x93, 0x01, 0x02, 0x03], 105 | &ValueRef::Array(vec![ 106 | ValueRef::from(1), 107 | ValueRef::from(2), 108 | ValueRef::from(3), 109 | ]), 110 | ); 111 | } 112 | 113 | #[test] 114 | fn pass_pack_map() { 115 | check_packed_eq( 116 | &vec![0x81, 0x01, 0x02], 117 | &ValueRef::Map( 118 | vec![(ValueRef::from(1), ValueRef::from(2))] 119 | ) 120 | ); 121 | } 122 | 123 | #[test] 124 | fn pass_pack_ext() { 125 | check_packed_eq( 126 | &vec![0xc7, 0x03, 0x10, 0x01, 0x02, 0x03], 127 | &ValueRef::Ext(16, &[0x01, 0x02, 0x03]), 128 | ); 129 | } 130 | -------------------------------------------------------------------------------- /rmpv/tests/mirror.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] 2 | extern crate quickcheck; 3 | 4 | use rmpv::decode::read_value; 5 | use rmpv::encode::write_value; 6 | use rmpv::Value; 7 | 8 | fn mirror_test(xs: T) -> bool 9 | where Value: From 10 | { 11 | let mut buf = Vec::new(); 12 | write_value(&mut buf, &Value::from(xs.clone())).unwrap(); 13 | 14 | Value::from(xs) == read_value(&mut &buf[..]).unwrap() 15 | } 16 | 17 | quickcheck! { 18 | fn mirror_uint(xs: u64) -> bool { 19 | mirror_test(xs) 20 | } 21 | 22 | fn mirror_sint(xs: i64) -> bool { 23 | mirror_test(xs) 24 | } 25 | 26 | fn mirror_f32_value(xs: f32) -> bool { 27 | let mut buf = Vec::new(); 28 | write_value(&mut buf, &Value::from(xs)).unwrap(); 29 | let eq = Value::from(xs) == read_value(&mut &buf[..]).unwrap(); 30 | 31 | eq || (!eq && xs.is_nan()) 32 | } 33 | 34 | fn mirror_f64_value(xs: f64) -> bool { 35 | let mut buf = Vec::new(); 36 | write_value(&mut buf, &Value::from(xs)).unwrap(); 37 | let eq = Value::from(xs) == read_value(&mut &buf[..]).unwrap(); 38 | 39 | eq || (!eq && xs.is_nan()) 40 | } 41 | 42 | fn mirror_str(xs: String) -> bool { 43 | mirror_test(xs) 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /rmpv/tests/value.rs: -------------------------------------------------------------------------------- 1 | use rmpv::Value; 2 | 3 | #[test] 4 | fn display_nil() { 5 | assert_eq!("nil", format!("{}", Value::Nil)); 6 | } 7 | 8 | #[test] 9 | fn display_bool() { 10 | assert_eq!("true", format!("{}", Value::Boolean(true))); 11 | assert_eq!("false", format!("{}", Value::Boolean(false))); 12 | } 13 | 14 | #[test] 15 | fn display_int() { 16 | assert_eq!("42", format!("{}", Value::from(42))); 17 | assert_eq!("42", format!("{}", Value::from(42))); 18 | } 19 | 20 | #[test] 21 | fn display_float() { 22 | assert_eq!("3.1415", format!("{}", Value::F32(3.1415))); 23 | assert_eq!("3.1415", format!("{}", Value::F64(3.1415))); 24 | } 25 | 26 | #[test] 27 | fn display_string() { 28 | assert_eq!("\"le string\"", format!("{}", Value::String("le string".into()))); 29 | } 30 | 31 | #[test] 32 | fn display_binary() { 33 | assert_eq!("[108, 101, 32, 115, 116, 114, 105, 110, 103]", format!("{}", 34 | Value::Binary(b"le string".to_vec()))); 35 | } 36 | 37 | #[test] 38 | fn display_array() { 39 | assert_eq!("[]", format!("{}", Value::Array(vec![]))); 40 | assert_eq!("[nil]", format!("{}", Value::Array(vec![Value::Nil]))); 41 | assert_eq!("[nil, nil]", format!("{}", Value::Array(vec![Value::Nil, Value::Nil]))); 42 | } 43 | 44 | #[test] 45 | fn display_map() { 46 | assert_eq!("{}", format!("{}", Value::Map(vec![]))); 47 | assert_eq!("{nil: nil}", format!("{}", Value::Map(vec![(Value::Nil, Value::Nil)]))); 48 | assert_eq!("{nil: nil, true: false}", format!("{}", Value::Map(vec![(Value::Nil, Value::Nil), 49 | (Value::Boolean(true), Value::Boolean(false))]))); 50 | } 51 | 52 | #[test] 53 | fn display_ext() { 54 | assert_eq!("[1, []]", format!("{}", Value::Ext(1, vec![]))); 55 | assert_eq!("[1, [100]]", format!("{}", Value::Ext(1, vec![100]))); 56 | assert_eq!("[1, [100, 42]]", format!("{}", Value::Ext(1, vec![100, 42]))); 57 | } 58 | 59 | #[test] 60 | fn from_bool() { 61 | assert_eq!(Value::Boolean(true), Value::from(true)); 62 | assert_eq!(Value::Boolean(false), Value::from(false)); 63 | } 64 | 65 | #[test] 66 | fn from_u8() { 67 | assert_eq!(Value::from(42), Value::from(42u8)); 68 | } 69 | 70 | #[test] 71 | fn from_u16() { 72 | assert_eq!(Value::from(42), Value::from(42u16)); 73 | } 74 | 75 | #[test] 76 | fn from_u32() { 77 | assert_eq!(Value::from(42), Value::from(42u32)); 78 | } 79 | 80 | #[test] 81 | fn from_u64() { 82 | assert_eq!(Value::from(42), Value::from(42u64)); 83 | } 84 | 85 | #[test] 86 | fn from_usize() { 87 | assert_eq!(Value::from(42), Value::from(42usize)); 88 | } 89 | 90 | #[test] 91 | fn from_i8() { 92 | assert_eq!(Value::from(-42), Value::from(-42i8)); 93 | } 94 | 95 | #[test] 96 | fn from_i16() { 97 | assert_eq!(Value::from(-42), Value::from(-42i16)); 98 | } 99 | 100 | #[test] 101 | fn from_i32() { 102 | assert_eq!(Value::from(-42), Value::from(-42i32)); 103 | } 104 | 105 | #[test] 106 | fn from_i64() { 107 | assert_eq!(Value::from(-42), Value::from(-42i64)); 108 | } 109 | 110 | #[test] 111 | fn from_isize() { 112 | assert_eq!(Value::from(-42), Value::from(-42isize)); 113 | } 114 | 115 | #[test] 116 | fn from_f32() { 117 | assert_eq!(Value::F32(3.1415), Value::from(3.1415f32)); 118 | } 119 | 120 | #[test] 121 | fn from_f64() { 122 | assert_eq!(Value::F64(3.1415), Value::from(3.1415f64)); 123 | } 124 | 125 | #[test] 126 | fn from_iterator() { 127 | let v: Vec = vec![0u8, 1u8, 2u8]; 128 | let w: Value = v.into_iter().collect(); 129 | 130 | let w2 = Value::Array(vec![ 131 | Value::from(0u8), 132 | Value::from(1u8), 133 | Value::from(2u8) 134 | ]); 135 | 136 | assert_eq!(w, w2); 137 | 138 | let w3 = Value::Binary(vec![0u8, 1u8, 2u8]); 139 | 140 | assert!(w != w3); 141 | } 142 | 143 | #[test] 144 | fn is_nil() { 145 | assert!(Value::Nil.is_nil()); 146 | assert!(!Value::Boolean(true).is_nil()); 147 | } 148 | 149 | #[test] 150 | fn monadic_index() { 151 | let val = Value::Array(vec![ 152 | Value::Array(vec![ 153 | Value::String("value".into()), 154 | Value::Boolean(true), 155 | ]), 156 | Value::Boolean(false), 157 | ]); 158 | 159 | assert_eq!("value", val[0][0].as_str().unwrap()); 160 | assert!(val[0][1].as_bool().unwrap()); 161 | assert!(!val[1].as_bool().unwrap()); 162 | 163 | assert!(val[0][0][0].is_nil()); 164 | assert!(val[2].is_nil()); 165 | assert!(val[1][2][3][4][5].is_nil()); 166 | } 167 | 168 | #[test] 169 | fn index_into_map() { 170 | let val = Value::Map(vec![ 171 | ( Value::String("a".into()), Value::from(1) ), 172 | ( Value::String("b".into()), Value::Array(vec![ 173 | Value::from(3), 174 | Value::from(4), 175 | Value::from(5) 176 | ])), 177 | ( Value::String("c".into()), Value::Map(vec![ 178 | ( Value::String("d".into()), Value::from(8) ), 179 | ( Value::String("e".into()), Value::from(9) ) 180 | ])) 181 | ]); 182 | assert_eq!(1, val["a"].as_i64().unwrap()); 183 | assert_eq!(5, val["b"][2].as_i64().unwrap()); 184 | assert_eq!(9, val["c"]["e"].as_i64().unwrap()); 185 | assert!(val["b"][3].is_nil()); 186 | assert!(val["d"][4].is_nil()); 187 | } 188 | 189 | #[test] 190 | fn try_from_val() { 191 | use rmpv::Utf8String; 192 | use std::convert::TryInto; 193 | 194 | assert_eq!(false, Value::Boolean(false).try_into().unwrap()); 195 | assert_eq!(Utf8String::from("spook"), Value::from("spook").try_into().unwrap()); 196 | assert_eq!(String::from("spook"), TryInto::::try_into(Value::from("spook")).unwrap()); 197 | assert_eq!(vec![0], TryInto::>::try_into(Value::Binary(vec![0u8])).unwrap()); 198 | } 199 | --------------------------------------------------------------------------------