Skip to content

Commit 80b7749

Browse files
authored
Drop dependency on anyhow (#241)
Preparation for upgrading to matrix-rust-sdk 0.12.0. As of matrix-org/matrix-rust-sdk#5082, some of the the errors returned by the rust SDK are no longer Send + Sync. That means we can no longer pass them into anyhow::Error::from(). As it turns out, most of our uses of anyhow::Error are redundant anyway. This patch set (review commit-by-commit) removes the places we use anyhow::Error, and means that we will be able to build against rust-sdk 0.12.0. Fixes: #232
2 parents 4ad5fcb + f50742b commit 80b7749

File tree

8 files changed

+62
-52
lines changed

8 files changed

+62
-52
lines changed

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,6 @@ default = ["qrcode"]
5858
qrcode = ["matrix-sdk-crypto/qrcode", "dep:matrix-sdk-qrcode"]
5959

6060
[dependencies]
61-
anyhow = "1.0.68"
6261
console_error_panic_hook = "0.1.7"
6362
futures-util = "0.3.27"
6463
# getrandom is not a direct dependency, but we need to enable the "wasm_js" backend.
@@ -71,6 +70,7 @@ matrix-sdk-qrcode = { git = "https://github.com/matrix-org/matrix-rust-sdk", rev
7170
serde = "1.0.91"
7271
serde_json = "1.0.91"
7372
serde-wasm-bindgen = "0.6.5"
73+
thiserror = "2.0.12"
7474
tracing = { version = "0.1.36", default-features = false, features = ["std"] }
7575
tracing-subscriber = { version = "0.3.14", default-features = false, features = ["registry", "std", "ansi"] }
7676
url = "2.5.0"

src/future.rs

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,29 @@
11
use std::future::Future;
22

3-
use futures_util::TryFutureExt;
43
use js_sys::Promise;
54
use wasm_bindgen::{JsError, JsValue, UnwrapThrowExt};
65
use wasm_bindgen_futures::spawn_local;
76

7+
/**
8+
* Convert a Rust [`Future`] which returns [`Result<T, JsError>`] into a
9+
* Javascript [`Promise`] which either resolves with an object of type `T`,
10+
* or rejects with an error of type [`Error`].
11+
*
12+
* [`Error`]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error
13+
*/
814
pub(crate) fn future_to_promise<F, T>(future: F) -> Promise
915
where
10-
F: Future<Output = Result<T, anyhow::Error>> + 'static,
16+
F: Future<Output = Result<T, JsError>> + 'static,
1117
T: Into<JsValue>,
1218
{
13-
future_to_promise_with_custom_error(future.map_err(|error| JsError::new(&error.to_string())))
19+
future_to_promise_with_custom_error(future)
1420
}
1521

22+
/**
23+
* Convert a Rust [`Future`] which returns [`Result<T, E>`] into a
24+
* Javascript [`Promise`] which either resolves with an object of type `T`,
25+
* or rejects with an error of type `E`.
26+
*/
1627
pub(crate) fn future_to_promise_with_custom_error<F, T, E>(future: F) -> Promise
1728
where
1829
F: Future<Output = Result<T, E>> + 'static,

src/libolm_migration.rs

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
1717
use std::time::Duration;
1818

19-
use anyhow::Context;
2019
use js_sys::{Date, Uint8Array};
2120
use matrix_sdk_common::ruma::{
2221
DeviceKeyAlgorithm, MilliSecondsSinceUnixEpoch, SecondsSinceUnixEpoch, UInt,
@@ -120,8 +119,7 @@ impl Migration {
120119
store_handle: &StoreHandle,
121120
) -> Result<JsValue, JsError> {
122121
migrate_base_data_to_store(data, &(pickle_key.to_vec()), store_handle.store.as_ref())
123-
.await
124-
.map_err(|e| JsError::from(&*e))?;
122+
.await?;
125123
Ok(JsValue::UNDEFINED)
126124
}
127125
}
@@ -130,13 +128,13 @@ async fn migrate_base_data_to_store(
130128
data: &BaseMigrationData,
131129
pickle_key: &[u8],
132130
store: &DynCryptoStore,
133-
) -> anyhow::Result<()> {
134-
let user_id = data.user_id.clone().context("User ID not specified")?.inner;
131+
) -> Result<(), JsError> {
132+
let user_id = data.user_id.clone().ok_or(JsError::new("User ID not specified"))?.inner;
135133
let account = vodozemac::olm::Account::from_libolm_pickle(&data.pickled_account, pickle_key)?;
136134
let account =
137135
matrix_sdk_crypto::olm::Account::from_pickle(matrix_sdk_crypto::olm::PickledAccount {
138136
user_id: user_id.clone(),
139-
device_id: data.device_id.clone().context("Device ID not specified")?.inner,
137+
device_id: data.device_id.clone().ok_or(JsError::new("Device ID not specified"))?.inner,
140138
pickle: account.pickle(),
141139
// Legacy crypto in the js-sdk does not keep a record of whether it has published the
142140
// device keys to the server (it does it every time the stack is started). For safety,
@@ -253,9 +251,7 @@ impl Migration {
253251
.map(|session| libolm_pickled_session_to_rust_pickled_session(session, &pickle_key))
254252
.collect::<Result<_>>()?;
255253

256-
import_olm_sessions_to_store(rust_sessions, store_handle.store.as_ref())
257-
.await
258-
.map_err(|e| JsError::from(&*e))?;
254+
import_olm_sessions_to_store(rust_sessions, store_handle.store.as_ref()).await?;
259255
Ok(JsValue::UNDEFINED)
260256
}
261257
}
@@ -295,11 +291,11 @@ fn libolm_pickled_session_to_rust_pickled_session(
295291
async fn import_olm_sessions_to_store(
296292
pickled_sessions: Vec<matrix_sdk_crypto::olm::PickledSession>,
297293
store: &DynCryptoStore,
298-
) -> anyhow::Result<()> {
294+
) -> Result<(), JsError> {
299295
let account = store
300296
.load_account()
301297
.await?
302-
.context("Base data must be imported before calling `migrateOlmSessions`")?;
298+
.ok_or(JsError::new("Base data must be imported before calling `migrateOlmSessions`"))?;
303299

304300
let sessions = pickled_sessions
305301
.into_iter()
@@ -409,9 +405,7 @@ impl Migration {
409405
})
410406
.collect::<Result<_>>()?;
411407

412-
import_megolm_sessions_to_store(rust_sessions, store_handle.store.as_ref())
413-
.await
414-
.map_err(|e| JsError::from(&*e))?;
408+
import_megolm_sessions_to_store(rust_sessions, store_handle.store.as_ref()).await?;
415409
Ok(JsValue::UNDEFINED)
416410
}
417411
}
@@ -455,7 +449,7 @@ fn libolm_pickled_megolm_session_to_rust_pickled_session(
455449
async fn import_megolm_sessions_to_store(
456450
pickled_sessions: Vec<matrix_sdk_crypto::olm::PickledInboundGroupSession>,
457451
store: &DynCryptoStore,
458-
) -> anyhow::Result<()> {
452+
) -> Result<(), JsError> {
459453
let inbound_group_sessions = pickled_sessions
460454
.into_iter()
461455
.map(matrix_sdk_crypto::olm::InboundGroupSession::from_pickle)

src/machine.rs

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ use crate::{
3838
future::{future_to_promise, future_to_promise_with_custom_error},
3939
identifiers, identities, olm, requests,
4040
requests::{outgoing_request_to_js_value, CrossSigningBootstrapRequests, ToDeviceRequest},
41-
responses::{self, response_from_string},
41+
responses::{self, response_from_string, UnsupportedAlgorithmError},
4242
store,
4343
store::{RoomKeyInfo, RoomKeyWithheldInfo, StoreHandle},
4444
sync_events,
@@ -99,9 +99,7 @@ impl OlmMachine {
9999
let user_id = user_id.inner.clone();
100100
let device_id = device_id.inner.clone();
101101

102-
let store_handle = StoreHandle::open(store_name, store_passphrase)
103-
.await
104-
.map_err(|e| JsError::from(&*e))?;
102+
let store_handle = StoreHandle::open(store_name, store_passphrase).await?;
105103
Self::init_helper(user_id, device_id, store_handle).await
106104
}
107105

@@ -513,13 +511,15 @@ impl OlmMachine {
513511
.map_err(MegolmDecryptionError::from)?
514512
.into();
515513

516-
responses::DecryptedRoomEvent::try_from(room_event).map_err(|e: anyhow::Error| {
517-
// This happens if we somehow encounter a room event whose encryption info we
518-
// don't understand (e.g., it is encrypted with Olm rather than
519-
// Megolm). That seems pretty unlikely. If it happens, let's
520-
// just treat it as a generic UTD.
521-
MegolmDecryptionError::unable_to_decrypt(format!("{e:#}"))
522-
})
514+
responses::DecryptedRoomEvent::try_from(room_event).map_err(
515+
|e: UnsupportedAlgorithmError| {
516+
// This happens if we somehow encounter a room event whose encryption info we
517+
// don't understand (e.g., it is encrypted with Olm rather than
518+
// Megolm). That seems pretty unlikely. If it happens, let's
519+
// just treat it as a generic UTD.
520+
MegolmDecryptionError::unable_to_decrypt(format!("{e:#}"))
521+
},
522+
)
523523
}))
524524
}
525525

@@ -979,7 +979,7 @@ impl OlmMachine {
979979
let me = self.inner.clone();
980980

981981
future_to_promise(async move {
982-
stream_to_json_array(pin!(
982+
Ok(stream_to_json_array(pin!(
983983
me.store()
984984
.export_room_keys_stream(|session| {
985985
let session = session.clone();
@@ -992,7 +992,7 @@ impl OlmMachine {
992992
})
993993
.await?,
994994
))
995-
.await
995+
.await?)
996996
})
997997
}
998998

@@ -1696,7 +1696,7 @@ pub(crate) async fn promise_result_to_future(
16961696
}
16971697
}
16981698

1699-
async fn stream_to_json_array<T, S>(mut stream: Pin<&mut S>) -> Result<String, anyhow::Error>
1699+
async fn stream_to_json_array<T, S>(mut stream: Pin<&mut S>) -> Result<String, serde_json::Error>
17001700
where
17011701
T: Serialize,
17021702
S: Stream<Item = T>,
@@ -1709,5 +1709,5 @@ where
17091709
}
17101710
seq.end()?;
17111711

1712-
Ok(String::from_utf8(stream_json)?)
1712+
Ok(String::from_utf8(stream_json).expect("serde_json generated invalid UTF8"))
17131713
}

src/responses.rs

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
33
use std::sync::Arc;
44

5-
use anyhow::anyhow;
65
use js_sys::{Array, JsString};
76
pub(crate) use matrix_sdk_common::ruma::api::client::{
87
backup::add_backup_keys::v3::Response as KeysBackupResponse,
@@ -19,6 +18,7 @@ use matrix_sdk_common::{
1918
ruma::{self, api::IncomingResponse as RumaIncomingResponse},
2019
};
2120
use matrix_sdk_crypto::types::requests::AnyIncomingResponse;
21+
use thiserror::Error;
2222
use wasm_bindgen::prelude::*;
2323

2424
use crate::{encryption, identifiers, requests::RequestType};
@@ -216,7 +216,7 @@ impl DecryptedRoomEvent {
216216
}
217217

218218
impl TryFrom<matrix_sdk_common::deserialized_responses::TimelineEvent> for DecryptedRoomEvent {
219-
type Error = anyhow::Error;
219+
type Error = UnsupportedAlgorithmError;
220220

221221
fn try_from(
222222
value: matrix_sdk_common::deserialized_responses::TimelineEvent,
@@ -288,7 +288,7 @@ impl EncryptionInfo {
288288
}
289289

290290
impl TryFrom<Arc<matrix_sdk_common::deserialized_responses::EncryptionInfo>> for EncryptionInfo {
291-
type Error = anyhow::Error;
291+
type Error = UnsupportedAlgorithmError;
292292

293293
fn try_from(
294294
value: Arc<matrix_sdk_common::deserialized_responses::EncryptionInfo>,
@@ -306,8 +306,8 @@ impl TryFrom<Arc<matrix_sdk_common::deserialized_responses::EncryptionInfo>> for
306306
verification_state: value.verification_state.clone(),
307307
})
308308
}
309-
AlgorithmInfo::OlmV1Curve25519AesSha2 { .. } => Err(anyhow!(
310-
"AlgorithmInfo::OlmV1Curve25519AesSha2 is not applicable for room event EncryptionInfo",
309+
AlgorithmInfo::OlmV1Curve25519AesSha2 { .. } => Err(UnsupportedAlgorithmError(
310+
"AlgorithmInfo::OlmV1Curve25519AesSha2 is not applicable for room event EncryptionInfo".to_owned()
311311
)),
312312
}
313313
}
@@ -344,14 +344,15 @@ pub struct ToDeviceEncryptionInfo {
344344
}
345345

346346
impl TryFrom<matrix_sdk_common::deserialized_responses::EncryptionInfo> for ToDeviceEncryptionInfo {
347-
type Error = anyhow::Error;
347+
type Error = UnsupportedAlgorithmError;
348348

349349
fn try_from(
350350
value: matrix_sdk_common::deserialized_responses::EncryptionInfo,
351351
) -> Result<Self, Self::Error> {
352352
match &value.algorithm_info {
353-
AlgorithmInfo::MegolmV1AesSha2 { .. } => Err(anyhow!(
354-
"AlgorithmInfo::MegolmV1AesSha2 is not applicable for ToDeviceEncryptionInfo",
353+
AlgorithmInfo::MegolmV1AesSha2 { .. } => Err(UnsupportedAlgorithmError(
354+
"AlgorithmInfo::MegolmV1AesSha2 is not applicable for ToDeviceEncryptionInfo"
355+
.to_owned(),
355356
)),
356357
AlgorithmInfo::OlmV1Curve25519AesSha2 { curve25519_public_key_base64 } => Ok(Self {
357358
sender_curve25519_key_base64: curve25519_public_key_base64.clone(),
@@ -375,3 +376,11 @@ impl ToDeviceEncryptionInfo {
375376
)
376377
}
377378
}
379+
380+
/// Error type returned when converting
381+
/// [`matrix_sdk_common::deserialized_responses::EncryptionInfo`] to one of our
382+
/// own types: the `algorithm_info` on the `EncryptionInfo` was of an unexpected
383+
/// type.
384+
#[derive(Error, Debug)]
385+
#[error("{0}")]
386+
pub struct UnsupportedAlgorithmError(String);

src/store.rs

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
33
use std::sync::Arc;
44

5-
use anyhow::Context;
65
use matrix_sdk_crypto::{
76
store::{DynCryptoStore, IntoCryptoStore, MemoryStore},
87
types::BackupSecrets,
@@ -50,19 +49,19 @@ impl StoreHandle {
5049
store_name: Option<String>,
5150
store_passphrase: Option<String>,
5251
) -> Result<StoreHandle, JsError> {
53-
StoreHandle::open(store_name, store_passphrase).await.map_err(|e| JsError::from(&*e))
52+
StoreHandle::open(store_name, store_passphrase).await
5453
}
5554

5655
pub(crate) async fn open(
5756
store_name: Option<String>,
5857
store_passphrase: Option<String>,
59-
) -> Result<StoreHandle, anyhow::Error> {
58+
) -> Result<StoreHandle, JsError> {
6059
let store = match store_name {
6160
Some(store_name) => Self::open_indexeddb(&store_name, store_passphrase).await?,
6261

6362
None => {
6463
if store_passphrase.is_some() {
65-
return Err(anyhow::Error::msg(
64+
return Err(JsError::new(
6665
"The `store_passphrase` has been set, but it has an effect only if \
6766
`store_name` is set, which is not; please provide one",
6867
));
@@ -118,8 +117,7 @@ impl StoreHandle {
118117
store_key
119118
.as_slice()
120119
.try_into()
121-
.with_context(|| "Expected a key of length 32")
122-
.map_err(|e| JsError::from(&*e))?,
120+
.map_err(|_| JsError::new("Expected a key of length 32"))?,
123121
);
124122
store_key.zeroize();
125123

src/verification.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1034,9 +1034,7 @@ impl VerificationRequest {
10341034
.transpose()
10351035
{
10361036
Ok(a) => Ok(a),
1037-
Err(_) => {
1038-
Err(anyhow::Error::msg("Failed to build the outgoing verification request"))
1039-
}
1037+
Err(_) => Err(JsError::new("Failed to build the outgoing verification request")),
10401038
}
10411039
})
10421040
}

0 commit comments

Comments
 (0)