In Python, when decoding a messagepack message that contains a timestamp, the code in the msgpack library (Timestamp class) is pretty straightforward as it just takes the bytes it finds for a field and converts them as copied from the lib below:
def from_bytes(b):
"""Unpack bytes into a `Timestamp` object.
Used for pure-Python msgpack unpacking.
:param b: Payload from msgpack ext message with code -1
:type b: bytes
:returns: Timestamp object unpacked from msgpack ext payload
:rtype: Timestamp
"""
if len(b) == 4:
seconds = struct.unpack("!L", b)[0]
nanoseconds = 0
elif len(b) == 8:
data64 = struct.unpack("!Q", b)[0]
seconds = data64 & 0x00000003FFFFFFFF
nanoseconds = data64 >> 34
elif len(b) == 12:
nanoseconds, seconds = struct.unpack("!Iq", b)
else:
raise ValueError(
"Timestamp type can only be created from 32, 64, or 96-bit byte objects"
)
return Timestamp(seconds, nanoseconds)
I am massively struggling to achieve the same behavior in Rust. For simplicity's sake, this a simple struct:
#[derive(Debug, PartialEq, Deserialize)]
struct ReceivedMessage {
a_string: String,
a_value: f64,
a_timestamp: ????? // <--- what to put here?
}
When calling rmp_serde::from_slice(&'a [u8])
with the binary messagepack message I get
called
Result::unwrap()
on anErr
value: Syntax("invalid type: newtype struct, expected byte array")
and it just doesn't matter what type I put for a_timestamp
. I tried SystemTime
, i64
, f64
and serde_as
with TimestampSeconds
etc. I then tried using Vec<u8>
and serde_bytes
as well as writing a custom converter with serde::conv!
All to no avail and always the same error message. There doesn't seem to be any comprehensive tutorial online on this. (The other fields in the struct deserialize just fine as I found out when debugging).
If it matters, the binary message comes as a map, i.e. with the field names and not as an array.
It seems to me that this should be easy as Python has all this functionality built-in into the msgpack library. So how can I decode a timestamp in Rust?
I am using the newest crate versions
rmp-serde = "1.1.2"
serde = "1"
serde_derive = "1"
serde_with = "3.4"
serde_bytes = "0.11"
rmp-serde
doesn't have this feature implemented, see #298.There is some code from the issue that appears to follow the Msgpack standard:
However, this seems to only care for precision up to the second.