@@ -28,14 +28,14 @@ use ruma::{
28
28
assign,
29
29
events:: {
30
30
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 ,
34
33
} ,
35
34
serde:: { from_raw_json_value, Raw } ,
36
35
to_device:: DeviceIdOrAllDevices ,
37
- EventId , OwnedUserId , RoomId , TransactionId ,
36
+ EventId , OwnedRoomId , OwnedUserId , TransactionId ,
38
37
} ;
38
+ use serde:: { Deserialize , Serialize } ;
39
39
use serde_json:: { value:: RawValue as RawJsonValue , Value } ;
40
40
use tokio:: sync:: mpsc:: { unbounded_channel, UnboundedReceiver } ;
41
41
use tracing:: error;
@@ -89,11 +89,14 @@ impl MatrixDriver {
89
89
) -> Result < Vec < Raw < AnyTimelineEvent > > > {
90
90
let room_id = self . room . room_id ( ) ;
91
91
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
+ }
97
100
RawAnySyncOrStrippedState :: Stripped ( _) => {
98
101
error ! ( "MatrixDriver can't operate in invited rooms" ) ;
99
102
None
@@ -197,9 +200,9 @@ impl MatrixDriver {
197
200
let _room_id = room_id. clone ( ) ;
198
201
let handle_msg_like =
199
202
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 ) {
201
204
Ok ( event_with_room_id) => {
202
- let _ = _tx. send ( event_with_room_id) ;
205
+ let _ = _tx. send ( event_with_room_id. cast ( ) ) ;
203
206
}
204
207
Err ( e) => {
205
208
error ! ( "Failed to attach room id to message like event: {}" , e) ;
@@ -212,9 +215,9 @@ impl MatrixDriver {
212
215
let _tx = tx;
213
216
// Get only all state events from the state section of the sync.
214
217
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 ) {
216
219
Ok ( event_with_room_id) => {
217
- let _ = _tx. send ( event_with_room_id) ;
220
+ let _ = _tx. send ( event_with_room_id. cast ( ) ) ;
218
221
}
219
222
Err ( e) => {
220
223
error ! ( "Failed to attach room id to state event: {}" , e) ;
@@ -240,7 +243,7 @@ impl MatrixDriver {
240
243
241
244
let to_device_handle = self . room . client ( ) . add_event_handler (
242
245
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 ( ) ) {
244
247
Ok ( ev) => {
245
248
let _ = tx. send ( ev) ;
246
249
}
@@ -296,35 +299,40 @@ impl<T> EventReceiver<T> {
296
299
}
297
300
}
298
301
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 ,
317
315
}
318
316
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 ( ) )
328
336
}
329
337
Err ( e) => Err ( Error :: from ( e) ) ,
330
338
}
0 commit comments