Skip to content

Commit 4fba759

Browse files
committed
fixup use custom type to serialize with references
1 parent bb14445 commit 4fba759

File tree

3 files changed

+56
-49
lines changed

3 files changed

+56
-49
lines changed

crates/matrix-sdk/src/widget/capabilities.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -288,9 +288,8 @@ impl<'de> Deserialize<'de> for Capabilities {
288288
mod tests {
289289
use ruma::events::StateEventType;
290290

291-
use crate::widget::filter::ToDeviceEventFilter;
292-
293291
use super::*;
292+
use crate::widget::filter::ToDeviceEventFilter;
294293

295294
#[test]
296295
fn deserialization_of_no_capabilities() {

crates/matrix-sdk/src/widget/filter.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -228,8 +228,8 @@ impl<'a> TryFrom<&'a Raw<AnyTimelineEvent>> for FilterInput<'a> {
228228
type Error = serde_json::Error;
229229

230230
fn try_from(raw_event: &'a Raw<AnyTimelineEvent>) -> Result<Self, Self::Error> {
231-
// FilterInput first checks if it can deserialize as a state event (state_key exists)
232-
// and then as a message like event.
231+
// FilterInput first checks if it can deserialize as a state event (state_key
232+
// exists) and then as a message like event.
233233
raw_event.deserialize_as()
234234
}
235235
}
@@ -244,9 +244,9 @@ pub struct FilterInputToDevice<'a> {
244244
impl<'a> TryFrom<&'a Raw<AnyToDeviceEvent>> for FilterInput<'a> {
245245
type Error = serde_json::Error;
246246
fn try_from(raw_event: &'a Raw<AnyToDeviceEvent>) -> Result<Self, Self::Error> {
247-
// deserialize_as::<FilterInput> will first try state, message like and then to-device.
248-
// The `AnyToDeviceEvent` would match message like first, so we need to explicitly
249-
// deserialize as `FilterInputToDevice`.
247+
// deserialize_as::<FilterInput> will first try state, message like and then
248+
// to-device. The `AnyToDeviceEvent` would match message like first, so
249+
// we need to explicitly deserialize as `FilterInputToDevice`.
250250
raw_event.deserialize_as::<FilterInputToDevice<'a>>().map(FilterInput::ToDevice)
251251
}
252252
}
@@ -515,7 +515,7 @@ mod tests {
515515
fn test_to_device_filter_does_match() {
516516
let f = Filter::ToDevice(ToDeviceEventFilter::new("my.custom.to.device".into()));
517517
assert!(f.matches(&FilterInput::ToDevice(FilterInputToDevice {
518-
event_type: "my.custom.to.device".into(),
518+
event_type: "my.custom.to.device",
519519
})));
520520
}
521521
}

crates/matrix-sdk/src/widget/matrix.rs

Lines changed: 49 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,14 @@ use ruma::{
2828
assign,
2929
events::{
3030
AnyMessageLikeEventContent, AnyStateEventContent, AnySyncMessageLikeEvent,
31-
AnySyncStateEvent, AnySyncTimelineEvent, AnyTimelineEvent, AnyToDeviceEvent,
32-
AnyToDeviceEventContent, MessageLikeEventType, StateEventType, TimelineEventType,
33-
ToDeviceEventType,
31+
AnySyncStateEvent, AnyTimelineEvent, AnyToDeviceEvent, AnyToDeviceEventContent,
32+
MessageLikeEventType, StateEventType, TimelineEventType, ToDeviceEventType,
3433
},
3534
serde::{from_raw_json_value, Raw},
3635
to_device::DeviceIdOrAllDevices,
37-
EventId, OwnedUserId, RoomId, TransactionId,
36+
EventId, OwnedRoomId, OwnedUserId, TransactionId,
3837
};
38+
use serde::{Deserialize, Serialize};
3939
use serde_json::{value::RawValue as RawJsonValue, Value};
4040
use tokio::sync::mpsc::{unbounded_channel, UnboundedReceiver};
4141
use tracing::error;
@@ -89,11 +89,14 @@ impl MatrixDriver {
8989
) -> Result<Vec<Raw<AnyTimelineEvent>>> {
9090
let room_id = self.room.room_id();
9191
let convert = |sync_or_stripped_state| match sync_or_stripped_state {
92-
RawAnySyncOrStrippedState::Sync(ev) => with_attached_room_id(ev.cast_ref(), room_id)
93-
.map_err(|e| {
94-
error!("failed to convert event from `get_state_event` response:{}", e)
95-
})
96-
.ok(),
92+
RawAnySyncOrStrippedState::Sync(ev) => {
93+
add_props_to_raw(&ev, Some(room_id.to_owned()), None)
94+
.map(Raw::cast)
95+
.map_err(|e| {
96+
error!("failed to convert event from `get_state_event` response:{}", e)
97+
})
98+
.ok()
99+
}
97100
RawAnySyncOrStrippedState::Stripped(_) => {
98101
error!("MatrixDriver can't operate in invited rooms");
99102
None
@@ -197,9 +200,9 @@ impl MatrixDriver {
197200
let _room_id = room_id.clone();
198201
let handle_msg_like =
199202
self.room.add_event_handler(move |raw: Raw<AnySyncMessageLikeEvent>| {
200-
match with_attached_room_id(raw.cast_ref(), &_room_id) {
203+
match add_props_to_raw(&raw, Some(_room_id), None) {
201204
Ok(event_with_room_id) => {
202-
let _ = _tx.send(event_with_room_id);
205+
let _ = _tx.send(event_with_room_id.cast());
203206
}
204207
Err(e) => {
205208
error!("Failed to attach room id to message like event: {}", e);
@@ -212,9 +215,9 @@ impl MatrixDriver {
212215
let _tx = tx;
213216
// Get only all state events from the state section of the sync.
214217
let handle_state = self.room.add_event_handler(move |raw: Raw<AnySyncStateEvent>| {
215-
match with_attached_room_id(raw.cast_ref(), &_room_id) {
218+
match add_props_to_raw(&raw, Some(_room_id.to_owned()), None) {
216219
Ok(event_with_room_id) => {
217-
let _ = _tx.send(event_with_room_id);
220+
let _ = _tx.send(event_with_room_id.cast());
218221
}
219222
Err(e) => {
220223
error!("Failed to attach room id to state event: {}", e);
@@ -240,7 +243,7 @@ impl MatrixDriver {
240243

241244
let to_device_handle = self.room.client().add_event_handler(
242245
move |raw: Raw<AnyToDeviceEvent>, encryption_info: Option<EncryptionInfo>| {
243-
match with_attached_encryption_flag(raw, &encryption_info) {
246+
match add_props_to_raw(&raw, None, encryption_info.as_ref()) {
244247
Ok(ev) => {
245248
let _ = tx.send(ev);
246249
}
@@ -296,35 +299,40 @@ impl<T> EventReceiver<T> {
296299
}
297300
}
298301

299-
/// Attach a room id to the event. This is needed because the widget API
300-
/// requires the room id to be present in the event.
301-
302-
fn with_attached_room_id(
303-
raw: &Raw<AnySyncTimelineEvent>,
304-
room_id: &RoomId,
305-
) -> Result<Raw<AnyTimelineEvent>> {
306-
// This is the only modification we need to do to the events otherwise they are
307-
// just forwarded raw to the widget.
308-
// This is why we do the serialization dance here to allow the optimization of
309-
// using `BTreeMap<String, Box<RawJsonValue>` instead of serializing the full event.
310-
match raw.deserialize_as::<BTreeMap<String, Box<RawJsonValue>>>() {
311-
Ok(mut ev_mut) => {
312-
ev_mut.insert("room_id".to_owned(), serde_json::value::to_raw_value(room_id)?);
313-
Ok(Raw::new(&ev_mut)?.cast())
314-
}
315-
Err(e) => Err(Error::from(e)),
316-
}
302+
// `room_id` and `encryption` is the only modification we need to do to the
303+
// events otherwise they are just forwarded raw to the widget.
304+
// This is why we do not serialization the whole event but pass it as a raw
305+
// value through the widget driver and only serialize here to allow potimizing
306+
// with `serde(borrow)`.
307+
#[derive(Deserialize, Serialize)]
308+
struct RoomIdEncryptionSerializer<'a> {
309+
#[serde(skip_serializing_if = "Option::is_none")]
310+
room_id: Option<OwnedRoomId>,
311+
#[serde(skip_serializing_if = "Option::is_none")]
312+
encrypted: Option<bool>,
313+
#[serde(flatten, borrow)]
314+
rest: &'a RawJsonValue,
317315
}
318316

319-
fn with_attached_encryption_flag(
320-
raw: Raw<AnyToDeviceEvent>,
321-
encryption_info: &Option<EncryptionInfo>,
322-
) -> Result<Raw<AnyToDeviceEvent>> {
323-
match raw.deserialize_as::<BTreeMap<String, Box<RawJsonValue>>>() {
324-
Ok(mut ev_mut) => {
325-
let encrypted = encryption_info.is_some();
326-
ev_mut.insert("encrypted".to_owned(), serde_json::value::to_raw_value(&encrypted)?);
327-
Ok(Raw::new(&ev_mut)?.cast())
317+
/// Attach additional properties to the event.
318+
///
319+
/// Attach a room id to the event. This is needed because the widget API
320+
/// requires the room id to be present in the event.
321+
///
322+
/// Attach the `ecryption` flag to the event. This is needed so the widget gets
323+
/// informed if an event is encrypted or not. Since the client is responsible
324+
/// for decrypting the event, there otherwise is no way for the widget to know
325+
/// if its an encrypted (signed/trusted) event or not.
326+
fn add_props_to_raw<T>(
327+
raw: &Raw<T>,
328+
room_id: Option<OwnedRoomId>,
329+
encryption_info: Option<&EncryptionInfo>,
330+
) -> Result<Raw<T>> {
331+
match raw.deserialize_as::<RoomIdEncryptionSerializer<'_>>() {
332+
Ok(mut event) => {
333+
event.room_id = room_id.or(event.room_id);
334+
event.encrypted = encryption_info.map(|_| true).or(event.encrypted);
335+
Ok(Raw::new(&event)?.cast())
328336
}
329337
Err(e) => Err(Error::from(e)),
330338
}

0 commit comments

Comments
 (0)