From ab7c005d670e44e5fb7cce218bc9931394db74d8 Mon Sep 17 00:00:00 2001 From: nazeh Date: Mon, 26 Aug 2024 14:24:37 +0300 Subject: [PATCH] feat(common): add serde to Timestamp --- pubky-common/Cargo.toml | 3 ++ pubky-common/src/timestamp.rs | 71 +++++++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+) diff --git a/pubky-common/Cargo.toml b/pubky-common/Cargo.toml index 0a9df3b..9e539b7 100644 --- a/pubky-common/Cargo.toml +++ b/pubky-common/Cargo.toml @@ -19,3 +19,6 @@ crypto_secretbox = { version = "0.1.1", features = ["std"] } [target.'cfg(target_arch = "wasm32")'.dependencies] js-sys = "0.3.69" + +[dev-dependencies] +postcard = "1.0.8" diff --git a/pubky-common/src/timestamp.rs b/pubky-common/src/timestamp.rs index 4c546d5..4b9accc 100644 --- a/pubky-common/src/timestamp.rs +++ b/pubky-common/src/timestamp.rs @@ -6,6 +6,12 @@ use std::{ sync::Mutex, }; +use serde::{ + de::{SeqAccess, Visitor}, + ser::SerializeTuple, + Deserialize, Deserializer, Serialize, Serializer, +}; + use once_cell::sync::Lazy; use rand::Rng; @@ -173,6 +179,58 @@ pub fn system_time() -> u64 { * 1000 } +// === Serde === + +impl Serialize for Timestamp { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + // Convert u64 to 8 bytes in Big-Endian format + let mut tup = serializer.serialize_tuple(8)?; + + for byte in self.to_bytes() { + tup.serialize_element(&byte)?; + } + + tup.end() + } +} + +impl<'de> Deserialize<'de> for Timestamp { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct TimestampVisitor; + + impl<'de> Visitor<'de> for TimestampVisitor { + type Value = Timestamp; + + fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { + formatter.write_str("a tuple of 8 bytes") + } + + fn visit_seq(self, mut seq: V) -> Result + where + V: SeqAccess<'de>, + { + let mut bytes = [0u8; 8]; + + for i in 0..8 { + bytes[i] = seq + .next_element()? + .ok_or_else(|| serde::de::Error::invalid_length(i, &self))?; + } + + Ok(Timestamp::from(bytes)) + } + } + + deserializer.deserialize_tuple(8, TimestampVisitor) + } +} + #[derive(thiserror::Error, Debug)] pub enum TimestampError { #[error("Invalid bytes length, Timestamp should be encoded as 8 bytes, got {0}")] @@ -237,4 +295,17 @@ mod tests { assert_eq!(decoded, timestamp) } + + #[test] + fn serde() { + let timestamp = Timestamp::now(); + + let serialized = postcard::to_allocvec(×tamp).unwrap(); + + assert_eq!(serialized, timestamp.to_bytes()); + + let deserialized: Timestamp = postcard::from_bytes(&serialized).unwrap(); + + assert_eq!(deserialized, timestamp); + } }