1use std::collections::BTreeMap;
16
17use as_variant::as_variant;
18use ruma::{
19 events::{
20 key::verification::{
21 accept::{
22 AcceptMethod, KeyVerificationAcceptEventContent,
23 ToDeviceKeyVerificationAcceptEventContent,
24 },
25 cancel::{
26 CancelCode, KeyVerificationCancelEventContent,
27 ToDeviceKeyVerificationCancelEventContent,
28 },
29 done::{KeyVerificationDoneEventContent, ToDeviceKeyVerificationDoneEventContent},
30 key::{KeyVerificationKeyEventContent, ToDeviceKeyVerificationKeyEventContent},
31 mac::{KeyVerificationMacEventContent, ToDeviceKeyVerificationMacEventContent},
32 ready::{KeyVerificationReadyEventContent, ToDeviceKeyVerificationReadyEventContent},
33 request::ToDeviceKeyVerificationRequestEventContent,
34 start::{
35 KeyVerificationStartEventContent, StartMethod,
36 ToDeviceKeyVerificationStartEventContent,
37 },
38 VerificationMethod,
39 },
40 room::message::{KeyVerificationRequestEventContent, MessageType},
41 AnyMessageLikeEvent, AnyMessageLikeEventContent, AnyToDeviceEventContent, MessageLikeEvent,
42 },
43 serde::Base64,
44 CanonicalJsonValue, DeviceId, MilliSecondsSinceUnixEpoch, OwnedRoomId, UserId,
45};
46
47use super::FlowId;
48
49#[derive(Debug)]
50pub enum AnyEvent<'a> {
51 Room(&'a AnyMessageLikeEvent),
52 ToDevice(&'a ToDeviceEvents),
53}
54
55impl AnyEvent<'_> {
56 pub fn event_type(&self) -> String {
57 match self {
58 Self::Room(e) => e.event_type().to_string(),
59 Self::ToDevice(e) => e.event_type().to_string(),
60 }
61 }
62
63 pub fn sender(&self) -> &UserId {
64 match self {
65 Self::Room(e) => e.sender(),
66 Self::ToDevice(e) => e.sender(),
67 }
68 }
69
70 pub fn timestamp(&self) -> Option<MilliSecondsSinceUnixEpoch> {
71 match self {
72 AnyEvent::Room(e) => Some(e.origin_server_ts()),
73 AnyEvent::ToDevice(e) => {
74 as_variant!(e, ToDeviceEvents::KeyVerificationRequest(e) => e.content.timestamp)
75 }
76 }
77 }
78
79 pub fn is_room_event(&self) -> bool {
80 matches!(self, AnyEvent::Room(_))
81 }
82
83 pub fn verification_content(&self) -> Option<AnyVerificationContent<'_>> {
84 match self {
85 AnyEvent::Room(e) => match e {
86 AnyMessageLikeEvent::RoomMessage(MessageLikeEvent::Original(m)) => {
87 as_variant!(&m.content.msgtype, MessageType::VerificationRequest)
88 .map(|v| RequestContent::from(v).into())
89 }
90 AnyMessageLikeEvent::KeyVerificationReady(MessageLikeEvent::Original(e)) => {
91 Some(ReadyContent::from(&e.content).into())
92 }
93 AnyMessageLikeEvent::KeyVerificationStart(MessageLikeEvent::Original(e)) => {
94 Some(StartContent::from(&e.content).into())
95 }
96 AnyMessageLikeEvent::KeyVerificationCancel(MessageLikeEvent::Original(e)) => {
97 Some(CancelContent::from(&e.content).into())
98 }
99 AnyMessageLikeEvent::KeyVerificationAccept(MessageLikeEvent::Original(e)) => {
100 Some(AcceptContent::from(&e.content).into())
101 }
102 AnyMessageLikeEvent::KeyVerificationKey(MessageLikeEvent::Original(e)) => {
103 Some(KeyContent::from(&e.content).into())
104 }
105 AnyMessageLikeEvent::KeyVerificationMac(MessageLikeEvent::Original(e)) => {
106 Some(MacContent::from(&e.content).into())
107 }
108 AnyMessageLikeEvent::KeyVerificationDone(MessageLikeEvent::Original(e)) => {
109 Some(DoneContent::from(&e.content).into())
110 }
111 _ => None,
112 },
113 AnyEvent::ToDevice(e) => match e {
114 ToDeviceEvents::KeyVerificationRequest(e) => {
115 Some(RequestContent::from(&e.content).into())
116 }
117 ToDeviceEvents::KeyVerificationReady(e) => {
118 Some(ReadyContent::from(&e.content).into())
119 }
120 ToDeviceEvents::KeyVerificationStart(e) => {
121 Some(StartContent::from(&e.content).into())
122 }
123 ToDeviceEvents::KeyVerificationCancel(e) => {
124 Some(CancelContent::from(&e.content).into())
125 }
126 ToDeviceEvents::KeyVerificationAccept(e) => {
127 Some(AcceptContent::from(&e.content).into())
128 }
129 ToDeviceEvents::KeyVerificationKey(e) => Some(KeyContent::from(&e.content).into()),
130 ToDeviceEvents::KeyVerificationMac(e) => Some(MacContent::from(&e.content).into()),
131 ToDeviceEvents::KeyVerificationDone(e) => {
132 Some(DoneContent::from(&e.content).into())
133 }
134 _ => None,
135 },
136 }
137 }
138}
139
140impl<'a> From<&'a AnyMessageLikeEvent> for AnyEvent<'a> {
141 fn from(e: &'a AnyMessageLikeEvent) -> Self {
142 Self::Room(e)
143 }
144}
145
146impl<'a> From<&'a ToDeviceEvents> for AnyEvent<'a> {
147 fn from(e: &'a ToDeviceEvents) -> Self {
148 Self::ToDevice(e)
149 }
150}
151
152impl TryFrom<&AnyEvent<'_>> for FlowId {
153 type Error = ();
154
155 fn try_from(value: &AnyEvent<'_>) -> Result<Self, Self::Error> {
156 match value {
157 AnyEvent::Room(e) => FlowId::try_from(*e),
158 AnyEvent::ToDevice(e) => FlowId::try_from(*e),
159 }
160 }
161}
162
163impl TryFrom<&AnyMessageLikeEvent> for FlowId {
164 type Error = ();
165
166 fn try_from(value: &AnyMessageLikeEvent) -> Result<Self, Self::Error> {
167 match value {
168 AnyMessageLikeEvent::KeyVerificationReady(MessageLikeEvent::Original(e)) => {
169 Ok(FlowId::from((&*e.room_id, &*e.content.relates_to.event_id)))
170 }
171 AnyMessageLikeEvent::RoomMessage(MessageLikeEvent::Original(e)) => {
172 Ok(FlowId::from((&*e.room_id, &*e.event_id)))
173 }
174 AnyMessageLikeEvent::KeyVerificationStart(MessageLikeEvent::Original(e)) => {
175 Ok(FlowId::from((&*e.room_id, &*e.content.relates_to.event_id)))
176 }
177 AnyMessageLikeEvent::KeyVerificationCancel(MessageLikeEvent::Original(e)) => {
178 Ok(FlowId::from((&*e.room_id, &*e.content.relates_to.event_id)))
179 }
180 AnyMessageLikeEvent::KeyVerificationAccept(MessageLikeEvent::Original(e)) => {
181 Ok(FlowId::from((&*e.room_id, &*e.content.relates_to.event_id)))
182 }
183 AnyMessageLikeEvent::KeyVerificationKey(MessageLikeEvent::Original(e)) => {
184 Ok(FlowId::from((&*e.room_id, &*e.content.relates_to.event_id)))
185 }
186 AnyMessageLikeEvent::KeyVerificationMac(MessageLikeEvent::Original(e)) => {
187 Ok(FlowId::from((&*e.room_id, &*e.content.relates_to.event_id)))
188 }
189 AnyMessageLikeEvent::KeyVerificationDone(MessageLikeEvent::Original(e)) => {
190 Ok(FlowId::from((&*e.room_id, &*e.content.relates_to.event_id)))
191 }
192 _ => Err(()),
193 }
194 }
195}
196
197impl TryFrom<&ToDeviceEvents> for FlowId {
198 type Error = ();
199
200 fn try_from(value: &ToDeviceEvents) -> Result<Self, Self::Error> {
201 match value {
202 ToDeviceEvents::KeyVerificationRequest(e) => {
203 Ok(FlowId::from(e.content.transaction_id.to_owned()))
204 }
205 ToDeviceEvents::KeyVerificationReady(e) => {
206 Ok(FlowId::from(e.content.transaction_id.to_owned()))
207 }
208 ToDeviceEvents::KeyVerificationStart(e) => {
209 Ok(FlowId::from(e.content.transaction_id.to_owned()))
210 }
211 ToDeviceEvents::KeyVerificationCancel(e) => {
212 Ok(FlowId::from(e.content.transaction_id.to_owned()))
213 }
214 ToDeviceEvents::KeyVerificationAccept(e) => {
215 Ok(FlowId::from(e.content.transaction_id.to_owned()))
216 }
217 ToDeviceEvents::KeyVerificationKey(e) => {
218 Ok(FlowId::from(e.content.transaction_id.to_owned()))
219 }
220 ToDeviceEvents::KeyVerificationMac(e) => {
221 Ok(FlowId::from(e.content.transaction_id.to_owned()))
222 }
223 ToDeviceEvents::KeyVerificationDone(e) => {
224 Ok(FlowId::from(e.content.transaction_id.to_owned()))
225 }
226 _ => Err(()),
227 }
228 }
229}
230
231#[derive(Debug)]
232pub enum AnyVerificationContent<'a> {
233 Request(RequestContent<'a>),
234 Ready(ReadyContent<'a>),
235 Cancel(CancelContent<'a>),
236 Start(StartContent<'a>),
237 Done(DoneContent<'a>),
238 Accept(AcceptContent<'a>),
239 Key(KeyContent<'a>),
240 Mac(MacContent<'a>),
241}
242
243#[derive(Debug)]
244pub enum RequestContent<'a> {
245 ToDevice(&'a ToDeviceKeyVerificationRequestEventContent),
246 Room(&'a KeyVerificationRequestEventContent),
247}
248
249impl RequestContent<'_> {
250 #[allow(clippy::wrong_self_convention)]
251 pub fn from_device(&self) -> &DeviceId {
252 match self {
253 Self::ToDevice(t) => &t.from_device,
254 Self::Room(r) => &r.from_device,
255 }
256 }
257
258 pub fn methods(&self) -> &[VerificationMethod] {
259 match self {
260 Self::ToDevice(t) => &t.methods,
261 Self::Room(r) => &r.methods,
262 }
263 }
264}
265
266#[derive(Debug)]
267pub enum ReadyContent<'a> {
268 ToDevice(&'a ToDeviceKeyVerificationReadyEventContent),
269 Room(&'a KeyVerificationReadyEventContent),
270}
271
272impl ReadyContent<'_> {
273 #[allow(clippy::wrong_self_convention)]
274 pub fn from_device(&self) -> &DeviceId {
275 match self {
276 Self::ToDevice(t) => &t.from_device,
277 Self::Room(r) => &r.from_device,
278 }
279 }
280
281 pub fn methods(&self) -> &[VerificationMethod] {
282 match self {
283 Self::ToDevice(t) => &t.methods,
284 Self::Room(r) => &r.methods,
285 }
286 }
287}
288
289macro_rules! from_for_enum {
290 ($type: ident, $enum_variant: ident, $enum: ident) => {
291 impl<'a> From<$type<'a>> for $enum<'a> {
292 fn from(c: $type<'a>) -> Self {
293 Self::$enum_variant(c)
294 }
295 }
296 };
297}
298
299macro_rules! from_borrow_for_enum {
300 ($type: ident, $enum_variant: ident, $enum: ident) => {
301 impl<'a> From<&'a $type> for $enum<'a> {
302 fn from(c: &'a $type) -> Self {
303 Self::$enum_variant(c)
304 }
305 }
306 };
307}
308
309from_for_enum!(RequestContent, Request, AnyVerificationContent);
310from_for_enum!(ReadyContent, Ready, AnyVerificationContent);
311from_for_enum!(CancelContent, Cancel, AnyVerificationContent);
312from_for_enum!(StartContent, Start, AnyVerificationContent);
313from_for_enum!(DoneContent, Done, AnyVerificationContent);
314from_for_enum!(AcceptContent, Accept, AnyVerificationContent);
315from_for_enum!(KeyContent, Key, AnyVerificationContent);
316from_for_enum!(MacContent, Mac, AnyVerificationContent);
317
318from_borrow_for_enum!(ToDeviceKeyVerificationRequestEventContent, ToDevice, RequestContent);
319from_borrow_for_enum!(KeyVerificationRequestEventContent, Room, RequestContent);
320from_borrow_for_enum!(KeyVerificationReadyEventContent, Room, ReadyContent);
321from_borrow_for_enum!(ToDeviceKeyVerificationReadyEventContent, ToDevice, ReadyContent);
322from_borrow_for_enum!(KeyVerificationStartEventContent, Room, StartContent);
323from_borrow_for_enum!(ToDeviceKeyVerificationStartEventContent, ToDevice, StartContent);
324from_borrow_for_enum!(KeyVerificationAcceptEventContent, Room, AcceptContent);
325from_borrow_for_enum!(ToDeviceKeyVerificationAcceptEventContent, ToDevice, AcceptContent);
326from_borrow_for_enum!(KeyVerificationKeyEventContent, Room, KeyContent);
327from_borrow_for_enum!(ToDeviceKeyVerificationKeyEventContent, ToDevice, KeyContent);
328from_borrow_for_enum!(KeyVerificationMacEventContent, Room, MacContent);
329from_borrow_for_enum!(ToDeviceKeyVerificationMacEventContent, ToDevice, MacContent);
330from_borrow_for_enum!(KeyVerificationCancelEventContent, Room, CancelContent);
331from_borrow_for_enum!(ToDeviceKeyVerificationCancelEventContent, ToDevice, CancelContent);
332
333macro_rules! try_from_outgoing_content {
334 ($type: ident, $enum_variant: ident) => {
335 impl<'a> TryFrom<&'a OutgoingContent> for $type<'a> {
336 type Error = ();
337
338 fn try_from(value: &'a OutgoingContent) -> Result<Self, Self::Error> {
339 match value {
340 OutgoingContent::Room(_, c) => {
341 if let AnyMessageLikeEventContent::$enum_variant(c) = c {
342 Ok(Self::Room(c))
343 } else {
344 Err(())
345 }
346 }
347 OutgoingContent::ToDevice(c) => {
348 if let AnyToDeviceEventContent::$enum_variant(c) = c {
349 Ok(Self::ToDevice(c))
350 } else {
351 Err(())
352 }
353 }
354 }
355 }
356 }
357 };
358}
359
360try_from_outgoing_content!(ReadyContent, KeyVerificationReady);
361try_from_outgoing_content!(StartContent, KeyVerificationStart);
362try_from_outgoing_content!(AcceptContent, KeyVerificationAccept);
363try_from_outgoing_content!(KeyContent, KeyVerificationKey);
364try_from_outgoing_content!(MacContent, KeyVerificationMac);
365try_from_outgoing_content!(CancelContent, KeyVerificationCancel);
366try_from_outgoing_content!(DoneContent, KeyVerificationDone);
367
368impl<'a> TryFrom<&'a OutgoingContent> for RequestContent<'a> {
369 type Error = ();
370
371 fn try_from(value: &'a OutgoingContent) -> Result<Self, Self::Error> {
372 match value {
373 OutgoingContent::Room(_, c) => {
374 if let AnyMessageLikeEventContent::RoomMessage(m) = c {
375 if let MessageType::VerificationRequest(c) = &m.msgtype {
376 Ok(Self::Room(c))
377 } else {
378 Err(())
379 }
380 } else {
381 Err(())
382 }
383 }
384 OutgoingContent::ToDevice(c) => {
385 if let AnyToDeviceEventContent::KeyVerificationRequest(c) = c {
386 Ok(Self::ToDevice(c))
387 } else {
388 Err(())
389 }
390 }
391 }
392 }
393}
394
395#[derive(Debug)]
396pub enum StartContent<'a> {
397 ToDevice(&'a ToDeviceKeyVerificationStartEventContent),
398 Room(&'a KeyVerificationStartEventContent),
399}
400
401impl StartContent<'_> {
402 #[allow(clippy::wrong_self_convention)]
403 pub fn from_device(&self) -> &DeviceId {
404 match self {
405 Self::ToDevice(c) => &c.from_device,
406 Self::Room(c) => &c.from_device,
407 }
408 }
409
410 pub fn flow_id(&self) -> &str {
411 match self {
412 Self::ToDevice(c) => c.transaction_id.as_str(),
413 Self::Room(c) => c.relates_to.event_id.as_str(),
414 }
415 }
416
417 pub fn method(&self) -> &StartMethod {
418 match self {
419 Self::ToDevice(c) => &c.method,
420 Self::Room(c) => &c.method,
421 }
422 }
423
424 pub fn canonical_json(&self) -> CanonicalJsonValue {
425 let content = match self {
426 Self::ToDevice(c) => serde_json::to_value(c),
427 Self::Room(c) => serde_json::to_value(c),
428 };
429
430 content.expect("Can't serialize content").try_into().expect("Can't canonicalize content")
431 }
432}
433
434impl<'a> From<&'a OwnedStartContent> for StartContent<'a> {
435 fn from(c: &'a OwnedStartContent) -> Self {
436 match c {
437 OwnedStartContent::ToDevice(c) => Self::ToDevice(c),
438 OwnedStartContent::Room(_, c) => Self::Room(c),
439 }
440 }
441}
442
443#[derive(Debug)]
444pub enum DoneContent<'a> {
445 ToDevice(&'a ToDeviceKeyVerificationDoneEventContent),
446 Room(&'a KeyVerificationDoneEventContent),
447}
448
449impl<'a> From<&'a KeyVerificationDoneEventContent> for DoneContent<'a> {
450 fn from(c: &'a KeyVerificationDoneEventContent) -> Self {
451 Self::Room(c)
452 }
453}
454
455impl<'a> From<&'a ToDeviceKeyVerificationDoneEventContent> for DoneContent<'a> {
456 fn from(c: &'a ToDeviceKeyVerificationDoneEventContent) -> Self {
457 Self::ToDevice(c)
458 }
459}
460
461impl DoneContent<'_> {
462 pub fn flow_id(&self) -> &str {
463 match self {
464 Self::ToDevice(c) => c.transaction_id.as_str(),
465 Self::Room(c) => c.relates_to.event_id.as_str(),
466 }
467 }
468}
469
470#[derive(Clone, Debug)]
471pub enum AcceptContent<'a> {
472 ToDevice(&'a ToDeviceKeyVerificationAcceptEventContent),
473 Room(&'a KeyVerificationAcceptEventContent),
474}
475
476impl AcceptContent<'_> {
477 pub fn flow_id(&self) -> &str {
478 match self {
479 Self::ToDevice(c) => c.transaction_id.as_str(),
480 Self::Room(c) => c.relates_to.event_id.as_str(),
481 }
482 }
483
484 pub fn method(&self) -> &AcceptMethod {
485 match self {
486 Self::ToDevice(c) => &c.method,
487 Self::Room(c) => &c.method,
488 }
489 }
490}
491
492impl<'a> From<&'a OwnedAcceptContent> for AcceptContent<'a> {
493 fn from(content: &'a OwnedAcceptContent) -> Self {
494 match content {
495 OwnedAcceptContent::ToDevice(c) => Self::ToDevice(c),
496 OwnedAcceptContent::Room(_, c) => Self::Room(c),
497 }
498 }
499}
500
501#[derive(Clone, Debug)]
502pub enum KeyContent<'a> {
503 ToDevice(&'a ToDeviceKeyVerificationKeyEventContent),
504 Room(&'a KeyVerificationKeyEventContent),
505}
506
507impl KeyContent<'_> {
508 pub fn flow_id(&self) -> &str {
509 match self {
510 Self::ToDevice(c) => c.transaction_id.as_str(),
511 Self::Room(c) => c.relates_to.event_id.as_str(),
512 }
513 }
514
515 pub fn public_key(&self) -> &Base64 {
516 match self {
517 Self::ToDevice(c) => &c.key,
518 Self::Room(c) => &c.key,
519 }
520 }
521}
522
523#[derive(Clone, Debug)]
524pub enum MacContent<'a> {
525 ToDevice(&'a ToDeviceKeyVerificationMacEventContent),
526 Room(&'a KeyVerificationMacEventContent),
527}
528
529impl MacContent<'_> {
530 pub fn flow_id(&self) -> &str {
531 match self {
532 Self::ToDevice(c) => c.transaction_id.as_str(),
533 Self::Room(c) => c.relates_to.event_id.as_str(),
534 }
535 }
536
537 pub fn mac(&self) -> &BTreeMap<String, Base64> {
538 match self {
539 Self::ToDevice(c) => &c.mac,
540 Self::Room(c) => &c.mac,
541 }
542 }
543
544 pub fn keys(&self) -> &Base64 {
545 match self {
546 Self::ToDevice(c) => &c.keys,
547 Self::Room(c) => &c.keys,
548 }
549 }
550}
551
552#[derive(Clone, Debug)]
553pub enum CancelContent<'a> {
554 ToDevice(&'a ToDeviceKeyVerificationCancelEventContent),
555 Room(&'a KeyVerificationCancelEventContent),
556}
557
558impl CancelContent<'_> {
559 pub fn cancel_code(&self) -> &CancelCode {
560 match self {
561 Self::ToDevice(c) => &c.code,
562 Self::Room(c) => &c.code,
563 }
564 }
565}
566
567#[derive(Clone, Debug)]
568pub enum OwnedStartContent {
569 ToDevice(ToDeviceKeyVerificationStartEventContent),
570 Room(OwnedRoomId, KeyVerificationStartEventContent),
571}
572
573impl OwnedStartContent {
574 pub fn method(&self) -> &StartMethod {
575 match self {
576 Self::ToDevice(c) => &c.method,
577 Self::Room(_, c) => &c.method,
578 }
579 }
580
581 pub fn method_mut(&mut self) -> &mut StartMethod {
582 match self {
583 Self::ToDevice(c) => &mut c.method,
584 Self::Room(_, c) => &mut c.method,
585 }
586 }
587
588 pub fn as_start_content(&self) -> StartContent<'_> {
589 match self {
590 Self::ToDevice(c) => StartContent::ToDevice(c),
591 Self::Room(_, c) => StartContent::Room(c),
592 }
593 }
594
595 pub fn flow_id(&self) -> FlowId {
596 match self {
597 Self::ToDevice(c) => FlowId::ToDevice(c.transaction_id.clone()),
598 Self::Room(r, c) => FlowId::InRoom(r.clone(), c.relates_to.event_id.clone()),
599 }
600 }
601
602 pub fn canonical_json(self) -> CanonicalJsonValue {
603 let content = match self {
604 Self::ToDevice(c) => serde_json::to_value(c),
605 Self::Room(_, c) => serde_json::to_value(c),
606 };
607
608 content.expect("Can't serialize content").try_into().expect("Can't canonicalize content")
609 }
610}
611
612impl From<(OwnedRoomId, KeyVerificationStartEventContent)> for OwnedStartContent {
613 fn from(tuple: (OwnedRoomId, KeyVerificationStartEventContent)) -> Self {
614 Self::Room(tuple.0, tuple.1)
615 }
616}
617
618impl From<ToDeviceKeyVerificationStartEventContent> for OwnedStartContent {
619 fn from(content: ToDeviceKeyVerificationStartEventContent) -> Self {
620 Self::ToDevice(content)
621 }
622}
623
624#[derive(Clone, Debug)]
625pub enum OwnedAcceptContent {
626 ToDevice(ToDeviceKeyVerificationAcceptEventContent),
627 Room(OwnedRoomId, KeyVerificationAcceptEventContent),
628}
629
630impl From<ToDeviceKeyVerificationAcceptEventContent> for OwnedAcceptContent {
631 fn from(content: ToDeviceKeyVerificationAcceptEventContent) -> Self {
632 Self::ToDevice(content)
633 }
634}
635
636impl From<(OwnedRoomId, KeyVerificationAcceptEventContent)> for OwnedAcceptContent {
637 fn from(content: (OwnedRoomId, KeyVerificationAcceptEventContent)) -> Self {
638 Self::Room(content.0, content.1)
639 }
640}
641
642impl OwnedAcceptContent {
643 pub fn method_mut(&mut self) -> &mut AcceptMethod {
644 match self {
645 Self::ToDevice(c) => &mut c.method,
646 Self::Room(_, c) => &mut c.method,
647 }
648 }
649}
650
651#[derive(Clone, Debug)]
652pub enum OutgoingContent {
653 Room(OwnedRoomId, AnyMessageLikeEventContent),
654 ToDevice(AnyToDeviceEventContent),
655}
656
657impl From<OwnedStartContent> for OutgoingContent {
658 fn from(content: OwnedStartContent) -> Self {
659 match content {
660 OwnedStartContent::Room(r, c) => {
661 (r, AnyMessageLikeEventContent::KeyVerificationStart(c)).into()
662 }
663 OwnedStartContent::ToDevice(c) => {
664 AnyToDeviceEventContent::KeyVerificationStart(c).into()
665 }
666 }
667 }
668}
669
670impl From<AnyToDeviceEventContent> for OutgoingContent {
671 fn from(content: AnyToDeviceEventContent) -> Self {
672 OutgoingContent::ToDevice(content)
673 }
674}
675
676impl From<(OwnedRoomId, AnyMessageLikeEventContent)> for OutgoingContent {
677 fn from(content: (OwnedRoomId, AnyMessageLikeEventContent)) -> Self {
678 OutgoingContent::Room(content.0, content.1)
679 }
680}
681
682use crate::types::{
683 events::ToDeviceEvents,
684 requests::{OutgoingRequest, OutgoingVerificationRequest, RoomMessageRequest, ToDeviceRequest},
685};
686
687impl TryFrom<OutgoingVerificationRequest> for OutgoingContent {
688 type Error = String;
689
690 fn try_from(request: OutgoingVerificationRequest) -> Result<Self, Self::Error> {
691 match request {
692 OutgoingVerificationRequest::ToDevice(r) => Self::try_from(r),
693 OutgoingVerificationRequest::InRoom(r) => Ok(Self::from(r)),
694 }
695 }
696}
697
698impl From<RoomMessageRequest> for OutgoingContent {
699 fn from(value: RoomMessageRequest) -> Self {
700 (value.room_id, value.content).into()
701 }
702}
703
704impl TryFrom<ToDeviceRequest> for OutgoingContent {
705 type Error = String;
706
707 fn try_from(request: ToDeviceRequest) -> Result<Self, Self::Error> {
708 use ruma::events::ToDeviceEventType;
709 use serde_json::Value;
710
711 let json: Value = serde_json::from_str(
712 request
713 .messages
714 .values()
715 .next()
716 .and_then(|m| m.values().next())
717 .map(|c| c.json().get())
718 .ok_or_else(|| "Content is missing from the request".to_owned())?,
719 )
720 .map_err(|e| e.to_string())?;
721
722 let content = match request.event_type {
723 ToDeviceEventType::KeyVerificationStart => {
724 AnyToDeviceEventContent::KeyVerificationStart(
725 serde_json::from_value(json).map_err(|e| e.to_string())?,
726 )
727 }
728 ToDeviceEventType::KeyVerificationKey => AnyToDeviceEventContent::KeyVerificationKey(
729 serde_json::from_value(json).map_err(|e| e.to_string())?,
730 ),
731 ToDeviceEventType::KeyVerificationAccept => {
732 AnyToDeviceEventContent::KeyVerificationAccept(
733 serde_json::from_value(json).map_err(|e| e.to_string())?,
734 )
735 }
736 ToDeviceEventType::KeyVerificationMac => AnyToDeviceEventContent::KeyVerificationMac(
737 serde_json::from_value(json).map_err(|e| e.to_string())?,
738 ),
739 ToDeviceEventType::KeyVerificationCancel => {
740 AnyToDeviceEventContent::KeyVerificationCancel(
741 serde_json::from_value(json).map_err(|e| e.to_string())?,
742 )
743 }
744 ToDeviceEventType::KeyVerificationReady => {
745 AnyToDeviceEventContent::KeyVerificationReady(
746 serde_json::from_value(json).map_err(|e| e.to_string())?,
747 )
748 }
749 ToDeviceEventType::KeyVerificationDone => AnyToDeviceEventContent::KeyVerificationDone(
750 serde_json::from_value(json).map_err(|e| e.to_string())?,
751 ),
752 ToDeviceEventType::KeyVerificationRequest => {
753 AnyToDeviceEventContent::KeyVerificationRequest(
754 serde_json::from_value(json).map_err(|e| e.to_string())?,
755 )
756 }
757 e => return Err(format!("Unsupported event type {e}")),
758 };
759
760 Ok(content.into())
761 }
762}
763
764impl TryFrom<OutgoingRequest> for OutgoingContent {
765 type Error = String;
766
767 fn try_from(value: OutgoingRequest) -> Result<Self, Self::Error> {
768 use crate::types::requests::AnyOutgoingRequest;
769
770 match value.request() {
771 AnyOutgoingRequest::KeysUpload(_)
772 | AnyOutgoingRequest::KeysQuery(_)
773 | AnyOutgoingRequest::SignatureUpload(_)
774 | AnyOutgoingRequest::KeysClaim(_) => Err("Invalid request type".to_owned()),
775 AnyOutgoingRequest::ToDeviceRequest(r) => Self::try_from(r.clone()),
776 AnyOutgoingRequest::RoomMessage(r) => Ok(Self::from(r.clone())),
777 }
778 }
779}