use std::collections::BTreeMap;
use as_variant::as_variant;
use ruma::{
events::{
key::verification::{
accept::{
AcceptMethod, KeyVerificationAcceptEventContent,
ToDeviceKeyVerificationAcceptEventContent,
},
cancel::{
CancelCode, KeyVerificationCancelEventContent,
ToDeviceKeyVerificationCancelEventContent,
},
done::{KeyVerificationDoneEventContent, ToDeviceKeyVerificationDoneEventContent},
key::{KeyVerificationKeyEventContent, ToDeviceKeyVerificationKeyEventContent},
mac::{KeyVerificationMacEventContent, ToDeviceKeyVerificationMacEventContent},
ready::{KeyVerificationReadyEventContent, ToDeviceKeyVerificationReadyEventContent},
request::ToDeviceKeyVerificationRequestEventContent,
start::{
KeyVerificationStartEventContent, StartMethod,
ToDeviceKeyVerificationStartEventContent,
},
VerificationMethod,
},
room::message::{KeyVerificationRequestEventContent, MessageType},
AnyMessageLikeEvent, AnyMessageLikeEventContent, AnyToDeviceEventContent, MessageLikeEvent,
},
serde::Base64,
CanonicalJsonValue, DeviceId, MilliSecondsSinceUnixEpoch, OwnedRoomId, UserId,
};
use super::FlowId;
#[derive(Debug)]
pub enum AnyEvent<'a> {
Room(&'a AnyMessageLikeEvent),
ToDevice(&'a ToDeviceEvents),
}
impl AnyEvent<'_> {
pub fn event_type(&self) -> String {
match self {
Self::Room(e) => e.event_type().to_string(),
Self::ToDevice(e) => e.event_type().to_string(),
}
}
pub fn sender(&self) -> &UserId {
match self {
Self::Room(e) => e.sender(),
Self::ToDevice(e) => e.sender(),
}
}
pub fn timestamp(&self) -> Option<MilliSecondsSinceUnixEpoch> {
match self {
AnyEvent::Room(e) => Some(e.origin_server_ts()),
AnyEvent::ToDevice(e) => {
as_variant!(e, ToDeviceEvents::KeyVerificationRequest(e) => e.content.timestamp)
}
}
}
pub fn is_room_event(&self) -> bool {
matches!(self, AnyEvent::Room(_))
}
pub fn verification_content(&self) -> Option<AnyVerificationContent<'_>> {
match self {
AnyEvent::Room(e) => match e {
AnyMessageLikeEvent::RoomMessage(MessageLikeEvent::Original(m)) => {
as_variant!(&m.content.msgtype, MessageType::VerificationRequest)
.map(|v| RequestContent::from(v).into())
}
AnyMessageLikeEvent::KeyVerificationReady(MessageLikeEvent::Original(e)) => {
Some(ReadyContent::from(&e.content).into())
}
AnyMessageLikeEvent::KeyVerificationStart(MessageLikeEvent::Original(e)) => {
Some(StartContent::from(&e.content).into())
}
AnyMessageLikeEvent::KeyVerificationCancel(MessageLikeEvent::Original(e)) => {
Some(CancelContent::from(&e.content).into())
}
AnyMessageLikeEvent::KeyVerificationAccept(MessageLikeEvent::Original(e)) => {
Some(AcceptContent::from(&e.content).into())
}
AnyMessageLikeEvent::KeyVerificationKey(MessageLikeEvent::Original(e)) => {
Some(KeyContent::from(&e.content).into())
}
AnyMessageLikeEvent::KeyVerificationMac(MessageLikeEvent::Original(e)) => {
Some(MacContent::from(&e.content).into())
}
AnyMessageLikeEvent::KeyVerificationDone(MessageLikeEvent::Original(e)) => {
Some(DoneContent::from(&e.content).into())
}
_ => None,
},
AnyEvent::ToDevice(e) => match e {
ToDeviceEvents::KeyVerificationRequest(e) => {
Some(RequestContent::from(&e.content).into())
}
ToDeviceEvents::KeyVerificationReady(e) => {
Some(ReadyContent::from(&e.content).into())
}
ToDeviceEvents::KeyVerificationStart(e) => {
Some(StartContent::from(&e.content).into())
}
ToDeviceEvents::KeyVerificationCancel(e) => {
Some(CancelContent::from(&e.content).into())
}
ToDeviceEvents::KeyVerificationAccept(e) => {
Some(AcceptContent::from(&e.content).into())
}
ToDeviceEvents::KeyVerificationKey(e) => Some(KeyContent::from(&e.content).into()),
ToDeviceEvents::KeyVerificationMac(e) => Some(MacContent::from(&e.content).into()),
ToDeviceEvents::KeyVerificationDone(e) => {
Some(DoneContent::from(&e.content).into())
}
_ => None,
},
}
}
}
impl<'a> From<&'a AnyMessageLikeEvent> for AnyEvent<'a> {
fn from(e: &'a AnyMessageLikeEvent) -> Self {
Self::Room(e)
}
}
impl<'a> From<&'a ToDeviceEvents> for AnyEvent<'a> {
fn from(e: &'a ToDeviceEvents) -> Self {
Self::ToDevice(e)
}
}
impl TryFrom<&AnyEvent<'_>> for FlowId {
type Error = ();
fn try_from(value: &AnyEvent<'_>) -> Result<Self, Self::Error> {
match value {
AnyEvent::Room(e) => FlowId::try_from(*e),
AnyEvent::ToDevice(e) => FlowId::try_from(*e),
}
}
}
impl TryFrom<&AnyMessageLikeEvent> for FlowId {
type Error = ();
fn try_from(value: &AnyMessageLikeEvent) -> Result<Self, Self::Error> {
match value {
AnyMessageLikeEvent::KeyVerificationReady(MessageLikeEvent::Original(e)) => {
Ok(FlowId::from((&*e.room_id, &*e.content.relates_to.event_id)))
}
AnyMessageLikeEvent::RoomMessage(MessageLikeEvent::Original(e)) => {
Ok(FlowId::from((&*e.room_id, &*e.event_id)))
}
AnyMessageLikeEvent::KeyVerificationStart(MessageLikeEvent::Original(e)) => {
Ok(FlowId::from((&*e.room_id, &*e.content.relates_to.event_id)))
}
AnyMessageLikeEvent::KeyVerificationCancel(MessageLikeEvent::Original(e)) => {
Ok(FlowId::from((&*e.room_id, &*e.content.relates_to.event_id)))
}
AnyMessageLikeEvent::KeyVerificationAccept(MessageLikeEvent::Original(e)) => {
Ok(FlowId::from((&*e.room_id, &*e.content.relates_to.event_id)))
}
AnyMessageLikeEvent::KeyVerificationKey(MessageLikeEvent::Original(e)) => {
Ok(FlowId::from((&*e.room_id, &*e.content.relates_to.event_id)))
}
AnyMessageLikeEvent::KeyVerificationMac(MessageLikeEvent::Original(e)) => {
Ok(FlowId::from((&*e.room_id, &*e.content.relates_to.event_id)))
}
AnyMessageLikeEvent::KeyVerificationDone(MessageLikeEvent::Original(e)) => {
Ok(FlowId::from((&*e.room_id, &*e.content.relates_to.event_id)))
}
_ => Err(()),
}
}
}
impl TryFrom<&ToDeviceEvents> for FlowId {
type Error = ();
fn try_from(value: &ToDeviceEvents) -> Result<Self, Self::Error> {
match value {
ToDeviceEvents::KeyVerificationRequest(e) => {
Ok(FlowId::from(e.content.transaction_id.to_owned()))
}
ToDeviceEvents::KeyVerificationReady(e) => {
Ok(FlowId::from(e.content.transaction_id.to_owned()))
}
ToDeviceEvents::KeyVerificationStart(e) => {
Ok(FlowId::from(e.content.transaction_id.to_owned()))
}
ToDeviceEvents::KeyVerificationCancel(e) => {
Ok(FlowId::from(e.content.transaction_id.to_owned()))
}
ToDeviceEvents::KeyVerificationAccept(e) => {
Ok(FlowId::from(e.content.transaction_id.to_owned()))
}
ToDeviceEvents::KeyVerificationKey(e) => {
Ok(FlowId::from(e.content.transaction_id.to_owned()))
}
ToDeviceEvents::KeyVerificationMac(e) => {
Ok(FlowId::from(e.content.transaction_id.to_owned()))
}
ToDeviceEvents::KeyVerificationDone(e) => {
Ok(FlowId::from(e.content.transaction_id.to_owned()))
}
_ => Err(()),
}
}
}
#[derive(Debug)]
pub enum AnyVerificationContent<'a> {
Request(RequestContent<'a>),
Ready(ReadyContent<'a>),
Cancel(CancelContent<'a>),
Start(StartContent<'a>),
Done(DoneContent<'a>),
Accept(AcceptContent<'a>),
Key(KeyContent<'a>),
Mac(MacContent<'a>),
}
#[derive(Debug)]
pub enum RequestContent<'a> {
ToDevice(&'a ToDeviceKeyVerificationRequestEventContent),
Room(&'a KeyVerificationRequestEventContent),
}
impl RequestContent<'_> {
#[allow(clippy::wrong_self_convention)]
pub fn from_device(&self) -> &DeviceId {
match self {
Self::ToDevice(t) => &t.from_device,
Self::Room(r) => &r.from_device,
}
}
pub fn methods(&self) -> &[VerificationMethod] {
match self {
Self::ToDevice(t) => &t.methods,
Self::Room(r) => &r.methods,
}
}
}
#[derive(Debug)]
pub enum ReadyContent<'a> {
ToDevice(&'a ToDeviceKeyVerificationReadyEventContent),
Room(&'a KeyVerificationReadyEventContent),
}
impl ReadyContent<'_> {
#[allow(clippy::wrong_self_convention)]
pub fn from_device(&self) -> &DeviceId {
match self {
Self::ToDevice(t) => &t.from_device,
Self::Room(r) => &r.from_device,
}
}
pub fn methods(&self) -> &[VerificationMethod] {
match self {
Self::ToDevice(t) => &t.methods,
Self::Room(r) => &r.methods,
}
}
}
macro_rules! from_for_enum {
($type: ident, $enum_variant: ident, $enum: ident) => {
impl<'a> From<$type<'a>> for $enum<'a> {
fn from(c: $type<'a>) -> Self {
Self::$enum_variant(c)
}
}
};
}
macro_rules! from_borrow_for_enum {
($type: ident, $enum_variant: ident, $enum: ident) => {
impl<'a> From<&'a $type> for $enum<'a> {
fn from(c: &'a $type) -> Self {
Self::$enum_variant(c)
}
}
};
}
from_for_enum!(RequestContent, Request, AnyVerificationContent);
from_for_enum!(ReadyContent, Ready, AnyVerificationContent);
from_for_enum!(CancelContent, Cancel, AnyVerificationContent);
from_for_enum!(StartContent, Start, AnyVerificationContent);
from_for_enum!(DoneContent, Done, AnyVerificationContent);
from_for_enum!(AcceptContent, Accept, AnyVerificationContent);
from_for_enum!(KeyContent, Key, AnyVerificationContent);
from_for_enum!(MacContent, Mac, AnyVerificationContent);
from_borrow_for_enum!(ToDeviceKeyVerificationRequestEventContent, ToDevice, RequestContent);
from_borrow_for_enum!(KeyVerificationRequestEventContent, Room, RequestContent);
from_borrow_for_enum!(KeyVerificationReadyEventContent, Room, ReadyContent);
from_borrow_for_enum!(ToDeviceKeyVerificationReadyEventContent, ToDevice, ReadyContent);
from_borrow_for_enum!(KeyVerificationStartEventContent, Room, StartContent);
from_borrow_for_enum!(ToDeviceKeyVerificationStartEventContent, ToDevice, StartContent);
from_borrow_for_enum!(KeyVerificationAcceptEventContent, Room, AcceptContent);
from_borrow_for_enum!(ToDeviceKeyVerificationAcceptEventContent, ToDevice, AcceptContent);
from_borrow_for_enum!(KeyVerificationKeyEventContent, Room, KeyContent);
from_borrow_for_enum!(ToDeviceKeyVerificationKeyEventContent, ToDevice, KeyContent);
from_borrow_for_enum!(KeyVerificationMacEventContent, Room, MacContent);
from_borrow_for_enum!(ToDeviceKeyVerificationMacEventContent, ToDevice, MacContent);
from_borrow_for_enum!(KeyVerificationCancelEventContent, Room, CancelContent);
from_borrow_for_enum!(ToDeviceKeyVerificationCancelEventContent, ToDevice, CancelContent);
macro_rules! try_from_outgoing_content {
($type: ident, $enum_variant: ident) => {
impl<'a> TryFrom<&'a OutgoingContent> for $type<'a> {
type Error = ();
fn try_from(value: &'a OutgoingContent) -> Result<Self, Self::Error> {
match value {
OutgoingContent::Room(_, c) => {
if let AnyMessageLikeEventContent::$enum_variant(c) = c {
Ok(Self::Room(c))
} else {
Err(())
}
}
OutgoingContent::ToDevice(c) => {
if let AnyToDeviceEventContent::$enum_variant(c) = c {
Ok(Self::ToDevice(c))
} else {
Err(())
}
}
}
}
}
};
}
try_from_outgoing_content!(ReadyContent, KeyVerificationReady);
try_from_outgoing_content!(StartContent, KeyVerificationStart);
try_from_outgoing_content!(AcceptContent, KeyVerificationAccept);
try_from_outgoing_content!(KeyContent, KeyVerificationKey);
try_from_outgoing_content!(MacContent, KeyVerificationMac);
try_from_outgoing_content!(CancelContent, KeyVerificationCancel);
try_from_outgoing_content!(DoneContent, KeyVerificationDone);
impl<'a> TryFrom<&'a OutgoingContent> for RequestContent<'a> {
type Error = ();
fn try_from(value: &'a OutgoingContent) -> Result<Self, Self::Error> {
match value {
OutgoingContent::Room(_, c) => {
if let AnyMessageLikeEventContent::RoomMessage(m) = c {
if let MessageType::VerificationRequest(c) = &m.msgtype {
Ok(Self::Room(c))
} else {
Err(())
}
} else {
Err(())
}
}
OutgoingContent::ToDevice(c) => {
if let AnyToDeviceEventContent::KeyVerificationRequest(c) = c {
Ok(Self::ToDevice(c))
} else {
Err(())
}
}
}
}
}
#[derive(Debug)]
pub enum StartContent<'a> {
ToDevice(&'a ToDeviceKeyVerificationStartEventContent),
Room(&'a KeyVerificationStartEventContent),
}
impl StartContent<'_> {
#[allow(clippy::wrong_self_convention)]
pub fn from_device(&self) -> &DeviceId {
match self {
Self::ToDevice(c) => &c.from_device,
Self::Room(c) => &c.from_device,
}
}
pub fn flow_id(&self) -> &str {
match self {
Self::ToDevice(c) => c.transaction_id.as_str(),
Self::Room(c) => c.relates_to.event_id.as_str(),
}
}
pub fn method(&self) -> &StartMethod {
match self {
Self::ToDevice(c) => &c.method,
Self::Room(c) => &c.method,
}
}
pub fn canonical_json(&self) -> CanonicalJsonValue {
let content = match self {
Self::ToDevice(c) => serde_json::to_value(c),
Self::Room(c) => serde_json::to_value(c),
};
content.expect("Can't serialize content").try_into().expect("Can't canonicalize content")
}
}
impl<'a> From<&'a OwnedStartContent> for StartContent<'a> {
fn from(c: &'a OwnedStartContent) -> Self {
match c {
OwnedStartContent::ToDevice(c) => Self::ToDevice(c),
OwnedStartContent::Room(_, c) => Self::Room(c),
}
}
}
#[derive(Debug)]
pub enum DoneContent<'a> {
ToDevice(&'a ToDeviceKeyVerificationDoneEventContent),
Room(&'a KeyVerificationDoneEventContent),
}
impl<'a> From<&'a KeyVerificationDoneEventContent> for DoneContent<'a> {
fn from(c: &'a KeyVerificationDoneEventContent) -> Self {
Self::Room(c)
}
}
impl<'a> From<&'a ToDeviceKeyVerificationDoneEventContent> for DoneContent<'a> {
fn from(c: &'a ToDeviceKeyVerificationDoneEventContent) -> Self {
Self::ToDevice(c)
}
}
impl DoneContent<'_> {
pub fn flow_id(&self) -> &str {
match self {
Self::ToDevice(c) => c.transaction_id.as_str(),
Self::Room(c) => c.relates_to.event_id.as_str(),
}
}
}
#[derive(Clone, Debug)]
pub enum AcceptContent<'a> {
ToDevice(&'a ToDeviceKeyVerificationAcceptEventContent),
Room(&'a KeyVerificationAcceptEventContent),
}
impl AcceptContent<'_> {
pub fn flow_id(&self) -> &str {
match self {
Self::ToDevice(c) => c.transaction_id.as_str(),
Self::Room(c) => c.relates_to.event_id.as_str(),
}
}
pub fn method(&self) -> &AcceptMethod {
match self {
Self::ToDevice(c) => &c.method,
Self::Room(c) => &c.method,
}
}
}
impl<'a> From<&'a OwnedAcceptContent> for AcceptContent<'a> {
fn from(content: &'a OwnedAcceptContent) -> Self {
match content {
OwnedAcceptContent::ToDevice(c) => Self::ToDevice(c),
OwnedAcceptContent::Room(_, c) => Self::Room(c),
}
}
}
#[derive(Clone, Debug)]
pub enum KeyContent<'a> {
ToDevice(&'a ToDeviceKeyVerificationKeyEventContent),
Room(&'a KeyVerificationKeyEventContent),
}
impl KeyContent<'_> {
pub fn flow_id(&self) -> &str {
match self {
Self::ToDevice(c) => c.transaction_id.as_str(),
Self::Room(c) => c.relates_to.event_id.as_str(),
}
}
pub fn public_key(&self) -> &Base64 {
match self {
Self::ToDevice(c) => &c.key,
Self::Room(c) => &c.key,
}
}
}
#[derive(Clone, Debug)]
pub enum MacContent<'a> {
ToDevice(&'a ToDeviceKeyVerificationMacEventContent),
Room(&'a KeyVerificationMacEventContent),
}
impl MacContent<'_> {
pub fn flow_id(&self) -> &str {
match self {
Self::ToDevice(c) => c.transaction_id.as_str(),
Self::Room(c) => c.relates_to.event_id.as_str(),
}
}
pub fn mac(&self) -> &BTreeMap<String, Base64> {
match self {
Self::ToDevice(c) => &c.mac,
Self::Room(c) => &c.mac,
}
}
pub fn keys(&self) -> &Base64 {
match self {
Self::ToDevice(c) => &c.keys,
Self::Room(c) => &c.keys,
}
}
}
#[derive(Clone, Debug)]
pub enum CancelContent<'a> {
ToDevice(&'a ToDeviceKeyVerificationCancelEventContent),
Room(&'a KeyVerificationCancelEventContent),
}
impl CancelContent<'_> {
pub fn cancel_code(&self) -> &CancelCode {
match self {
Self::ToDevice(c) => &c.code,
Self::Room(c) => &c.code,
}
}
}
#[derive(Clone, Debug)]
pub enum OwnedStartContent {
ToDevice(ToDeviceKeyVerificationStartEventContent),
Room(OwnedRoomId, KeyVerificationStartEventContent),
}
impl OwnedStartContent {
pub fn method(&self) -> &StartMethod {
match self {
Self::ToDevice(c) => &c.method,
Self::Room(_, c) => &c.method,
}
}
pub fn method_mut(&mut self) -> &mut StartMethod {
match self {
Self::ToDevice(c) => &mut c.method,
Self::Room(_, c) => &mut c.method,
}
}
pub fn as_start_content(&self) -> StartContent<'_> {
match self {
Self::ToDevice(c) => StartContent::ToDevice(c),
Self::Room(_, c) => StartContent::Room(c),
}
}
pub fn flow_id(&self) -> FlowId {
match self {
Self::ToDevice(c) => FlowId::ToDevice(c.transaction_id.clone()),
Self::Room(r, c) => FlowId::InRoom(r.clone(), c.relates_to.event_id.clone()),
}
}
pub fn canonical_json(self) -> CanonicalJsonValue {
let content = match self {
Self::ToDevice(c) => serde_json::to_value(c),
Self::Room(_, c) => serde_json::to_value(c),
};
content.expect("Can't serialize content").try_into().expect("Can't canonicalize content")
}
}
impl From<(OwnedRoomId, KeyVerificationStartEventContent)> for OwnedStartContent {
fn from(tuple: (OwnedRoomId, KeyVerificationStartEventContent)) -> Self {
Self::Room(tuple.0, tuple.1)
}
}
impl From<ToDeviceKeyVerificationStartEventContent> for OwnedStartContent {
fn from(content: ToDeviceKeyVerificationStartEventContent) -> Self {
Self::ToDevice(content)
}
}
#[derive(Clone, Debug)]
pub enum OwnedAcceptContent {
ToDevice(ToDeviceKeyVerificationAcceptEventContent),
Room(OwnedRoomId, KeyVerificationAcceptEventContent),
}
impl From<ToDeviceKeyVerificationAcceptEventContent> for OwnedAcceptContent {
fn from(content: ToDeviceKeyVerificationAcceptEventContent) -> Self {
Self::ToDevice(content)
}
}
impl From<(OwnedRoomId, KeyVerificationAcceptEventContent)> for OwnedAcceptContent {
fn from(content: (OwnedRoomId, KeyVerificationAcceptEventContent)) -> Self {
Self::Room(content.0, content.1)
}
}
impl OwnedAcceptContent {
pub fn method_mut(&mut self) -> &mut AcceptMethod {
match self {
Self::ToDevice(c) => &mut c.method,
Self::Room(_, c) => &mut c.method,
}
}
}
#[derive(Clone, Debug)]
pub enum OutgoingContent {
Room(OwnedRoomId, AnyMessageLikeEventContent),
ToDevice(AnyToDeviceEventContent),
}
impl From<OwnedStartContent> for OutgoingContent {
fn from(content: OwnedStartContent) -> Self {
match content {
OwnedStartContent::Room(r, c) => {
(r, AnyMessageLikeEventContent::KeyVerificationStart(c)).into()
}
OwnedStartContent::ToDevice(c) => {
AnyToDeviceEventContent::KeyVerificationStart(c).into()
}
}
}
}
impl From<AnyToDeviceEventContent> for OutgoingContent {
fn from(content: AnyToDeviceEventContent) -> Self {
OutgoingContent::ToDevice(content)
}
}
impl From<(OwnedRoomId, AnyMessageLikeEventContent)> for OutgoingContent {
fn from(content: (OwnedRoomId, AnyMessageLikeEventContent)) -> Self {
OutgoingContent::Room(content.0, content.1)
}
}
use crate::types::{
events::ToDeviceEvents,
requests::{OutgoingRequest, OutgoingVerificationRequest, RoomMessageRequest, ToDeviceRequest},
};
impl TryFrom<OutgoingVerificationRequest> for OutgoingContent {
type Error = String;
fn try_from(request: OutgoingVerificationRequest) -> Result<Self, Self::Error> {
match request {
OutgoingVerificationRequest::ToDevice(r) => Self::try_from(r),
OutgoingVerificationRequest::InRoom(r) => Ok(Self::from(r)),
}
}
}
impl From<RoomMessageRequest> for OutgoingContent {
fn from(value: RoomMessageRequest) -> Self {
(value.room_id, value.content).into()
}
}
impl TryFrom<ToDeviceRequest> for OutgoingContent {
type Error = String;
fn try_from(request: ToDeviceRequest) -> Result<Self, Self::Error> {
use ruma::events::ToDeviceEventType;
use serde_json::Value;
let json: Value = serde_json::from_str(
request
.messages
.values()
.next()
.and_then(|m| m.values().next())
.map(|c| c.json().get())
.ok_or_else(|| "Content is missing from the request".to_owned())?,
)
.map_err(|e| e.to_string())?;
let content = match request.event_type {
ToDeviceEventType::KeyVerificationStart => {
AnyToDeviceEventContent::KeyVerificationStart(
serde_json::from_value(json).map_err(|e| e.to_string())?,
)
}
ToDeviceEventType::KeyVerificationKey => AnyToDeviceEventContent::KeyVerificationKey(
serde_json::from_value(json).map_err(|e| e.to_string())?,
),
ToDeviceEventType::KeyVerificationAccept => {
AnyToDeviceEventContent::KeyVerificationAccept(
serde_json::from_value(json).map_err(|e| e.to_string())?,
)
}
ToDeviceEventType::KeyVerificationMac => AnyToDeviceEventContent::KeyVerificationMac(
serde_json::from_value(json).map_err(|e| e.to_string())?,
),
ToDeviceEventType::KeyVerificationCancel => {
AnyToDeviceEventContent::KeyVerificationCancel(
serde_json::from_value(json).map_err(|e| e.to_string())?,
)
}
ToDeviceEventType::KeyVerificationReady => {
AnyToDeviceEventContent::KeyVerificationReady(
serde_json::from_value(json).map_err(|e| e.to_string())?,
)
}
ToDeviceEventType::KeyVerificationDone => AnyToDeviceEventContent::KeyVerificationDone(
serde_json::from_value(json).map_err(|e| e.to_string())?,
),
ToDeviceEventType::KeyVerificationRequest => {
AnyToDeviceEventContent::KeyVerificationRequest(
serde_json::from_value(json).map_err(|e| e.to_string())?,
)
}
e => return Err(format!("Unsupported event type {e}")),
};
Ok(content.into())
}
}
impl TryFrom<OutgoingRequest> for OutgoingContent {
type Error = String;
fn try_from(value: OutgoingRequest) -> Result<Self, Self::Error> {
use crate::types::requests::AnyOutgoingRequest;
match value.request() {
AnyOutgoingRequest::KeysUpload(_)
| AnyOutgoingRequest::KeysQuery(_)
| AnyOutgoingRequest::SignatureUpload(_)
| AnyOutgoingRequest::KeysClaim(_) => Err("Invalid request type".to_owned()),
AnyOutgoingRequest::ToDeviceRequest(r) => Self::try_from(r.clone()),
AnyOutgoingRequest::RoomMessage(r) => Ok(Self::from(r.clone())),
}
}
}