diff --git a/libs/utils/src/id.rs b/libs/utils/src/id.rs index 2ce92ee914..1b56e6fa79 100644 --- a/libs/utils/src/id.rs +++ b/libs/utils/src/id.rs @@ -244,13 +244,13 @@ id_newtype!(TenantId); /// NOTE: It (de)serializes as an array of hex bytes, so the string representation would look /// like `[173,80,132,115,129,226,72,254,170,201,135,108,199,26,228,24]`. /// See [`Id`] for alternative ways to serialize it. -#[derive(Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, PartialOrd, Ord)] +#[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)] pub struct ConnectionId(Id); id_newtype!(ConnectionId); // A pair uniquely identifying Neon instance. -#[derive(Debug, Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Hash, Serialize, Deserialize)] +#[derive(Debug, Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Hash)] pub struct TenantTimelineId { pub tenant_id: TenantId, pub timeline_id: TimelineId, @@ -273,6 +273,36 @@ impl TenantTimelineId { } } +impl Serialize for TenantTimelineId { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.collect_str(self) + } +} + +impl<'de> Deserialize<'de> for TenantTimelineId { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let str = String::deserialize(deserializer)?; + if let Some((tenant_part, timeline_part)) = str.split_once("/") { + Ok(Self { + tenant_id: TenantId(Id::from_hex(tenant_part).map_err(|e| { + serde::de::Error::custom(format!("Malformed tenant in TenantTimelineId: {e}")) + })?), + timeline_id: TimelineId(Id::from_hex(timeline_part).map_err(|e| { + serde::de::Error::custom(format!("Malformed timeline in TenantTimelineId {e}")) + })?), + }) + } else { + Err(serde::de::Error::custom("Malformed TenantTimelineId")) + } + } +} + impl fmt::Display for TenantTimelineId { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}/{}", self.tenant_id, self.timeline_id)