Skip to content

Commit

Permalink
feat(common): add serde to Timestamp
Browse files Browse the repository at this point in the history
  • Loading branch information
Nuhvi committed Aug 26, 2024
1 parent 620e2ad commit ab7c005
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 0 deletions.
3 changes: 3 additions & 0 deletions pubky-common/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
71 changes: 71 additions & 0 deletions pubky-common/src/timestamp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -173,6 +179,58 @@ pub fn system_time() -> u64 {
* 1000
}

// === Serde ===

impl Serialize for Timestamp {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
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<D>(deserializer: D) -> Result<Self, D::Error>
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<V>(self, mut seq: V) -> Result<Self::Value, V::Error>
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}")]
Expand Down Expand Up @@ -237,4 +295,17 @@ mod tests {

assert_eq!(decoded, timestamp)
}

#[test]
fn serde() {
let timestamp = Timestamp::now();

let serialized = postcard::to_allocvec(&timestamp).unwrap();

assert_eq!(serialized, timestamp.to_bytes());

let deserialized: Timestamp = postcard::from_bytes(&serialized).unwrap();

assert_eq!(deserialized, timestamp);
}
}

0 comments on commit ab7c005

Please sign in to comment.