Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding Timestamp decode/encode #351

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 37 additions & 1 deletion rmp-serde/src/decode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use rmp::decode::{self, DecodeStringError, MarkerReadError, NumValueReadError, R
use rmp::Marker;

use crate::config::{BinaryConfig, DefaultConfig, HumanReadableConfig, SerializerConfig};
use crate::MSGPACK_EXT_STRUCT_NAME;
use crate::{MSGPACK_EXT_STRUCT_NAME, MSGPACK_TIMESTAMP_STRUCT_NAME};

/// Enum representing errors that can occur while decoding MessagePack data.
#[derive(Debug)]
Expand Down Expand Up @@ -698,6 +698,11 @@ impl<'de, 'a, R: ReadSlice<'de>, C: SerializerConfig> serde::Deserializer<'de> f
return visitor.visit_newtype_struct(ext_de);
}

if name == MSGPACK_TIMESTAMP_STRUCT_NAME {
let ts_de = TimestampDeserializer::new(&mut self.rd);
return ts_de.deserialize_any(visitor);
}

visitor.visit_newtype_struct(self)
}

Expand Down Expand Up @@ -1191,3 +1196,34 @@ where
let mut de = Deserializer::from_read_ref(rd);
Deserialize::deserialize(&mut de)
}

#[derive(Debug)]
pub(crate) struct TimestampDeserializer<'a, R> {
rd: &'a mut R,
}

impl<'a, R: Read> TimestampDeserializer<'a, R> {
pub(crate) fn new(rd: &'a mut R) -> Self {
Self {
rd,
}
}
}

impl<'de, 'a, R: Read> de::Deserializer<'de> for TimestampDeserializer<'a, R> {
type Error = Error;

fn deserialize_any<V>(mut self, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de> {
let ts = rmp::decode::read_timestamp(&mut self.rd)?;

visitor.visit_u128(ts.into_u128())
}

forward_to_deserialize_any! {
bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string unit option
seq bytes byte_buf map unit_struct newtype_struct
struct identifier tuple enum ignored_any tuple_struct
}
}
192 changes: 191 additions & 1 deletion rmp-serde/src/encode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use rmp::{encode, Marker};
use crate::config::{
BinaryConfig, DefaultConfig, HumanReadableConfig, RuntimeConfig, SerializerConfig, StructMapConfig, StructTupleConfig
};
use crate::MSGPACK_EXT_STRUCT_NAME;
use crate::{MSGPACK_EXT_STRUCT_NAME, MSGPACK_TIMESTAMP_STRUCT_NAME};

/// This type represents all possible errors that can occur when serializing or
/// deserializing MessagePack data.
Expand Down Expand Up @@ -685,6 +685,13 @@ where
return ext_se.end();
}

if name == MSGPACK_TIMESTAMP_STRUCT_NAME {
let mut ts_se = TimestampSerializer::new(&mut self.wr);
value.serialize(&mut ts_se)?;

return Ok(());
}

// Encode as if it's inner type.
value.serialize(self)
}
Expand Down Expand Up @@ -1269,3 +1276,186 @@ impl Write for FallibleWriter {
Ok(())
}
}

struct TimestampSerializer<'a, W> {
wr: &'a mut W
}

impl<'a, W: Write> TimestampSerializer<'a, W> {
fn new(wr: &'a mut W) -> Self {
Self { wr }
}
}

impl<'a, W: Write> serde::Serializer for &'a mut TimestampSerializer<'a, W> {
type Ok = ();

type Error = Error;

type SerializeSeq = serde::ser::Impossible<(), Error>;
type SerializeTuple = serde::ser::Impossible<(), Error>;
type SerializeTupleStruct = serde::ser::Impossible<(), Error>;
type SerializeTupleVariant = serde::ser::Impossible<(), Error>;
type SerializeMap = serde::ser::Impossible<(), Error>;
type SerializeStruct = serde::ser::Impossible<(), Error>;
type SerializeStructVariant = serde::ser::Impossible<(), Error>;

fn serialize_u128(self, v: u128) -> Result<Self::Ok, Self::Error> {
let ts = rmp::Timestamp::from_u128(v).ok_or_else(|| Error::Syntax(format!("Not a valid Timestamp")))?;
rmp::encode::write_timestamp(self.wr, ts).map_err(|_| Error::Syntax(format!("Not a valid Timestamp")))?;
Ok(())
}

fn serialize_bool(self, _v: bool) -> Result<Self::Ok, Self::Error> {
Err(Error::InvalidDataModel("expected u128"))
}

fn serialize_i8(self, _v: i8) -> Result<Self::Ok, Self::Error> {
Err(Error::InvalidDataModel("expected u128"))
}

fn serialize_i16(self, _v: i16) -> Result<Self::Ok, Self::Error> {
Err(Error::InvalidDataModel("expected u128"))
}

fn serialize_i32(self, _v: i32) -> Result<Self::Ok, Self::Error> {
Err(Error::InvalidDataModel("expected u128"))
}

fn serialize_i64(self, _v: i64) -> Result<Self::Ok, Self::Error> {
Err(Error::InvalidDataModel("expected u128"))
}

fn serialize_u8(self, _v: u8) -> Result<Self::Ok, Self::Error> {
Err(Error::InvalidDataModel("expected u128"))
}

fn serialize_u16(self, _v: u16) -> Result<Self::Ok, Self::Error> {
Err(Error::InvalidDataModel("expected u128"))
}

fn serialize_u32(self, _v: u32) -> Result<Self::Ok, Self::Error> {
Err(Error::InvalidDataModel("expected u128"))
}

fn serialize_u64(self, _v: u64) -> Result<Self::Ok, Self::Error> {
Err(Error::InvalidDataModel("expected u128"))
}

fn serialize_f32(self, _v: f32) -> Result<Self::Ok, Self::Error> {
Err(Error::InvalidDataModel("expected u128"))
}

fn serialize_f64(self, _v: f64) -> Result<Self::Ok, Self::Error> {
Err(Error::InvalidDataModel("expected u128"))
}

fn serialize_char(self, _v: char) -> Result<Self::Ok, Self::Error> {
Err(Error::InvalidDataModel("expected u128"))
}

fn serialize_str(self, _v: &str) -> Result<Self::Ok, Self::Error> {
Err(Error::InvalidDataModel("expected u128"))
}

fn serialize_bytes(self, _v: &[u8]) -> Result<Self::Ok, Self::Error> {
Err(Error::InvalidDataModel("expected u128"))
}

fn serialize_none(self) -> Result<Self::Ok, Self::Error> {
Err(Error::InvalidDataModel("expected u128"))
}

fn serialize_some<T>(self, _value: &T) -> Result<Self::Ok, Self::Error>
where
T: ?Sized + Serialize {
Err(Error::InvalidDataModel("expected u128"))
}

fn serialize_unit(self) -> Result<Self::Ok, Self::Error> {
Err(Error::InvalidDataModel("expected u128"))
}

fn serialize_unit_struct(self, _name: &'static str) -> Result<Self::Ok, Self::Error> {
Err(Error::InvalidDataModel("expected u128"))
}

fn serialize_unit_variant(
self,
_name: &'static str,
_variant_index: u32,
_variant: &'static str,
) -> Result<Self::Ok, Self::Error> {
Err(Error::InvalidDataModel("expected u128"))
}

fn serialize_newtype_struct<T>(
self,
_name: &'static str,
_value: &T,
) -> Result<Self::Ok, Self::Error>
where
T: ?Sized + Serialize {
Err(Error::InvalidDataModel("expected u128"))
}

fn serialize_newtype_variant<T>(
self,
_name: &'static str,
_variant_index: u32,
_variant: &'static str,
_value: &T,
) -> Result<Self::Ok, Self::Error>
where
T: ?Sized + Serialize {
Err(Error::InvalidDataModel("expected u128"))
}

fn serialize_seq(self, _len: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> {
Err(Error::InvalidDataModel("expected u128"))
}

fn serialize_tuple(self, _len: usize) -> Result<Self::SerializeTuple, Self::Error> {
Err(Error::InvalidDataModel("expected u128"))
}

fn serialize_tuple_struct(
self,
_name: &'static str,
_len: usize,
) -> Result<Self::SerializeTupleStruct, Self::Error> {
Err(Error::InvalidDataModel("expected u128"))
}

fn serialize_tuple_variant(
self,
_name: &'static str,
_variant_index: u32,
_variant: &'static str,
_len: usize,
) -> Result<Self::SerializeTupleVariant, Self::Error> {
Err(Error::InvalidDataModel("expected u128"))
}

fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap, Self::Error> {
Err(Error::InvalidDataModel("expected u128"))
}

fn serialize_struct(
self,
_name: &'static str,
_len: usize,
) -> Result<Self::SerializeStruct, Self::Error> {
Err(Error::InvalidDataModel("expected u128"))
}

fn serialize_struct_variant(
self,
_name: &'static str,
_variant_index: u32,
_variant: &'static str,
_len: usize,
) -> Result<Self::SerializeStructVariant, Self::Error> {
Err(Error::InvalidDataModel("expected u128"))
}
}
48 changes: 48 additions & 0 deletions rmp-serde/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ pub mod encode;
/// Value::Ext(2, vec![5]));
/// ```
pub const MSGPACK_EXT_STRUCT_NAME: &str = "_ExtStruct";
pub(crate) const MSGPACK_TIMESTAMP_STRUCT_NAME: &str = "_TimestampForInternalUseOnly";

/// Helper that allows both to encode and decode strings no matter whether they contain valid or
/// invalid UTF-8.
Expand Down Expand Up @@ -335,3 +336,50 @@ impl<'de> Deserialize<'de> for RawRef<'de> {
de.deserialize_any(RawRefVisitor)
}
}

/// This is a wrapper for `rmp::Timestamp` which is only used for serde.
///
/// This maps to the serde data model as follows:
///
/// `struct _TimestampForInternalUseOnly(u128);`
///
/// This will encode enough information for the Serializer and Deserializer
/// to properly manage the data to and from the msgpack format.
///
/// This wrapper should ONLY be used with the msgpack Serializer and Deserializer
/// from this library.
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct TimestampSerde(pub rmp::Timestamp);

impl Serialize for TimestampSerde {
fn serialize<S>(&self, se: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
se.serialize_newtype_struct(MSGPACK_TIMESTAMP_STRUCT_NAME, &self.0.into_u128())
}
}

impl<'de> Deserialize<'de> for TimestampSerde {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: de::Deserializer<'de>,
{
struct TimestampVisitor;

impl de::Visitor<'_> for TimestampVisitor {
type Value = TimestampSerde;

fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("A valid TimestampSerde")
}

fn visit_u128<E>(self, v: u128) -> Result<Self::Value, E>
where
E: de::Error, {
Ok(TimestampSerde(rmp::Timestamp::from_u128(v).ok_or_else(|| de::Error::custom("invalid TimestampSerde"))?))
}
}
deserializer.deserialize_newtype_struct(MSGPACK_TIMESTAMP_STRUCT_NAME, TimestampVisitor)
}
}
38 changes: 37 additions & 1 deletion rmp-serde/tests/decode_derive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::io::Cursor;
use serde::Deserialize;

use rmp_serde::decode::Error;
use rmp_serde::Deserializer;
use rmp_serde::{Deserializer, TimestampSerde};

#[test]
fn pass_newtype() {
Expand Down Expand Up @@ -66,6 +66,42 @@ fn pass_struct() {
assert_eq!(Decoded { id: 42, value: 100500 }, actual);
}

#[test]
fn pass_timestamp() {
#[derive(Debug, PartialEq, Deserialize)]
struct Decoded {
id: u32,
value: u32,
ts: TimestampSerde,
}

let vals = [
(Decoded {
id: 42,
value: 100500,
ts: TimestampSerde(rmp::Timestamp::from_32(9))
}, vec![0x93, 0x2a, 0xce, 0x0, 0x1, 0x88, 0x94, 0xd6, 0xff, 0x0, 0x0, 0x0, 0x9]),
(Decoded {
id: 42,
value: 100500,
ts: TimestampSerde(rmp::Timestamp::from_64(9, 1).unwrap())
}, vec![0x93, 0x2a, 0xce, 0x0, 0x1, 0x88, 0x94, 0xd7, 0xff, 0x0, 0x0, 0x0, 0x4, 0x0, 0x0, 0x0, 0x9]),
(Decoded {
id: 42,
value: 100500,
ts: TimestampSerde(rmp::Timestamp::from_96(9, 1).unwrap())
}, vec![0x93, 0x2a, 0xce, 0x0, 0x1, 0x88, 0x94, 0xc7, 0xc, 0xff, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x9]),
];

for (val, raw) in vals {
let cur = Cursor::new(&raw[..]);
let mut de = Deserializer::new(cur);
let actual: Decoded = Deserialize::deserialize(&mut de).unwrap();

assert_eq!(val, actual);
}
}

#[test]
fn pass_struct_from_map() {
#[derive(Debug, PartialEq, Deserialize)]
Expand Down
Loading