[][src]Crate msgpack_simple

Simplified, easy to use, pure Rust MessagePack implementation focused on handling dynamic data structures.

Example usage:

use msgpack_simple::{MsgPack, MapElement, Extension};

let message = MsgPack::Map(vec![
    MapElement {
        key: MsgPack::String(String::from("hello")),
        value: MsgPack::Int(42)
    },
    MapElement {
        key: MsgPack::String(String::from("world")),
        value: MsgPack::Array(vec![
            MsgPack::Boolean(true),
            MsgPack::Nil,
            MsgPack::Binary(vec![0x42, 0xff]),
            MsgPack::Extension(Extension {
                type_id: 2,
                value: vec![0x32, 0x4a, 0x67, 0x11]
            })
        ])
    }
]);

let encoded = message.encode(); // encoded is a Vec<u8>
let decoded = MsgPack::parse(&encoded).unwrap();

println!("{}", decoded);
assert_eq!(message, decoded);
assert!(message.is_map());

let mut map = message.as_map().unwrap(); // map is a Vec<MapElement>
let second_element = map.remove(1);

assert!(second_element.key.is_string());
assert_eq!(second_element.key.as_string().unwrap(), "world".to_string());

assert!(second_element.value.is_array());

let mut array = second_element.value.as_array().unwrap(); // array is a Vec<MsgPack>
let nil = array.remove(1);

assert!(nil.is_nil());

Data is abstracted with the MsgPack enum, which can contain any kind of data encodable with MessagePack. This is designed for dynamic data, for static models, mneumann's rust-msgpack or 3Hren's RMP crates are recommended.

Decoding MsgPack

msgpack_simple provides two functions for decoding data. For general use, MsgPack::parse() is recommended:

use msgpack_simple::MsgPack;

let data = vec![0xaa, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x52, 0x75, 0x73, 0x74];
let decoded = MsgPack::parse(&data);
assert!(decoded.is_ok());

let decoded = decoded.unwrap();
assert!(decoded.is_string());
assert_eq!(decoded.as_string().unwrap(), "Hello Rust".to_string());

MsgPack::parse() takes a byte array slice (&[u8]) and returns an MsgPack enum wrapped in a result. The error type is ParseError, which can show the byte where the parser encountered an error if needed.

If you need more control, you can use the parser module directly:

use msgpack_simple::parser;

let data = vec![0xaa, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x52, 0x75, 0x73, 0x74, 0x00];
let (decoded, length) = parser::parse(&data).unwrap();

assert!(decoded.is_string());
assert_eq!(decoded.as_string().unwrap(), "Hello Rust".to_string());
assert_eq!(length, 11);

parser::parse() behaves identically, but it also returns the length of the MessagePack data parsed.

Encoding MsgPack

msgpack_simple provides the MsgPack.encode() function for encoding data:

use msgpack_simple::MsgPack;

let message = MsgPack::String("Hello Rust".to_string());
let encoded = message.encode();

let data = vec![0xaa, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x52, 0x75, 0x73, 0x74];
assert_eq!(encoded, data);

Accessing MsgPack

For every variant of the enum (String, Float, Array, etc.) MsgPack provides two convenience functions, one of which checks the data against the type (is_string(), is_float(), is_array(), etc.), and the other one transforms the MsgPack enum into the value it contains (as_string(), as_float(), as_array(), etc.).

use msgpack_simple::MsgPack;

let message = MsgPack::String("Hello Rust".to_string());

assert_eq!(message.is_float(), false);
assert_eq!(message.is_string(), true);

let float = message.clone().as_float(); // the as_type functions consume the MsgPack
let string = message.as_string();

assert!(float.is_err());
assert!(string.is_ok());

There are two special cases: as_nil() does not exist because the Nil variant holds no data, and there is an is_some_int() and as_some_int() pair, which matches both Int and Uint and returns i64.

Arrays, Maps, and Extensions

One of MessagePack's greatest strengths is a compact representation of dynamic, nested hierarchies. To access that, msgpack_simple provides simple Rust abstractions for these types:

  • Array is represented with Vec<MsgPack>
  • Map is represented with Vec<MapElement>
  • Extension is represented with Extension

MapElement and Extension are two custom structs with simple representations of their respective types. MapElement simply has a key and a value, both with the MsgPack type, and Extension has a type_id (i8) and a value (Vec<u8>).

use msgpack_simple::{MsgPack, MapElement, Extension};

let message = MsgPack::Array(vec![
    MsgPack::Map(vec![
        MapElement {
            key: MsgPack::String("foo".to_string()),
            value: MsgPack::Int(42)
        },
        MapElement {
            key: MsgPack::Extension(Extension {
                type_id: 27,
                value: vec![0x32]
            }),
            value: MsgPack::Binary(vec![0x2a, 0xf4])
        }
    ])
]);

let mut array = message.as_array().unwrap();
let mut map = array.remove(0).as_map().unwrap();

let first = map.remove(0);
let second = map.remove(0);

assert_eq!(first.value.as_some_int().unwrap(), 42);
assert_eq!(second.key.as_extension().unwrap().type_id, 27);

Modules

parser

The actual parser under the hood

Structs

ConversionError

An error that occurred when trying to access a field as a different type

Extension

Represents an extension field

MapElement

Represents an element in a MessagePack map

ParseError

An error that occurred while parsing a binary as MsgPack

Enums

MsgPack

A piece of MessagePack-compatible data