1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
//! # The Rust MessagePack Library
//!
//! RMP is a pure Rust [MessagePack](http://msgpack.org) implementation of an efficient binary
//! serialization format. This crate provides low-level core functionality, writers and readers for
//! primitive values with direct mapping between binary MessagePack format.
//!
//! **Warning** this library is still in rapid development and everything may change until 1.0
//! comes.
//!
//! ## Usage
//!
//! To use `rmp`, first add this to your `Cargo.toml`:
//!
//! ```toml
//! [dependencies.rmp]
//! rmp = "^0.8"
//! ```
//!
//! Then, add this line to your crate root:
//!
//! ```rust
//! extern crate rmp;
//! ```
//!
//! ## Features
//!
//! - **Convenient API**
//!
//!   RMP is designed to be lightweight and straightforward. There are low-level API, which gives you
//!   full control on data encoding/decoding process and makes no heap allocations. On the other hand
//!   there are high-level API, which provides you convenient interface using Rust standard library and
//!   compiler reflection, allowing to encode/decode structures using `derive` attribute.
//!
//! - **Zero-copy value decoding**
//!
//!   RMP allows to decode bytes from a buffer in a zero-copy manner easily and blazingly fast, while Rust
//!   static checks guarantees that the data will be valid until buffer lives.
//!
//! - **Clear error handling**
//!
//!   RMP's error system guarantees that you never receive an error enum with unreachable variant.
//!
//! - **Robust and tested**
//!
//!   This project is developed using TDD and CI, so any found bugs will be fixed without breaking
//!   existing functionality.
//!
//! ## Detailed
//!
//! This crate represents the very basic functionality needed to work with MessagePack format.
//! Ideologically it is developed as a basis for building high-level abstractions.
//!
//! Currently there are two large modules: encode and decode. More detail you can find in the
//! corresponding sections.
//!
//! Formally every MessagePack message consists of some marker encapsulating a data type and the
//! data itself. Sometimes there are no separate data chunk, for example for booleans. In these
//! cases a marker contains the value. For example, the `true` value is encoded as `0xc3`.
//!
//! ```
//! let mut buf = Vec::new();
//! rmp::encode::write_bool(&mut buf, true).unwrap();
//!
//! assert_eq!([0xc3], buf[..]);
//! ```
//!
//! Sometimes a single value can be encoded in multiple ways. For example a value of `42` can be
//! represented as: `[0x2a], [0xcc, 0x2a], [0xcd, 0x00, 0x2a]` and so on, and all of them are
//! considered as valid representations. To allow fine-grained control over encoding such values
//! the library provides direct mapping functions.
//!
//! ```
//! let mut bufs = vec![vec![]; 5];
//!
//! rmp::encode::write_pfix(&mut bufs[0], 42).unwrap();
//! rmp::encode::write_u8(&mut bufs[1], 42).unwrap();
//! rmp::encode::write_u16(&mut bufs[2], 42).unwrap();
//! rmp::encode::write_u32(&mut bufs[3], 42).unwrap();
//! rmp::encode::write_u64(&mut bufs[4], 42).unwrap();
//!
//! assert_eq!([0x2a], bufs[0][..]);
//! assert_eq!([0xcc, 0x2a], bufs[1][..]);
//! assert_eq!([0xcd, 0x00, 0x2a], bufs[2][..]);
//! assert_eq!([0xce, 0x00, 0x00, 0x00, 0x2a], bufs[3][..]);
//! assert_eq!([0xcf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2a], bufs[4][..]);
//! ```
//!
//! But they aren't planned to be widely used. Instead we often need to encode bytes compactly to
//! save space. In these cases RMP provides functions that guarantee that for encoding the most
//! compact representation will be chosen.
//!
//! ```
//! let mut buf = Vec::new();
//!
//! rmp::encode::write_sint(&mut buf, 300).unwrap();
//!
//! assert_eq!([0xcd, 0x1, 0x2c], buf[..]);
//! ```
//!
//! On the other hand for deserialization it is not matter in which representation the value is
//! encoded - RMP deals with all of them.
//!
//! Sometimes you know the exact type representation and want to enforce the deserialization process
//! to make it strongly type safe.
//!
//! ```
//! let buf = [0xcd, 0x1, 0x2c];
//!
//! assert_eq!(300, rmp::decode::read_u16(&mut &buf[..]).unwrap());
//! ```
//!
//! However if you try to decode such bytearray as other integer type, for example `u32`, there will
//! be type mismatch error.
//!
//! ```
//! let buf = [0xcd, 0x1, 0x2c];
//! rmp::decode::read_u32(&mut &buf[..]).err().unwrap();
//! ```
//!
//! But sometimes all you want is just to encode an integer that *must* fit in the specified type
//! no matter how it was encoded. RMP provides [`such`][read_int] function to ease integration with
//! other MessagePack libraries.
//!
//! ```
//! let buf = [0xcd, 0x1, 0x2c];
//!
//! assert_eq!(300i16, rmp::decode::read_int(&mut &buf[..]).unwrap());
//! assert_eq!(300i32, rmp::decode::read_int(&mut &buf[..]).unwrap());
//! assert_eq!(300i64, rmp::decode::read_int(&mut &buf[..]).unwrap());
//! assert_eq!(300u16, rmp::decode::read_int(&mut &buf[..]).unwrap());
//! assert_eq!(300u32, rmp::decode::read_int(&mut &buf[..]).unwrap());
//! assert_eq!(300u64, rmp::decode::read_int(&mut &buf[..]).unwrap());
//! ```
//!
//! ## API
//!
//! Almost all API are represented as pure functions, which accepts a generic `Write` or `Read` and
//! the value to be encoded/decoded. For example let's do a round trip for π number.
//!
//! ```
//! let pi = std::f64::consts::PI;
//! let mut buf = Vec::new();
//! rmp::encode::write_f64(&mut buf, pi).unwrap();
//!
//! assert_eq!([0xcb, 0x40, 0x9, 0x21, 0xfb, 0x54, 0x44, 0x2d, 0x18], buf[..]);
//! assert_eq!(pi, rmp::decode::read_f64(&mut &buf[..]).unwrap());
//! ```
//!
//! [read_int]: decode/fn.read_int.html

extern crate byteorder;
extern crate num_traits;

mod marker;
pub mod encode;
pub mod decode;

pub use marker::Marker;

/// Version of the MessagePack [spec](http://github.com/msgpack/msgpack/blob/master/spec.md).
pub const MSGPACK_VERSION: u32 = 5;