-
Notifications
You must be signed in to change notification settings - Fork 131
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
rmp_serde : Timestamp Question #298
Comments
A while ago @dani-garcia and @vmx used timestamps with rmp. Maybe they can help. I think it would be nice if we could provide wrapper types or functions for |
Yea, if anyone can point to a resource, that would help me (and anyone else who searches for this in the future). If not, no worries, I can work around it. |
Did anyone found an example o.o? |
Ok, so in my case I wanted to get the amount of seconds and following https://github.com/msgpack/msgpack/blob/master/spec.md#timestamp-extension-type got this code working: #[derive(Debug, Serialize, Deserialize)]
struct SomeStruct {
#[serde(
serialize_with = "serialize_mp_date_secs",
deserialize_with = "deserialize_mp_date_secs"
)]
date: u64,
}
#[derive(Debug, Serialize, Deserialize)]
#[serde(rename = "_ExtStruct")]
pub struct ExtStruct((i8, ByteBuf));
fn u32_from_bytebuf(buf: &ByteBuf) -> Result<u32, TryFromSliceError> {
let bytes = buf.as_slice().try_into()?;
Ok(u32::from_be_bytes(bytes))
}
fn u64_from_bytebuf(buf: &ByteBuf) -> Result<u64, TryFromSliceError> {
let bytes = buf.as_slice().try_into()?;
Ok(u64::from_be_bytes(bytes))
}
pub fn serialize_mp_date_secs<S>(secs: &u64, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let data64 = *secs;
let ext = if (secs >> 34) == 0 {
if (data64 & 0xffffffff00000000) == 0 {
// timestamp 32
let data32 = data64 as u32;
ExtStruct((-1, ByteBuf::from(data32.to_be_bytes())))
} else {
// timestamp 64
ExtStruct((-1, ByteBuf::from(data64.to_be_bytes())))
}
} else {
// timestamp 96
let mut bytes = 0u32.to_be_bytes().to_vec();
let mut secs = (data64 as i64).to_be_bytes().to_vec();
bytes.append(&mut secs);
ExtStruct((-1, ByteBuf::from(bytes)))
};
ext.serialize(serializer)
}
pub fn deserialize_mp_date_secs<'de, D>(deserializer: D) -> Result<u64, D::Error>
where
D: Deserializer<'de>,
{
let ExtStruct((ext_type, buf)) = Deserialize::deserialize(deserializer)?;
if ext_type != -1 {
return Err(de::Error::custom("Invalid extension type (!=-1)"));
}
let sec = match buf.len() {
4 => {
let sec = u32_from_bytebuf(&buf).map_err(|e| {
de::Error::custom(format!("Failed to get u32 from bytebuf ({})", e))
})?;
sec as u64
}
8 => {
let data64 = u64_from_bytebuf(&buf).map_err(|e| {
de::Error::custom(format!("Failed to get u64 from bytebuf ({})", e))
})?;
data64 & 0x00000003ffffffff
}
12 => {
u64_from_bytebuf(&buf)
.map_err(|e| de::Error::custom(format!("Failed to get u64 from bytebuf ({})", e)))?
+ 4
}
n => {
return Err(de::Error::custom(format!(
"Invalid data len {n} (valid sizes are 4, 8 and 12)"
)))
}
};
Ok(sec)
} |
Here's some code allowing for nanoseconds as well. To be used in the same way as above. The struct field has to have the Timestamp type.
|
I am starting something in #351 to make dealing with Timestamps a bit easier. |
Hello, I am porting some messagepack code from another language and need to deserialize Msgpack's Timestamp type. Are there any resources on how to do this?
I'm guessing I need to write some kind of custom deserializer for this value through Serde but wanted to make sure there wasn't an easier way first.
The text was updated successfully, but these errors were encountered: