use super::number::Number;
use alloc::vec::Vec;
use messagepack_core::extension::ExtensionRef;
use serde::{de::Visitor, ser::SerializeMap};
#[derive(Debug, Clone, PartialEq, PartialOrd)]
pub enum ValueRef<'a> {
Nil,
Bool(bool),
Bin(&'a [u8]),
Extension(ExtensionRef<'a>),
Number(Number),
String(&'a str),
Array(Vec<ValueRef<'a>>),
Map(Vec<(ValueRef<'a>, ValueRef<'a>)>),
}
impl ValueRef<'_> {
pub fn is_nil(&self) -> bool {
matches!(self, ValueRef::Nil)
}
pub fn as_bool(&self) -> Option<bool> {
match self {
ValueRef::Bool(v) => Some(*v),
_ => None,
}
}
pub fn as_bin(&self) -> Option<&[u8]> {
match self {
ValueRef::Bin(v) => Some(*v),
_ => None,
}
}
pub fn as_extension(&self) -> Option<&ExtensionRef<'_>> {
match self {
ValueRef::Extension(v) => Some(v),
_ => None,
}
}
pub fn as_number(&self) -> Option<Number> {
match self {
ValueRef::Number(v) => Some(*v),
_ => None,
}
}
pub fn as_string(&self) -> Option<&str> {
match self {
ValueRef::String(v) => Some(*v),
_ => None,
}
}
pub fn as_array(&self) -> Option<&[ValueRef<'_>]> {
match self {
ValueRef::Array(v) => Some(v),
_ => None,
}
}
pub fn as_map(&self) -> Option<&[(ValueRef<'_>, ValueRef<'_>)]> {
match self {
ValueRef::Map(v) => Some(v),
_ => None,
}
}
}
impl serde::Serialize for ValueRef<'_> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
match self {
ValueRef::Nil => serializer.serialize_none(),
ValueRef::Bool(v) => serializer.serialize_bool(*v),
ValueRef::Bin(items) => serializer.serialize_bytes(items),
ValueRef::Extension(extension_ref) => {
crate::extension::ext_ref::serialize(extension_ref, serializer)
}
ValueRef::Number(number) => number.serialize(serializer),
ValueRef::String(s) => serializer.serialize_str(s),
ValueRef::Array(value_refs) => (*value_refs).serialize(serializer),
ValueRef::Map(items) => {
let mut map = serializer.serialize_map(Some(items.len()))?;
for (k, v) in items.iter() {
map.serialize_entry(k, v)?;
}
map.end()
}
}
}
}
impl<'de> serde::Deserialize<'de> for ValueRef<'de> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
struct ValueVisitor;
impl<'de> Visitor<'de> for ValueVisitor {
type Value = ValueRef<'de>;
fn expecting(&self, formatter: &mut core::fmt::Formatter) -> core::fmt::Result {
formatter.write_str("expect valid messagepack")
}
fn visit_bool<E>(self, v: bool) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
Ok(ValueRef::Bool(v))
}
fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
let n = Number::from(v);
Ok(ValueRef::Number(n))
}
fn visit_i64<E>(self, v: i64) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
let n = Number::from(v);
Ok(ValueRef::Number(n))
}
fn visit_f32<E>(self, v: f32) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
let n = Number::from(v);
Ok(ValueRef::from(n))
}
fn visit_f64<E>(self, v: f64) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
let n = Number::from(v);
Ok(ValueRef::from(n))
}
fn visit_borrowed_str<E>(self, v: &'de str) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
Ok(ValueRef::String(v))
}
fn visit_none<E>(self) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
Ok(ValueRef::Nil)
}
fn visit_unit<E>(self) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
Ok(ValueRef::Nil)
}
fn visit_borrowed_bytes<E>(self, v: &'de [u8]) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
Ok(ValueRef::Bin(v))
}
fn visit_newtype_struct<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
where
D: serde::Deserializer<'de>,
{
let ext = crate::extension::ext_ref::deserialize(deserializer)?;
Ok(ValueRef::Extension(ext))
}
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
where
A: serde::de::SeqAccess<'de>,
{
let mut buf =
Vec::with_capacity(super::cautiously_size_hint::<ValueRef>(seq.size_hint()));
while let Some(v) = seq.next_element::<ValueRef>()? {
buf.push(v);
}
Ok(ValueRef::Array(buf))
}
fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
where
A: serde::de::MapAccess<'de>,
{
let mut buf = Vec::with_capacity(
super::cautiously_size_hint::<(ValueRef, ValueRef)>(map.size_hint()),
);
while let Some(v) = map.next_entry()? {
buf.push(v);
}
Ok(ValueRef::Map(buf))
}
}
deserializer.deserialize_any(ValueVisitor)
}
}
impl From<()> for ValueRef<'_> {
fn from(_: ()) -> Self {
ValueRef::Nil
}
}
impl From<bool> for ValueRef<'_> {
fn from(v: bool) -> Self {
ValueRef::Bool(v)
}
}
impl From<u8> for ValueRef<'_> {
fn from(v: u8) -> Self {
ValueRef::Number(Number::from(v))
}
}
impl From<u16> for ValueRef<'_> {
fn from(v: u16) -> Self {
ValueRef::Number(Number::from(v))
}
}
impl From<u32> for ValueRef<'_> {
fn from(v: u32) -> Self {
ValueRef::Number(Number::from(v))
}
}
impl From<u64> for ValueRef<'_> {
fn from(v: u64) -> Self {
ValueRef::Number(Number::from(v))
}
}
impl From<i8> for ValueRef<'_> {
fn from(v: i8) -> Self {
ValueRef::Number(Number::from(v))
}
}
impl From<i16> for ValueRef<'_> {
fn from(v: i16) -> Self {
ValueRef::Number(Number::from(v))
}
}
impl From<i32> for ValueRef<'_> {
fn from(v: i32) -> Self {
ValueRef::Number(Number::from(v))
}
}
impl From<i64> for ValueRef<'_> {
fn from(v: i64) -> Self {
ValueRef::Number(Number::from(v))
}
}
impl From<f32> for ValueRef<'_> {
fn from(v: f32) -> Self {
ValueRef::Number(Number::from(v))
}
}
impl From<f64> for ValueRef<'_> {
fn from(v: f64) -> Self {
ValueRef::Number(Number::from(v))
}
}
impl From<Number> for ValueRef<'_> {
fn from(v: Number) -> Self {
ValueRef::Number(v)
}
}
impl TryFrom<usize> for ValueRef<'_> {
type Error = core::num::TryFromIntError;
fn try_from(v: usize) -> Result<Self, Self::Error> {
Number::try_from(v).map(Self::from)
}
}
impl TryFrom<isize> for ValueRef<'_> {
type Error = core::num::TryFromIntError;
fn try_from(v: isize) -> Result<Self, Self::Error> {
Number::try_from(v).map(Self::from)
}
}
impl<'a> From<&'a str> for ValueRef<'a> {
fn from(v: &'a str) -> Self {
ValueRef::String(v)
}
}
impl<'a> From<&'a [u8]> for ValueRef<'a> {
fn from(v: &'a [u8]) -> Self {
ValueRef::Bin(v)
}
}
impl<'a> From<ExtensionRef<'a>> for ValueRef<'a> {
fn from(v: ExtensionRef<'a>) -> Self {
ValueRef::Extension(v)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::{from_slice, to_slice};
use messagepack_core::extension::ExtensionRef;
use rstest::rstest;
#[rstest]
#[case(ValueRef::Nil, vec![0xc0])]
#[case(ValueRef::Bool(true), vec![0xc3])]
#[case(ValueRef::Number(Number::PositiveInt(5)), vec![0x05])]
#[case(ValueRef::Number(Number::NegativeInt(-33)), vec![0xd0, 0xdf])]
#[case(ValueRef::Number(Number::Float(1.5)), vec![0xca, 0x3f, 0xc0, 0x00, 0x00])]
#[case(ValueRef::String("a"), vec![0xa1, b'a'])]
#[case(ValueRef::Bin(&[0x01, 0x02]), vec![0xc4, 0x02, 0x01, 0x02])]
#[case(
ValueRef::Array(vec![ValueRef::Bool(true), ValueRef::Nil]),
vec![0x92, 0xc3, 0xc0]
)]
#[case(
ValueRef::Map(vec![
(ValueRef::String("a"), ValueRef::Number(Number::NegativeInt(-1)))
]),
vec![0x81, 0xa1, b'a', 0xff]
)]
fn encode_value_ref_cases(#[case] v: ValueRef<'_>, #[case] expected: Vec<u8>) {
let mut buf = vec![0u8; expected.len() + 8];
let len = to_slice(&v, &mut buf).unwrap();
assert_eq!(buf[..len], expected);
}
#[rstest]
#[case(&[0xc0], ValueRef::Nil)]
#[case(&[0xc3], ValueRef::Bool(true))]
#[case(&[0x05], ValueRef::Number(Number::PositiveInt(5)))]
#[case(&[0xd0, 0xdf], ValueRef::Number(Number::NegativeInt(-33)))]
#[case(&[0xca, 0x3f, 0xc0, 0x00, 0x00], ValueRef::Number(Number::Float(1.5)))]
#[case(&[0xa1, b'a'], ValueRef::String("a"))]
#[case(&[0xc4, 0x02, 0x01, 0x02], ValueRef::Bin(&[0x01, 0x02]))]
#[case(&[0x92, 0xc3, 0xc0], ValueRef::Array(vec![ValueRef::Bool(true), ValueRef::Nil]))]
#[case(
&[0x81, 0xa1, b'a', 0xff],
ValueRef::Map(vec![
(ValueRef::String("a"), ValueRef::Number(Number::NegativeInt(-1)))
])
)]
fn decode_value_ref_cases(#[case] input: &[u8], #[case] expected: ValueRef<'_>) {
let v = from_slice::<ValueRef<'_>>(input).unwrap();
assert_eq!(v, expected);
}
#[test]
fn encode_value_ref_extension_fixext1() {
let kind: i8 = 10;
let v = ValueRef::Extension(ExtensionRef::new(kind, &[0x12]));
let mut buf = [0u8; 3];
let len = to_slice(&v, &mut buf).unwrap();
assert_eq!(len, 3);
assert_eq!(buf, [0xd4, kind as u8, 0x12]);
}
#[test]
fn decode_then_reencode_value_ref_extension_timestamp32_roundtrip() {
let ts32: &[u8] = &[0xd6, 0xff, 0x00, 0x00, 0x00, 0x00];
let v = from_slice::<ValueRef<'_>>(ts32).unwrap();
match v {
ValueRef::Extension(ext) => {
assert_eq!(ext.r#type, -1);
assert_eq!(ext.data, &[0x00, 0x00, 0x00, 0x00]);
let mut buf = [0u8; 6];
let len = to_slice(&ValueRef::Extension(ext), &mut buf).unwrap();
assert_eq!(&buf[..len], ts32);
}
_ => panic!("expected extension"),
}
}
const COMPLEX: &[u8] = &[
0x82, 0xa4, 0x6d, 0x65, 0x74, 0x61, 0x82, 0xa2, 0x69, 0x64, 0xcd, 0x03, 0xe9, 0xa4, 0x74,
0x61, 0x67, 0x73, 0x94, 0xa6, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0xc0, 0x2a, 0x81, 0xa5,
0x65, 0x78, 0x74, 0x72, 0x61, 0xa3, 0x79, 0x65, 0x73, 0xa5, 0x75, 0x73, 0x65, 0x72, 0x73,
0x92, 0x82, 0xa4, 0x6e, 0x61, 0x6d, 0x65, 0xa5, 0x41, 0x6c, 0x69, 0x63, 0x65, 0xaa, 0x61,
0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x82, 0xa3, 0x61, 0x67, 0x65, 0x1d,
0xab, 0x70, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x73, 0x93, 0xa6, 0x63,
0x6f, 0x66, 0x66, 0x65, 0x65, 0xc0, 0x81, 0xa5, 0x6d, 0x75, 0x73, 0x69, 0x63, 0x93, 0xa4,
0x6a, 0x61, 0x7a, 0x7a, 0xa4, 0x72, 0x6f, 0x63, 0x6b, 0x81, 0xa6, 0x67, 0x65, 0x6e, 0x72,
0x65, 0x73, 0x92, 0xa9, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x69, 0x63, 0x61, 0x6c, 0x7b, 0x82,
0xa4, 0x6e, 0x61, 0x6d, 0x65, 0xa3, 0x42, 0x6f, 0x62, 0xaa, 0x61, 0x74, 0x74, 0x72, 0x69,
0x62, 0x75, 0x74, 0x65, 0x73, 0x82, 0xa3, 0x61, 0x67, 0x65, 0xc0, 0xab, 0x70, 0x72, 0x65,
0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x73, 0x92, 0x81, 0xa4, 0x66, 0x6f, 0x6f, 0x64,
0x93, 0xa5, 0x70, 0x69, 0x7a, 0x7a, 0x61, 0xa5, 0x73, 0x75, 0x73, 0x68, 0x69, 0xc0, 0x93,
0xc3, 0xc2, 0x81, 0xa6, 0x6e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x92, 0x00, 0x81, 0xa5, 0x69,
0x6e, 0x6e, 0x65, 0x72, 0xa5, 0x76, 0x61, 0x6c, 0x75, 0x65,
];
#[test]
fn roundtrip_complex() {
let meta = ValueRef::Map(vec![
(ValueRef::String("id"), ValueRef::from(1001)),
(
ValueRef::String("tags"),
ValueRef::Array(vec![
ValueRef::String("sample"),
ValueRef::Nil,
ValueRef::from(42),
ValueRef::Map(vec![(ValueRef::String("extra"), ValueRef::String("yes"))]),
]),
),
]);
let alice = ValueRef::Map(vec![
(ValueRef::String("name"), ValueRef::String("Alice")),
(
ValueRef::String("attributes"),
ValueRef::Map(vec![
(ValueRef::String("age"), ValueRef::from(29)),
(
ValueRef::String("preferences"),
ValueRef::Array(vec![
ValueRef::String("coffee"),
ValueRef::Nil,
ValueRef::Map(vec![(
ValueRef::String("music"),
ValueRef::Array(vec![
ValueRef::String("jazz"),
ValueRef::String("rock"),
ValueRef::Map(vec![(
ValueRef::String("genres"),
ValueRef::Array(vec![
ValueRef::String("classical"),
ValueRef::from(123),
]),
)]),
]),
)]),
]),
),
]),
),
]);
let bob = ValueRef::Map(vec![
(ValueRef::String("name"), ValueRef::String("Bob")),
(
ValueRef::String("attributes"),
ValueRef::Map(vec![
(ValueRef::String("age"), ValueRef::Nil),
(
ValueRef::String("preferences"),
ValueRef::Array(vec![
ValueRef::Map(vec![(
ValueRef::String("food"),
ValueRef::Array(vec![
ValueRef::String("pizza"),
ValueRef::String("sushi"),
ValueRef::Nil,
]),
)]),
ValueRef::Array(vec![
ValueRef::Bool(true),
ValueRef::Bool(false),
ValueRef::Map(vec![(
ValueRef::String("nested"),
ValueRef::Array(vec![
ValueRef::from(0),
ValueRef::Map(vec![(
ValueRef::String("inner"),
ValueRef::String("value"),
)]),
]),
)]),
]),
]),
),
]),
),
]);
let v = ValueRef::Map(vec![
(ValueRef::String("meta"), meta),
(ValueRef::String("users"), ValueRef::Array(vec![alice, bob])),
]);
let deserialized = from_slice::<ValueRef<'_>>(COMPLEX).unwrap();
assert_eq!(deserialized, v);
let mut buf = [0u8; COMPLEX.len()];
let len = to_slice(&v, &mut buf).unwrap();
assert_eq!(len, COMPLEX.len());
assert_eq!(&buf, COMPLEX);
}
}