matrix-rust-sdk/crates/matrix-sdk-base/src/deserialized_responses.rs

281 lines
9.3 KiB
Rust

// Copyright 2022 The Matrix.org Foundation C.I.C.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! SDK-specific variations of response types from Ruma.
use std::{collections::BTreeMap, fmt};
pub use matrix_sdk_common::deserialized_responses::*;
use ruma::{
events::{
room::{
member::{MembershipState, RoomMemberEvent, RoomMemberEventContent},
power_levels::{RoomPowerLevels, RoomPowerLevelsEventContent},
},
AnyStrippedStateEvent, AnySyncStateEvent, EventContentFromType,
PossiblyRedactedStateEventContent, RedactContent, RedactedStateEventContent,
StateEventContent, StaticStateEventContent, StrippedStateEvent, SyncStateEvent,
},
serde::Raw,
EventId, MilliSecondsSinceUnixEpoch, OwnedEventId, OwnedRoomId, OwnedUserId, UserId,
};
use serde::Serialize;
/// A change in ambiguity of room members that an `m.room.member` event
/// triggers.
#[derive(Clone, Debug, Default)]
#[non_exhaustive]
pub struct AmbiguityChange {
/// Is the member that is contained in the state key of the `m.room.member`
/// event itself ambiguous because of the event.
pub member_ambiguous: bool,
/// Has another user been disambiguated because of this event.
pub disambiguated_member: Option<OwnedUserId>,
/// Has another user become ambiguous because of this event.
pub ambiguated_member: Option<OwnedUserId>,
}
/// Collection of ambiguity changes that room member events trigger.
#[derive(Clone, Debug, Default)]
#[non_exhaustive]
pub struct AmbiguityChanges {
/// A map from room id to a map of an event id to the `AmbiguityChange` that
/// the event with the given id caused.
pub changes: BTreeMap<OwnedRoomId, BTreeMap<OwnedEventId, AmbiguityChange>>,
}
/// A deserialized response for the rooms members API call.
///
/// [`GET /_matrix/client/r0/rooms/{roomId}/members`](https://spec.matrix.org/v1.5/client-server-api/#get_matrixclientv3roomsroomidmembers)
#[derive(Clone, Debug, Default)]
pub struct MembersResponse {
/// The list of members events.
pub chunk: Vec<RoomMemberEvent>,
/// Collection of ambiguity changes that room member events trigger.
pub ambiguity_changes: AmbiguityChanges,
}
/// Wrapper around both versions of any raw state event.
#[derive(Clone, Debug, Serialize)]
#[serde(untagged)]
pub enum RawAnySyncOrStrippedState {
/// An event from a room in joined or left state.
Sync(Raw<AnySyncStateEvent>),
/// An event from a room in invited state.
Stripped(Raw<AnyStrippedStateEvent>),
}
impl RawAnySyncOrStrippedState {
/// Try to deserialize the inner JSON as the expected type.
pub fn deserialize(&self) -> serde_json::Result<AnySyncOrStrippedState> {
match self {
Self::Sync(raw) => Ok(AnySyncOrStrippedState::Sync(raw.deserialize()?)),
Self::Stripped(raw) => Ok(AnySyncOrStrippedState::Stripped(raw.deserialize()?)),
}
}
/// Turns this `RawAnySyncOrStrippedState` into `RawSyncOrStrippedState<C>`
/// without changing the underlying JSON.
pub fn cast<C>(self) -> RawSyncOrStrippedState<C>
where
C: StaticStateEventContent + RedactContent,
C::Redacted: RedactedStateEventContent,
{
match self {
Self::Sync(raw) => RawSyncOrStrippedState::Sync(raw.cast()),
Self::Stripped(raw) => RawSyncOrStrippedState::Stripped(raw.cast()),
}
}
}
/// Wrapper around both versions of any state event.
#[derive(Clone, Debug)]
pub enum AnySyncOrStrippedState {
/// An event from a room in joined or left state.
Sync(AnySyncStateEvent),
/// An event from a room in invited state.
Stripped(AnyStrippedStateEvent),
}
impl AnySyncOrStrippedState {
/// If this is an `AnySyncStateEvent`, return a reference to the inner
/// event.
pub fn as_sync(&self) -> Option<&AnySyncStateEvent> {
match self {
Self::Sync(ev) => Some(ev),
Self::Stripped(_) => None,
}
}
/// If this is an `AnyStrippedStateEvent`, return a reference to the inner
/// event.
pub fn as_stripped(&self) -> Option<&AnyStrippedStateEvent> {
match self {
Self::Sync(_) => None,
Self::Stripped(ev) => Some(ev),
}
}
}
/// Wrapper around both versions of a raw state event.
#[derive(Clone, Debug, Serialize)]
#[serde(untagged)]
pub enum RawSyncOrStrippedState<C>
where
C: StaticStateEventContent + RedactContent,
C::Redacted: RedactedStateEventContent,
{
/// An event from a room in joined or left state.
Sync(Raw<SyncStateEvent<C>>),
/// An event from a room in invited state.
Stripped(Raw<StrippedStateEvent<C::PossiblyRedacted>>),
}
impl<C> RawSyncOrStrippedState<C>
where
C: StaticStateEventContent + RedactContent,
C::Redacted: RedactedStateEventContent + fmt::Debug + Clone,
{
/// Try to deserialize the inner JSON as the expected type.
pub fn deserialize(&self) -> serde_json::Result<SyncOrStrippedState<C>>
where
C: StaticStateEventContent + EventContentFromType + RedactContent,
C::Redacted: RedactedStateEventContent<StateKey = C::StateKey> + EventContentFromType,
C::PossiblyRedacted: PossiblyRedactedStateEventContent + EventContentFromType,
{
match self {
Self::Sync(ev) => Ok(SyncOrStrippedState::Sync(ev.deserialize()?)),
Self::Stripped(ev) => Ok(SyncOrStrippedState::Stripped(ev.deserialize()?)),
}
}
}
/// Raw version of [`MemberEvent`].
pub type RawMemberEvent = RawSyncOrStrippedState<RoomMemberEventContent>;
/// Wrapper around both versions of a state event.
#[derive(Clone, Debug)]
pub enum SyncOrStrippedState<C>
where
C: StaticStateEventContent + RedactContent,
C::Redacted: RedactedStateEventContent + fmt::Debug + Clone,
{
/// An event from a room in joined or left state.
Sync(SyncStateEvent<C>),
/// An event from a room in invited state.
Stripped(StrippedStateEvent<C::PossiblyRedacted>),
}
impl<C> SyncOrStrippedState<C>
where
C: StaticStateEventContent + RedactContent,
C::Redacted: RedactedStateEventContent<StateKey = C::StateKey> + fmt::Debug + Clone,
C::PossiblyRedacted: PossiblyRedactedStateEventContent<StateKey = C::StateKey>,
{
/// If this is a `SyncStateEvent`, return a reference to the inner event.
pub fn as_sync(&self) -> Option<&SyncStateEvent<C>> {
match self {
Self::Sync(ev) => Some(ev),
Self::Stripped(_) => None,
}
}
/// If this is a `StrippedStateEvent`, return a reference to the inner
/// event.
pub fn as_stripped(&self) -> Option<&StrippedStateEvent<C::PossiblyRedacted>> {
match self {
Self::Sync(_) => None,
Self::Stripped(ev) => Some(ev),
}
}
/// The sender of this event.
pub fn sender(&self) -> &UserId {
match self {
Self::Sync(e) => e.sender(),
Self::Stripped(e) => &e.sender,
}
}
/// The ID of this event.
pub fn event_id(&self) -> Option<&EventId> {
match self {
Self::Sync(e) => Some(e.event_id()),
Self::Stripped(_) => None,
}
}
/// The server timestamp of this event.
pub fn origin_server_ts(&self) -> Option<MilliSecondsSinceUnixEpoch> {
match self {
Self::Sync(e) => Some(e.origin_server_ts()),
Self::Stripped(_) => None,
}
}
/// The state key associated to this state event.
pub fn state_key(&self) -> &C::StateKey {
match self {
Self::Sync(e) => e.state_key(),
Self::Stripped(e) => &e.state_key,
}
}
}
impl<C> SyncOrStrippedState<C>
where
C: StaticStateEventContent<PossiblyRedacted = C>
+ RedactContent
+ PossiblyRedactedStateEventContent,
C::Redacted: RedactedStateEventContent<StateKey = <C as StateEventContent>::StateKey>
+ fmt::Debug
+ Clone,
{
/// The inner content of the wrapped event.
pub fn original_content(&self) -> Option<&C> {
match self {
Self::Sync(e) => e.as_original().map(|e| &e.content),
Self::Stripped(e) => Some(&e.content),
}
}
}
/// Wrapper around both MemberEvent-Types
pub type MemberEvent = SyncOrStrippedState<RoomMemberEventContent>;
impl MemberEvent {
/// The membership state of the user.
pub fn membership(&self) -> &MembershipState {
match self {
MemberEvent::Sync(e) => e.membership(),
MemberEvent::Stripped(e) => &e.content.membership,
}
}
/// The user id associated to this member event.
pub fn user_id(&self) -> &UserId {
self.state_key()
}
}
impl SyncOrStrippedState<RoomPowerLevelsEventContent> {
/// The power levels of the event.
pub fn power_levels(&self) -> RoomPowerLevels {
match self {
Self::Sync(e) => e.power_levels(),
Self::Stripped(e) => e.power_levels(),
}
}
}