From 48a767d52c3d24c6a460a6defdddaa9c7c707387 Mon Sep 17 00:00:00 2001 From: Jason Volk Date: Thu, 3 Oct 2024 01:01:25 +0000 Subject: [PATCH] abstract common patterns as core pdu memberfns Signed-off-by: Jason Volk --- src/core/pdu/mod.rs | 67 ++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 60 insertions(+), 7 deletions(-) diff --git a/src/core/pdu/mod.rs b/src/core/pdu/mod.rs index cf9ffe64..a94e2bdc 100644 --- a/src/core/pdu/mod.rs +++ b/src/core/pdu/mod.rs @@ -18,11 +18,11 @@ use ruma::{ use serde::{Deserialize, Serialize}; use serde_json::{ json, - value::{to_raw_value, RawValue as RawJsonValue}, + value::{to_raw_value, RawValue as RawJsonValue, Value as JsonValue}, }; pub use self::{builder::PduBuilder, count::PduCount}; -use crate::{err, warn, Error, Result}; +use crate::{err, is_true, warn, Error, Result}; #[derive(Deserialize)] struct ExtractRedactedBecause { @@ -58,8 +58,8 @@ pub struct PduEvent { pub unsigned: Option>, pub hashes: EventHash, #[serde(default, skip_serializing_if = "Option::is_none")] - pub signatures: Option>, /* BTreeMap, BTreeMap> */ + // BTreeMap, BTreeMap> + pub signatures: Option>, } impl PduEvent { @@ -170,6 +170,54 @@ impl PduEvent { (self.redacts.clone(), self.content.clone()) } + #[must_use] + pub fn get_content_as_value(&self) -> JsonValue { + self.get_content() + .expect("pdu content must be a valid JSON value") + } + + pub fn get_content(&self) -> Result + where + T: for<'de> Deserialize<'de>, + { + serde_json::from_str(self.content.get()) + .map_err(|e| err!(Database("Failed to deserialize pdu content into type: {e}"))) + } + + pub fn contains_unsigned_property(&self, property: &str, is_type: F) -> bool + where + F: FnOnce(&JsonValue) -> bool, + { + self.get_unsigned_as_value() + .get(property) + .map(is_type) + .is_some_and(is_true!()) + } + + pub fn get_unsigned_property(&self, property: &str) -> Result + where + T: for<'de> Deserialize<'de>, + { + self.get_unsigned_as_value() + .get_mut(property) + .map(JsonValue::take) + .map(serde_json::from_value) + .ok_or(err!(Request(NotFound("property not found in unsigned object"))))? + .map_err(|e| err!(Database("Failed to deserialize unsigned.{property} into type: {e}"))) + } + + #[must_use] + pub fn get_unsigned_as_value(&self) -> JsonValue { self.get_unsigned::().unwrap_or_default() } + + pub fn get_unsigned(&self) -> Result { + self.unsigned + .as_ref() + .map(|raw| raw.get()) + .map(serde_json::from_str) + .ok_or(err!(Request(NotFound("\"unsigned\" property not found in pdu"))))? + .map_err(|e| err!(Database("Failed to deserialize \"unsigned\" into value: {e}"))) + } + #[tracing::instrument(skip(self), level = "debug")] pub fn to_sync_room_event(&self) -> Raw { let (redacts, content) = self.copy_redacts(); @@ -270,8 +318,8 @@ impl PduEvent { serde_json::from_value(json).expect("Raw::from_value always works") } - #[tracing::instrument(skip(self), level = "debug")] - pub fn to_state_event(&self) -> Raw { + #[must_use] + pub fn to_state_event_value(&self) -> JsonValue { let mut json = json!({ "content": self.content, "type": self.kind, @@ -286,7 +334,12 @@ impl PduEvent { json["unsigned"] = json!(unsigned); } - serde_json::from_value(json).expect("Raw::from_value always works") + json + } + + #[tracing::instrument(skip(self), level = "debug")] + pub fn to_state_event(&self) -> Raw { + serde_json::from_value(self.to_state_event_value()).expect("Raw::from_value always works") } #[tracing::instrument(skip(self), level = "debug")]