#[macro_export(local_inner_macros)]
macro_rules! msgpack_to_value {
($($msgpack:tt)+) => {
msgpack_internal!($($msgpack)+)
};
}
#[macro_export(local_inner_macros)]
macro_rules! msgpack {
($($msgpack:tt)+) => {
{
let mut buf = Vec::new();
let value = msgpack_internal!($($msgpack)+);
$crate::write_value(&mut buf, &value).unwrap();
buf
}
};
}
#[macro_export(local_inner_macros)]
#[doc(hidden)]
macro_rules! msgpack_internal {
(@array [$($elems:expr,)*]) => {
msgpack_internal_vec![$($elems,)*]
};
(@array [$($elems:expr),*]) => {
msgpack_internal_vec![$($elems),*]
};
(@array [$($elems:expr,)*] null $($rest:tt)*) => {
msgpack_internal!(@array [$($elems,)* msgpack_internal!(null)] $($rest)*)
};
(@array [$($elems:expr,)*] true $($rest:tt)*) => {
msgpack_internal!(@array [$($elems,)* msgpack_internal!(true)] $($rest)*)
};
(@array [$($elems:expr,)*] false $($rest:tt)*) => {
msgpack_internal!(@array [$($elems,)* msgpack_internal!(false)] $($rest)*)
};
(@array [$($elems:expr,)*] [$($array:tt)*] $($rest:tt)*) => {
msgpack_internal!(@array [$($elems,)* msgpack_internal!([$($array)*])] $($rest)*)
};
(@array [$($elems:expr,)*] {$($map:tt)*} $($rest:tt)*) => {
msgpack_internal!(@array [$($elems,)* msgpack_internal!({$($map)*})] $($rest)*)
};
(@array [$($elems:expr,)*] $next:expr, $($rest:tt)*) => {
msgpack_internal!(@array [$($elems,)* msgpack_internal!($next),] $($rest)*)
};
(@array [$($elems:expr,)*] $last:expr) => {
msgpack_internal!(@array [$($elems,)* msgpack_internal!($last)])
};
(@array [$($elems:expr),*] , $($rest:tt)*) => {
msgpack_internal!(@array [$($elems,)*] $($rest)*)
};
(@array [$($elems:expr),*] $unexpected:tt $($rest:tt)*) => {
msgpack_unexpected!($unexpected)
};
(@object $object:ident () () ()) => {};
(@object $object:ident [$($key:tt)+] ($value:expr) , $($rest:tt)*) => {
let _ = $object.insert(($($key)+).into(), $value);
msgpack_internal!(@object $object () ($($rest)*) ($($rest)*));
};
(@object $object:ident [$($key:tt)+] ($value:expr) $unexpected:tt $($rest:tt)*) => {
msgpack_unexpected!($unexpected);
};
(@object $object:ident [$($key:tt)+] ($value:expr)) => {
let _ = $object.insert(($($key)+).into(), $value);
};
(@object $object:ident ($($key:tt)+) (: null $($rest:tt)*) $copy:tt) => {
msgpack_internal!(@object $object [$($key)+] (msgpack_internal!(null)) $($rest)*);
};
(@object $object:ident ($($key:tt)+) (: true $($rest:tt)*) $copy:tt) => {
msgpack_internal!(@object $object [$($key)+] (msgpack_internal!(true)) $($rest)*);
};
(@object $object:ident ($($key:tt)+) (: false $($rest:tt)*) $copy:tt) => {
msgpack_internal!(@object $object [$($key)+] (msgpack_internal!(false)) $($rest)*);
};
(@object $object:ident ($($key:tt)+) (: [$($array:tt)*] $($rest:tt)*) $copy:tt) => {
msgpack_internal!(@object $object [$($key)+] (msgpack_internal!([$($array)*])) $($rest)*);
};
(@object $object:ident ($($key:tt)+) (: {$($map:tt)*} $($rest:tt)*) $copy:tt) => {
msgpack_internal!(@object $object [$($key)+] (msgpack_internal!({$($map)*})) $($rest)*);
};
(@object $object:ident ($($key:tt)+) (: $value:expr , $($rest:tt)*) $copy:tt) => {
msgpack_internal!(@object $object [$($key)+] (msgpack_internal!($value)) , $($rest)*);
};
(@object $object:ident ($($key:tt)+) (: $value:expr) $copy:tt) => {
msgpack_internal!(@object $object [$($key)+] (msgpack_internal!($value)));
};
(@object $object:ident ($($key:tt)+) (:) $copy:tt) => {
msgpack_internal!();
};
(@object $object:ident ($($key:tt)+) () $copy:tt) => {
msgpack_internal!();
};
(@object $object:ident () (: $($rest:tt)*) ($colon:tt $($copy:tt)*)) => {
msgpack_unexpected!($colon);
};
(@object $object:ident ($($key:tt)*) (, $($rest:tt)*) ($comma:tt $($copy:tt)*)) => {
msgpack_unexpected!($comma);
};
(@object $object:ident () (($key:expr) : $($rest:tt)*) $copy:tt) => {
msgpack_internal!(@object $object ($key) (: $($rest)*) (: $($rest)*));
};
(@object $object:ident ($($key:tt)*) (: $($unexpected:tt)+) $copy:tt) => {
msgpack_expect_expr_comma!($($unexpected)+);
};
(@object $object:ident ($($key:tt)*) ($tt:tt $($rest:tt)*) $copy:tt) => {
msgpack_internal!(@object $object ($($key)* $tt) ($($rest)*) ($($rest)*));
};
(null) => {
$crate::Value::Nil
};
(true) => {
$crate::Value::Boolean(true)
};
(false) => {
$crate::Value::Bool(false)
};
([]) => {
$crate::Value::Array(msgpack_internal_vec![])
};
([ $($tt:tt)+ ]) => {
$crate::Value::Array(msgpack_internal!(@array [] $($tt)+))
};
({}) => {
$crate::Value::Map($crate::RMPVObject::new().values)
};
({ $($tt:tt)+ }) => {
$crate::Value::Map({
let mut object = $crate::RMPVObject::new();
msgpack_internal!(@object object () ($($tt)+) ($($tt)+));
object.values
})
};
($other:expr) => {
$crate::Value::from($other)
};
}
#[macro_export]
#[doc(hidden)]
macro_rules! msgpack_internal_vec {
($($content:tt)*) => {
vec![$($content)*]
};
}
#[macro_export]
#[doc(hidden)]
macro_rules! msgpack_unexpected {
() => {};
}
#[macro_export]
#[doc(hidden)]
macro_rules! msgpack_expect_expr_comma {
($e:expr , $($tt:tt)*) => {};
}
#[cfg(test)]
mod tests {
use std::{collections::{BTreeMap}};
use rmp_serde::{to_vec, from_slice};
use rmpv::Value;
use crate::extensions::generic_map::GenericMap;
#[test]
fn msgpack() {
let value = msgpack_to_value!({
"code": 200,
"success": true,
"payload": {
"features": [
"serde",
"msgpack"
]
}
});
let mut expected_map_tuples: Vec<(Value, Value)> = Vec::new();
expected_map_tuples.push((Value::from("code"), Value::from(200)));
expected_map_tuples.push((Value::from("success"), Value::from(true)));
expected_map_tuples.push((
Value::from("payload"),
Value::Map(vec![(
Value::from("features"),
Value::Array(vec![Value::from("serde"), Value::from("msgpack")]),
)]),
));
let expected = Value::Map(expected_map_tuples);
assert_eq!(value, expected)
}
#[test]
fn msgpack_to_vec() {
let value = msgpack!({
"code": 200,
"success": true,
"payload": {
"features": [
"serde",
"msgpack"
]
}
});
assert_eq!(
value,
[
131, 164, 99, 111, 100, 101, 204, 200, 167, 115, 117, 99, 99, 101, 115, 115, 195,
167, 112, 97, 121, 108, 111, 97, 100, 129, 168, 102, 101, 97, 116, 117, 114, 101,
115, 146, 165, 115, 101, 114, 100, 101, 167, 109, 115, 103, 112, 97, 99, 107
]
)
}
#[test]
fn ext_type() {
let mut map = BTreeMap::new();
let mut map2 = BTreeMap::new();
map2.insert("foo".to_string(), "bar".to_string());
map.insert("key".to_string(), map2);
let gen = GenericMap(map);
let d = to_vec(&gen).unwrap();
println!("VEC: {:?}", d);
}
#[test]
fn decode_ext_type() {
let value: GenericMap<String, BTreeMap<String, String>> = from_slice(&[199, 14, 1, 129, 163, 107, 101, 121, 129, 163, 102, 111, 111, 163, 98, 97, 114]).unwrap();
println!("VALUE: {:?}", value);
}
}