Skip to content

Commit c7f5638

Browse files
committed
benjamin's review; let's squash this MR
1 parent d0048e7 commit c7f5638

File tree

9 files changed

+95
-112
lines changed

9 files changed

+95
-112
lines changed

bindings/matrix-sdk-ffi/src/client.rs

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1040,9 +1040,9 @@ impl Client {
10401040
// rustc win that one fight.
10411041
let room_id: &RoomId = &room_id;
10421042

1043-
let sdk_room_preview = self.inner.get_room_preview(room_id.into(), via_servers).await?;
1043+
let room_preview = self.inner.get_room_preview(room_id.into(), via_servers).await?;
10441044

1045-
Ok(Arc::new(RoomPreview::from_sdk(sdk_room_preview)))
1045+
Ok(Arc::new(RoomPreview::new(self.inner.clone(), room_preview)))
10461046
}
10471047

10481048
/// Given a room alias, get the preview of a room, to interact with it.
@@ -1057,9 +1057,9 @@ impl Client {
10571057
// rustc win that one fight.
10581058
let room_alias: &RoomAliasId = &room_alias;
10591059

1060-
let sdk_room_preview = self.inner.get_room_preview(room_alias.into(), Vec::new()).await?;
1060+
let room_preview = self.inner.get_room_preview(room_alias.into(), Vec::new()).await?;
10611061

1062-
Ok(Arc::new(RoomPreview::from_sdk(sdk_room_preview)))
1062+
Ok(Arc::new(RoomPreview::new(self.inner.clone(), room_preview)))
10631063
}
10641064

10651065
/// Waits until an at least partially synced room is received, and returns
@@ -1830,6 +1830,12 @@ pub enum JoinRule {
18301830
/// conditions described in a set of [`AllowRule`]s, or they can request
18311831
/// an invite to the room.
18321832
KnockRestricted { rules: Vec<AllowRule> },
1833+
1834+
/// A custom join rule, up for interpretation by the consumer.
1835+
Custom {
1836+
/// The string representation for this custom rule.
1837+
repr: String,
1838+
},
18331839
}
18341840

18351841
/// An allow rule which defines a condition that allows joining a room.
@@ -1857,6 +1863,7 @@ impl TryFrom<JoinRule> for ruma::events::room::join_rules::JoinRule {
18571863
let rules = allow_rules_from(rules)?;
18581864
Ok(Self::KnockRestricted(ruma::events::room::join_rules::Restricted::new(rules)))
18591865
}
1866+
JoinRule::Custom { repr } => Ok(serde_json::from_str(&repr)?),
18601867
}
18611868
}
18621869
}

bindings/matrix-sdk-ffi/src/error.rs

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ use std::{collections::HashMap, fmt, fmt::Display};
22

33
use matrix_sdk::{
44
encryption::CryptoStoreError, event_cache::EventCacheError, oidc::OidcError, reqwest,
5-
room::edit::EditError, room_preview::WrongRoomPreviewState, send_queue::RoomSendQueueError,
6-
HttpError, IdParseError, NotificationSettingsError as SdkNotificationSettingsError,
5+
room::edit::EditError, send_queue::RoomSendQueueError, HttpError, IdParseError,
6+
NotificationSettingsError as SdkNotificationSettingsError,
77
QueueWedgeError as SdkQueueWedgeError, StoreError,
88
};
99
use matrix_sdk_ui::{encryption_sync_service, notification_client, sync_service, timeline};
@@ -155,12 +155,6 @@ impl From<RoomSendQueueError> for ClientError {
155155
}
156156
}
157157

158-
impl From<WrongRoomPreviewState> for ClientError {
159-
fn from(e: WrongRoomPreviewState) -> Self {
160-
Self::new(e)
161-
}
162-
}
163-
164158
/// Bindings version of the sdk type replacing OwnedUserId/DeviceIds with simple
165159
/// String.
166160
///

bindings/matrix-sdk-ffi/src/lib.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,6 @@ mod platform;
1818
mod room;
1919
mod room_directory_search;
2020
mod room_info;
21-
22-
#[allow(deprecated)]
2321
mod room_list;
2422
mod room_member;
2523
mod room_preview;

bindings/matrix-sdk-ffi/src/room_list.rs

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,12 @@
1-
use std::{fmt::Debug, mem::MaybeUninit, ptr::addr_of_mut, sync::Arc, time::Duration};
1+
#![allow(deprecated)]
2+
3+
use std::{
4+
fmt::Debug,
5+
mem::{ManuallyDrop, MaybeUninit},
6+
ptr::addr_of_mut,
7+
sync::Arc,
8+
time::Duration,
9+
};
210

311
use eyeball_im::VectorDiff;
412
use futures_util::{pin_mut, StreamExt, TryFutureExt};
@@ -599,6 +607,13 @@ impl RoomListItem {
599607
/// An error will be returned if the room is in a state other than invited
600608
/// or knocked.
601609
async fn preview_room(&self, via: Vec<String>) -> Result<Arc<RoomPreview>, ClientError> {
610+
// Validate parameters first.
611+
let server_names: Vec<OwnedServerName> = via
612+
.into_iter()
613+
.map(|server| ServerName::parse(server).map_err(ClientError::from))
614+
.collect::<Result<_, ClientError>>()?;
615+
616+
// Validate internal room state.
602617
let membership = self.membership();
603618
if !matches!(membership, Membership::Invited | Membership::Knocked) {
604619
return Err(RoomListError::IncorrectRoomMembership {
@@ -608,21 +623,19 @@ impl RoomListItem {
608623
.into());
609624
}
610625

626+
// Do the thing.
611627
let client = self.inner.client();
612628
let (room_or_alias_id, server_names) = if let Some(alias) = self.inner.canonical_alias() {
613629
let room_or_alias_id: OwnedRoomOrAliasId = alias.into();
614630
(room_or_alias_id, Vec::new())
615631
} else {
616632
let room_or_alias_id: OwnedRoomOrAliasId = self.inner.id().to_owned().into();
617-
let server_names: Vec<OwnedServerName> = via
618-
.into_iter()
619-
.map(|server| ServerName::parse(server).map_err(ClientError::from))
620-
.collect::<Result<_, ClientError>>()?;
621633
(room_or_alias_id, server_names)
622634
};
623635

624636
let room_preview = client.get_room_preview(&room_or_alias_id, server_names).await?;
625-
Ok(Arc::new(RoomPreview::from_sdk(room_preview)))
637+
638+
Ok(Arc::new(RoomPreview::new(ManuallyDrop::new(client), room_preview)))
626639
}
627640

628641
/// Build a full `Room` FFI object, filling its associated timeline.

bindings/matrix-sdk-ffi/src/room_preview.rs

Lines changed: 43 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,41 @@
1-
use std::sync::Arc;
1+
use std::mem::ManuallyDrop;
22

3-
use matrix_sdk::room_preview::RoomPreview as SdkRoomPreview;
3+
use anyhow::Context as _;
4+
use async_compat::TOKIO1 as RUNTIME;
5+
use matrix_sdk::{room_preview::RoomPreview as SdkRoomPreview, Client};
46
use ruma::space::SpaceRoomJoinRule;
7+
use tracing::warn;
58

69
use crate::{client::JoinRule, error::ClientError, room::Membership};
710

811
/// A room preview for a room. It's intended to be used to represent rooms that
912
/// aren't joined yet.
1013
#[derive(uniffi::Object)]
1114
pub struct RoomPreview {
12-
inner: Arc<SdkRoomPreview>,
15+
inner: SdkRoomPreview,
16+
client: ManuallyDrop<Client>,
17+
}
18+
19+
impl Drop for RoomPreview {
20+
fn drop(&mut self) {
21+
// Dropping the inner OlmMachine must happen within a tokio context
22+
// because deadpool drops sqlite connections in the DB pool on tokio's
23+
// blocking threadpool to avoid blocking async worker threads.
24+
let _guard = RUNTIME.enter();
25+
// SAFETY: self.client is never used again, which is the only requirement
26+
// for ManuallyDrop::drop to be used safely.
27+
unsafe {
28+
ManuallyDrop::drop(&mut self.client);
29+
}
30+
}
1331
}
1432

1533
#[matrix_sdk_ffi_macros::export]
1634
impl RoomPreview {
1735
/// Returns the room info the preview contains.
18-
pub fn info(&self) -> RoomPreviewInfo {
36+
pub fn info(&self) -> Result<RoomPreviewInfo, ClientError> {
1937
let info = &self.inner;
20-
RoomPreviewInfo {
38+
Ok(RoomPreviewInfo {
2139
room_id: info.room_id.to_string(),
2240
canonical_alias: info.canonical_alias.as_ref().map(|alias| alias.to_string()),
2341
name: info.name.clone(),
@@ -27,22 +45,28 @@ impl RoomPreview {
2745
room_type: info.room_type.as_ref().map(|room_type| room_type.to_string()),
2846
is_history_world_readable: info.is_world_readable,
2947
membership: info.state.map(|state| state.into()),
30-
join_rule: info.join_rule.clone().into(),
31-
}
48+
join_rule: info
49+
.join_rule
50+
.clone()
51+
.try_into()
52+
.map_err(|_| anyhow::anyhow!("unhandled SpaceRoomJoinRule kind"))?,
53+
})
3254
}
3355

3456
/// Leave the room if the room preview state is either joined, invited or
3557
/// knocked.
3658
///
3759
/// Will return an error otherwise.
3860
pub async fn leave(&self) -> Result<(), ClientError> {
39-
self.inner.leave().await.map_err(Into::into)
61+
let room =
62+
self.client.get_room(&self.inner.room_id).context("missing room for a room preview")?;
63+
room.leave().await.map_err(Into::into)
4064
}
4165
}
4266

4367
impl RoomPreview {
44-
pub(crate) fn from_sdk(room_preview: SdkRoomPreview) -> Self {
45-
Self { inner: Arc::new(room_preview) }
68+
pub(crate) fn new(client: ManuallyDrop<Client>, inner: SdkRoomPreview) -> Self {
69+
Self { client, inner }
4670
}
4771
}
4872

@@ -71,22 +95,22 @@ pub struct RoomPreviewInfo {
7195
pub join_rule: JoinRule,
7296
}
7397

74-
impl From<SpaceRoomJoinRule> for JoinRule {
75-
fn from(join_rule: SpaceRoomJoinRule) -> Self {
76-
match join_rule {
98+
impl TryFrom<SpaceRoomJoinRule> for JoinRule {
99+
type Error = ();
100+
101+
fn try_from(join_rule: SpaceRoomJoinRule) -> Result<Self, ()> {
102+
Ok(match join_rule {
77103
SpaceRoomJoinRule::Invite => JoinRule::Invite,
78104
SpaceRoomJoinRule::Knock => JoinRule::Knock,
79105
SpaceRoomJoinRule::Private => JoinRule::Private,
80106
SpaceRoomJoinRule::Restricted => JoinRule::Restricted { rules: Vec::new() },
81107
SpaceRoomJoinRule::KnockRestricted => JoinRule::KnockRestricted { rules: Vec::new() },
82108
SpaceRoomJoinRule::Public => JoinRule::Public,
109+
SpaceRoomJoinRule::_Custom(_) => JoinRule::Custom { repr: join_rule.to_string() },
83110
_ => {
84-
// Since we have no way to get the _Custom contents, assume it's private.
85-
// Warning! If new join rules are introduced we may be mapping wrong values
86-
// here, but there's no way to match
87-
// `SpaceRoomJoinRule::_Custom(_)` and have an exhaustive match.
88-
JoinRule::Private
111+
warn!("unhandled SpaceRoomJoinRule: {join_rule}");
112+
return Err(());
89113
}
90-
}
114+
})
91115
}
92116
}

crates/matrix-sdk/src/client/mod.rs

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ use ruma::{
5454
},
5555
filter::{create_filter::v3::Request as FilterUploadRequest, FilterDefinition},
5656
knock::knock_room,
57-
membership::{join_room_by_id, join_room_by_id_or_alias, leave_room},
57+
membership::{join_room_by_id, join_room_by_id_or_alias},
5858
room::create_room,
5959
session::login::v3::DiscoveryInfo,
6060
sync::sync_events,
@@ -1208,13 +1208,6 @@ impl Client {
12081208
Ok(Room::new(self.clone(), base_room))
12091209
}
12101210

1211-
/// Leave a room given its `RoomId`.
1212-
pub async fn leave_room(&self, room_id: &RoomId) -> Result<()> {
1213-
let request = leave_room::v3::Request::new(room_id.to_owned());
1214-
self.send(request, None).await?;
1215-
self.base_client().room_left(room_id).await.map_err(Into::into)
1216-
}
1217-
12181211
/// Search the homeserver's directory of public rooms.
12191212
///
12201213
/// Sends a request to "_matrix/client/r0/publicRooms", returns

crates/matrix-sdk/src/error.rs

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,7 @@ use serde_json::Error as JsonError;
4545
use thiserror::Error;
4646
use url::ParseError as UrlParseError;
4747

48-
use crate::{
49-
event_cache::EventCacheError, room_preview::WrongRoomPreviewState, store_locks::LockStoreError,
50-
};
48+
use crate::{event_cache::EventCacheError, store_locks::LockStoreError};
5149

5250
/// Result type of the matrix-sdk.
5351
pub type Result<T, E = Error> = std::result::Result<T, E>;
@@ -350,12 +348,6 @@ pub enum Error {
350348
#[error("wrong room state: {0}")]
351349
WrongRoomState(WrongRoomState),
352350

353-
/// Attempted to call a method on a room preview that requires the user to
354-
/// have a specific membership state in the room, but the membership
355-
/// state is different or none.
356-
#[error("wrong room state: {0}")]
357-
WrongRoomPreviewState(WrongRoomPreviewState),
358-
359351
/// Session callbacks have been set multiple times.
360352
#[error("session callbacks have been set multiple times")]
361353
MultipleSessionCallbacks,

crates/matrix-sdk/src/room_preview.rs

Lines changed: 10 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ use ruma::{
2929
use tokio::try_join;
3030
use tracing::{instrument, warn};
3131

32-
use crate::{Client, Error, Room};
32+
use crate::{Client, Room};
3333

3434
/// The preview of a room, be it invited/joined/left, or not.
3535
#[derive(Debug, Clone)]
@@ -72,43 +72,20 @@ pub struct RoomPreview {
7272

7373
/// The `m.room.direct` state of the room, if known.
7474
pub is_direct: Option<bool>,
75-
76-
/// The [`Client`] that can be used to perform actions given the room
77-
/// preview.
78-
pub(crate) client: Client,
7975
}
8076

8177
impl RoomPreview {
82-
/// Leave a room using its [`RoomPreview`].
83-
pub async fn leave(&self) -> Result<(), Error> {
84-
match self.state {
85-
Some(RoomState::Left) | None => {
86-
Err(Error::WrongRoomPreviewState(WrongRoomPreviewState {
87-
expected: "Invited, Knocked or Joined",
88-
got: self.state,
89-
}))
90-
}
91-
Some(_) => self.client.leave_room(&self.room_id).await.map_err(Into::into),
92-
}
93-
}
94-
9578
/// Constructs a [`RoomPreview`] from the associated room info.
9679
///
9780
/// Note: not using the room info's state/count of joined members, because
9881
/// we can do better than that.
99-
async fn from_room_info(
100-
client: &Client,
82+
fn from_room_info(
10183
room_info: RoomInfo,
84+
is_direct: Option<bool>,
10285
num_joined_members: u64,
10386
state: Option<RoomState>,
10487
) -> Self {
105-
let is_direct = if let Some(room) = client.get_room(room_info.room_id()) {
106-
room.is_direct().await.ok()
107-
} else {
108-
None
109-
};
11088
RoomPreview {
111-
client: client.clone(),
11289
room_id: room_info.room_id().to_owned(),
11390
canonical_alias: room_info.canonical_alias().map(ToOwned::to_owned),
11491
name: room_info.name().map(ToOwned::to_owned),
@@ -138,13 +115,14 @@ impl RoomPreview {
138115
/// Create a room preview from a known room (i.e. one we've been invited to,
139116
/// we've joined or we've left).
140117
pub(crate) async fn from_known(room: &Room) -> Self {
118+
let is_direct = room.is_direct().await.ok();
119+
141120
Self::from_room_info(
142-
&room.client,
143121
room.clone_info(),
122+
is_direct,
144123
room.joined_members_count(),
145124
Some(room.state()),
146125
)
147-
.await
148126
}
149127

150128
#[instrument(skip(client))]
@@ -207,7 +185,6 @@ impl RoomPreview {
207185
};
208186

209187
Ok(RoomPreview {
210-
client: client.clone(),
211188
room_id,
212189
canonical_alias: response.canonical_alias,
213190
name: response.name,
@@ -259,23 +236,10 @@ impl RoomPreview {
259236
room_info.handle_state_event(&ev.into());
260237
}
261238

262-
let state = client.get_room(room_id).map(|room| room.state());
263-
264-
Ok(Self::from_room_info(client, room_info, num_joined_members, state).await)
265-
}
266-
}
267-
268-
/// An unexpected room preview state was found.
269-
#[derive(Debug, thiserror::Error)]
270-
#[error("expected: {expected}, got: {got:?}")]
271-
pub struct WrongRoomPreviewState {
272-
expected: &'static str,
273-
got: Option<RoomState>,
274-
}
239+
let room = client.get_room(room_id);
240+
let state = room.as_ref().map(|room| room.state());
241+
let is_direct = if let Some(room) = room { room.is_direct().await.ok() } else { None };
275242

276-
impl WrongRoomPreviewState {
277-
/// Instantiate a new
278-
pub fn new(expected: &'static str, got: Option<RoomState>) -> Self {
279-
Self { expected, got }
243+
Ok(Self::from_room_info(room_info, is_direct, num_joined_members, state))
280244
}
281245
}

0 commit comments

Comments
 (0)