atagen

macltok

public
Star0
Watch0
038cc6faeb1429501e5cd06596b831bbd2044b92
3
ssh://brewery@pls.lobotomise.me:33/atagen/macltok.git

Blame: src/error.rs

31ce2453c82fatagen2026-09-24 13:07 UTC1
use std::sync::Arc;
96fdf90aacd6atagen2026-09-08 08:24 UTC2
96fdf90aacd6atagen2026-09-08 08:24 UTC3
use matrix_sdk::{
1fe480c16a3catagen2026-09-26 08:44 UTC4
    HttpError, RefreshTokenError, SendOutsideWasm, SyncOutsideWasm,
96fdf90aacd6atagen2026-09-08 08:24 UTC5
    authentication::oauth::error::{
96fdf90aacd6atagen2026-09-08 08:24 UTC6
        OAuthAuthorizationCodeError, OAuthDiscoveryError, OAuthError, OAuthTokenRevocationError,
96fdf90aacd6atagen2026-09-08 08:24 UTC7
        RequestTokenError,
96fdf90aacd6atagen2026-09-08 08:24 UTC8
    },
96fdf90aacd6atagen2026-09-08 08:24 UTC9
    encryption::{
96fdf90aacd6atagen2026-09-08 08:24 UTC10
        identities::{ManualVerifyError, RequestVerificationError},
96fdf90aacd6atagen2026-09-08 08:24 UTC11
        recovery::RecoveryError,
96fdf90aacd6atagen2026-09-08 08:24 UTC12
        secret_storage::{ImportError, SecretStorageError},
96fdf90aacd6atagen2026-09-08 08:24 UTC13
    },
96fdf90aacd6atagen2026-09-08 08:24 UTC14
};
31ce2453c82fatagen2026-09-24 13:07 UTC15
#[cfg(feature = "serde")]
31ce2453c82fatagen2026-09-24 13:07 UTC16
use serde::{Deserialize, Serialize};
96fdf90aacd6atagen2026-09-08 08:24 UTC17
31ce2453c82fatagen2026-09-24 13:07 UTC18
use crate::InteractiveAuthChallenge;
96fdf90aacd6atagen2026-09-08 08:24 UTC19
1fe480c16a3catagen2026-09-26 08:44 UTC20
/// the sdk's `SendOutsideWasm` isn't an auto trait, so it can't go in a trait object
1fe480c16a3catagen2026-09-26 08:44 UTC21
#[cfg(not(target_family = "wasm"))]
62fe32759529atagen2026-09-26 08:50 UTC22
pub(crate) type SourceError = dyn std::error::Error + Send + Sync;
1fe480c16a3catagen2026-09-26 08:44 UTC23
#[cfg(target_family = "wasm")]
62fe32759529atagen2026-09-26 08:50 UTC24
pub(crate) type SourceError = dyn std::error::Error;
1fe480c16a3catagen2026-09-26 08:44 UTC25
31ce2453c82fatagen2026-09-24 13:07 UTC26
/// the one thing that goes wrong, for commands and queries alike. match on `kind`, show `message`
31ce2453c82fatagen2026-09-24 13:07 UTC27
#[derive(Clone, Debug, thiserror::Error)]
31ce2453c82fatagen2026-09-24 13:07 UTC28
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
96fdf90aacd6atagen2026-09-08 08:24 UTC29
#[error("{message}")]
31ce2453c82fatagen2026-09-24 13:07 UTC30
#[non_exhaustive]
31ce2453c82fatagen2026-09-24 13:07 UTC31
pub struct Error {
31ce2453c82fatagen2026-09-24 13:07 UTC32
    pub kind: ErrorKind,
31ce2453c82fatagen2026-09-24 13:07 UTC33
    pub message: String,
31ce2453c82fatagen2026-09-24 13:07 UTC34
    /// set when the server wants interactive auth before it'll do the thing
31ce2453c82fatagen2026-09-24 13:07 UTC35
    pub challenge: Option<Box<InteractiveAuthChallenge>>,
9a25b6ce66f4atagen2026-10-08 11:15 UTC36
    /// set when the homeserver refused with a matrix error
9a25b6ce66f4atagen2026-10-08 11:15 UTC37
    pub server: Option<ServerError>,
96fdf90aacd6atagen2026-09-08 08:24 UTC38
    #[source]
31ce2453c82fatagen2026-09-24 13:07 UTC39
    #[cfg_attr(feature = "serde", serde(skip))]
1fe480c16a3catagen2026-09-26 08:44 UTC40
    source: Option<Arc<SourceError>>,
96fdf90aacd6atagen2026-09-08 08:24 UTC41
}
96fdf90aacd6atagen2026-09-08 08:24 UTC42
31ce2453c82fatagen2026-09-24 13:07 UTC43
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
31ce2453c82fatagen2026-09-24 13:07 UTC44
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
31ce2453c82fatagen2026-09-24 13:07 UTC45
pub enum ErrorKind {
31ce2453c82fatagen2026-09-24 13:07 UTC46
    /// the engine stopped, or the task doing the work died, before answering
31ce2453c82fatagen2026-09-24 13:07 UTC47
    Interrupted,
31ce2453c82fatagen2026-09-24 13:07 UTC48
    Unauthenticated,
31ce2453c82fatagen2026-09-24 13:07 UTC49
    InteractiveAuthRequired,
31ce2453c82fatagen2026-09-24 13:07 UTC50
    Invalid,
9bd34e25bb86atagen2026-10-24 07:23 UTC51
    /// the room's power levels don't let you
9bd34e25bb86atagen2026-10-24 07:23 UTC52
    Forbidden,
31ce2453c82fatagen2026-09-24 13:07 UTC53
    RoomUnknown,
31ce2453c82fatagen2026-09-24 13:07 UTC54
    RoomNotOpen,
31ce2453c82fatagen2026-09-24 13:07 UTC55
    TimelineNotOpen,
da8896938cf0atagen2026-10-25 10:04 UTC56
    EventContextNotOpen,
c9effeac326aatagen2026-10-25 10:32 UTC57
    SearchNotOpen,
89bc9f8d246datagen2026-10-24 13:40 UTC58
    EventNotFound,
31ce2453c82fatagen2026-09-24 13:07 UTC59
    RoomBusy,
31ce2453c82fatagen2026-09-24 13:07 UTC60
    QueueFull,
31ce2453c82fatagen2026-09-24 13:07 UTC61
    EmptyBody,
31ce2453c82fatagen2026-09-24 13:07 UTC62
    MediaUnknown,
31ce2453c82fatagen2026-09-24 13:07 UTC63
    MediaTooLarge,
31ce2453c82fatagen2026-09-24 13:07 UTC64
    MediaUnavailable,
31ce2453c82fatagen2026-09-24 13:07 UTC65
    VerificationInactive,
31ce2453c82fatagen2026-09-24 13:07 UTC66
    VerificationUnsupported,
31ce2453c82fatagen2026-09-24 13:07 UTC67
    NoCrossSigningIdentity,
31ce2453c82fatagen2026-09-24 13:07 UTC68
    RecoveryRejected,
31ce2453c82fatagen2026-09-24 13:07 UTC69
    Network,
0291516d40b5atagen2026-10-22 08:31 UTC70
    /// the homeserver wants us to slow down. try again later
0291516d40b5atagen2026-10-22 08:31 UTC71
    RateLimited,
31ce2453c82fatagen2026-09-24 13:07 UTC72
    Server,
31ce2453c82fatagen2026-09-24 13:07 UTC73
    Store,
31ce2453c82fatagen2026-09-24 13:07 UTC74
    Timeline,
31ce2453c82fatagen2026-09-24 13:07 UTC75
    Encryption,
31ce2453c82fatagen2026-09-24 13:07 UTC76
    Other,
31ce2453c82fatagen2026-09-24 13:07 UTC77
}
31ce2453c82fatagen2026-09-24 13:07 UTC78
9a25b6ce66f4atagen2026-10-08 11:15 UTC79
/// the homeserver's own answer, worth showing a person as it stands
9a25b6ce66f4atagen2026-10-08 11:15 UTC80
#[derive(Clone, Debug, Eq, PartialEq)]
9a25b6ce66f4atagen2026-10-08 11:15 UTC81
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9a25b6ce66f4atagen2026-10-08 11:15 UTC82
#[non_exhaustive]
9a25b6ce66f4atagen2026-10-08 11:15 UTC83
pub struct ServerError {
9a25b6ce66f4atagen2026-10-08 11:15 UTC84
    pub status: u16,
9a25b6ce66f4atagen2026-10-08 11:15 UTC85
    pub errcode: String,
9a25b6ce66f4atagen2026-10-08 11:15 UTC86
    pub message: String,
9a25b6ce66f4atagen2026-10-08 11:15 UTC87
}
9a25b6ce66f4atagen2026-10-08 11:15 UTC88
9a25b6ce66f4atagen2026-10-08 11:15 UTC89
impl ServerError {
9a25b6ce66f4atagen2026-10-08 11:15 UTC90
    pub(crate) fn find(source: &(dyn std::error::Error + 'static)) -> Option<Self> {
9a25b6ce66f4atagen2026-10-08 11:15 UTC91
        let mut current = Some(source);
9a25b6ce66f4atagen2026-10-08 11:15 UTC92
        while let Some(error) = current {
9a25b6ce66f4atagen2026-10-08 11:15 UTC93
            let api = if let Some(error) = error.downcast_ref::<matrix_sdk::Error>() {
9a25b6ce66f4atagen2026-10-08 11:15 UTC94
                error.as_client_api_error()
9a25b6ce66f4atagen2026-10-08 11:15 UTC95
            } else if let Some(error) = error.downcast_ref::<HttpError>() {
9a25b6ce66f4atagen2026-10-08 11:15 UTC96
                error.as_client_api_error()
9a25b6ce66f4atagen2026-10-08 11:15 UTC97
            } else {
9a25b6ce66f4atagen2026-10-08 11:15 UTC98
                error.downcast_ref::<ruma::api::error::Error>()
9a25b6ce66f4atagen2026-10-08 11:15 UTC99
            };
9a25b6ce66f4atagen2026-10-08 11:15 UTC100
            if let Some(api) = api
9a25b6ce66f4atagen2026-10-08 11:15 UTC101
                && let ruma::api::error::ErrorBody::Standard(body) = &api.body
9a25b6ce66f4atagen2026-10-08 11:15 UTC102
            {
9a25b6ce66f4atagen2026-10-08 11:15 UTC103
                return Some(Self {
9a25b6ce66f4atagen2026-10-08 11:15 UTC104
                    status: api.status_code.as_u16(),
9a25b6ce66f4atagen2026-10-08 11:15 UTC105
                    errcode: body.kind.errcode().to_string(),
9a25b6ce66f4atagen2026-10-08 11:15 UTC106
                    message: body.message.clone(),
9a25b6ce66f4atagen2026-10-08 11:15 UTC107
                });
9a25b6ce66f4atagen2026-10-08 11:15 UTC108
            }
9a25b6ce66f4atagen2026-10-08 11:15 UTC109
            current = error.source();
9a25b6ce66f4atagen2026-10-08 11:15 UTC110
        }
9a25b6ce66f4atagen2026-10-08 11:15 UTC111
        None
9a25b6ce66f4atagen2026-10-08 11:15 UTC112
    }
9a25b6ce66f4atagen2026-10-08 11:15 UTC113
}
9a25b6ce66f4atagen2026-10-08 11:15 UTC114
9a25b6ce66f4atagen2026-10-08 11:15 UTC115
impl std::fmt::Display for ServerError {
9a25b6ce66f4atagen2026-10-08 11:15 UTC116
    fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
9a25b6ce66f4atagen2026-10-08 11:15 UTC117
        write!(formatter, "{} ({})", self.message, self.errcode)
9a25b6ce66f4atagen2026-10-08 11:15 UTC118
    }
9a25b6ce66f4atagen2026-10-08 11:15 UTC119
}
9a25b6ce66f4atagen2026-10-08 11:15 UTC120
9a25b6ce66f4atagen2026-10-08 11:15 UTC121
#[cfg(any(feature = "sqlite", feature = "indexeddb"))]
9a25b6ce66f4atagen2026-10-08 11:15 UTC122
pub(crate) fn classify(source: &(dyn std::error::Error + 'static)) -> ErrorKind {
9a25b6ce66f4atagen2026-10-08 11:15 UTC123
    let mut current = Some(source);
9a25b6ce66f4atagen2026-10-08 11:15 UTC124
    while let Some(error) = current {
9a25b6ce66f4atagen2026-10-08 11:15 UTC125
        if let Some(error) = error.downcast_ref::<matrix_sdk::Error>() {
9a25b6ce66f4atagen2026-10-08 11:15 UTC126
            return classify_sdk_error(error);
9a25b6ce66f4atagen2026-10-08 11:15 UTC127
        }
9a25b6ce66f4atagen2026-10-08 11:15 UTC128
        if let Some(error) = error.downcast_ref::<HttpError>() {
9a25b6ce66f4atagen2026-10-08 11:15 UTC129
            return classify_http_error(error);
9a25b6ce66f4atagen2026-10-08 11:15 UTC130
        }
9a25b6ce66f4atagen2026-10-08 11:15 UTC131
        if let Some(error) = error.downcast_ref::<OAuthError>() {
9a25b6ce66f4atagen2026-10-08 11:15 UTC132
            return classify_oauth_error(error);
9a25b6ce66f4atagen2026-10-08 11:15 UTC133
        }
9a25b6ce66f4atagen2026-10-08 11:15 UTC134
        if let Some(error) = error.downcast_ref::<RefreshTokenError>() {
9a25b6ce66f4atagen2026-10-08 11:15 UTC135
            return classify_refresh_token_error(error);
9a25b6ce66f4atagen2026-10-08 11:15 UTC136
        }
9a25b6ce66f4atagen2026-10-08 11:15 UTC137
        current = error.source();
9a25b6ce66f4atagen2026-10-08 11:15 UTC138
    }
9a25b6ce66f4atagen2026-10-08 11:15 UTC139
    ErrorKind::Other
9a25b6ce66f4atagen2026-10-08 11:15 UTC140
}
9a25b6ce66f4atagen2026-10-08 11:15 UTC141
31ce2453c82fatagen2026-09-24 13:07 UTC142
impl Error {
31ce2453c82fatagen2026-09-24 13:07 UTC143
    pub(crate) fn new(kind: ErrorKind, message: impl Into<String>) -> Self {
96fdf90aacd6atagen2026-09-08 08:24 UTC144
        Self {
96fdf90aacd6atagen2026-09-08 08:24 UTC145
            kind,
96fdf90aacd6atagen2026-09-08 08:24 UTC146
            message: message.into(),
31ce2453c82fatagen2026-09-24 13:07 UTC147
            challenge: None,
9a25b6ce66f4atagen2026-10-08 11:15 UTC148
            server: None,
96fdf90aacd6atagen2026-09-08 08:24 UTC149
            source: None,
96fdf90aacd6atagen2026-09-08 08:24 UTC150
        }
96fdf90aacd6atagen2026-09-08 08:24 UTC151
    }
96fdf90aacd6atagen2026-09-08 08:24 UTC152
96fdf90aacd6atagen2026-09-08 08:24 UTC153
    pub(crate) fn with_source(
31ce2453c82fatagen2026-09-24 13:07 UTC154
        kind: ErrorKind,
96fdf90aacd6atagen2026-09-08 08:24 UTC155
        message: impl Into<String>,
1fe480c16a3catagen2026-09-26 08:44 UTC156
        source: impl std::error::Error + SendOutsideWasm + SyncOutsideWasm + 'static,
96fdf90aacd6atagen2026-09-08 08:24 UTC157
    ) -> Self {
96fdf90aacd6atagen2026-09-08 08:24 UTC158
        Self {
9a25b6ce66f4atagen2026-10-08 11:15 UTC159
            server: ServerError::find(&source),
31ce2453c82fatagen2026-09-24 13:07 UTC160
            source: Some(Arc::new(source)),
31ce2453c82fatagen2026-09-24 13:07 UTC161
            ..Self::new(kind, message)
31ce2453c82fatagen2026-09-24 13:07 UTC162
        }
31ce2453c82fatagen2026-09-24 13:07 UTC163
    }
31ce2453c82fatagen2026-09-24 13:07 UTC164
31ce2453c82fatagen2026-09-24 13:07 UTC165
    pub(crate) fn interrupted() -> Self {
31ce2453c82fatagen2026-09-24 13:07 UTC166
        Self::new(
31ce2453c82fatagen2026-09-24 13:07 UTC167
            ErrorKind::Interrupted,
31ce2453c82fatagen2026-09-24 13:07 UTC168
            "the engine stopped before the operation finished",
31ce2453c82fatagen2026-09-24 13:07 UTC169
        )
31ce2453c82fatagen2026-09-24 13:07 UTC170
    }
31ce2453c82fatagen2026-09-24 13:07 UTC171
31ce2453c82fatagen2026-09-24 13:07 UTC172
    pub(crate) fn room_unknown() -> Self {
31ce2453c82fatagen2026-09-24 13:07 UTC173
        Self::new(
31ce2453c82fatagen2026-09-24 13:07 UTC174
            ErrorKind::RoomUnknown,
31ce2453c82fatagen2026-09-24 13:07 UTC175
            "room is not available in the local store",
31ce2453c82fatagen2026-09-24 13:07 UTC176
        )
31ce2453c82fatagen2026-09-24 13:07 UTC177
    }
31ce2453c82fatagen2026-09-24 13:07 UTC178
31ce2453c82fatagen2026-09-24 13:07 UTC179
    pub(crate) fn interactive_auth(challenge: InteractiveAuthChallenge) -> Self {
31ce2453c82fatagen2026-09-24 13:07 UTC180
        Self {
31ce2453c82fatagen2026-09-24 13:07 UTC181
            challenge: Some(Box::new(challenge)),
31ce2453c82fatagen2026-09-24 13:07 UTC182
            ..Self::new(
31ce2453c82fatagen2026-09-24 13:07 UTC183
                ErrorKind::InteractiveAuthRequired,
31ce2453c82fatagen2026-09-24 13:07 UTC184
                "interactive authentication is required",
31ce2453c82fatagen2026-09-24 13:07 UTC185
            )
96fdf90aacd6atagen2026-09-08 08:24 UTC186
        }
96fdf90aacd6atagen2026-09-08 08:24 UTC187
    }
96fdf90aacd6atagen2026-09-08 08:24 UTC188
96fdf90aacd6atagen2026-09-08 08:24 UTC189
    pub(crate) fn from_sdk(message: impl Into<String>, source: matrix_sdk::Error) -> Self {
96fdf90aacd6atagen2026-09-08 08:24 UTC190
        Self::with_source(classify_sdk_error(&source), message, source)
96fdf90aacd6atagen2026-09-08 08:24 UTC191
    }
96fdf90aacd6atagen2026-09-08 08:24 UTC192
96fdf90aacd6atagen2026-09-08 08:24 UTC193
    pub(crate) fn from_http(message: impl Into<String>, source: HttpError) -> Self {
96fdf90aacd6atagen2026-09-08 08:24 UTC194
        Self::with_source(classify_http_error(&source), message, source)
96fdf90aacd6atagen2026-09-08 08:24 UTC195
    }
31ce2453c82fatagen2026-09-24 13:07 UTC196
96fdf90aacd6atagen2026-09-08 08:24 UTC197
    pub(crate) fn from_refresh_token(
96fdf90aacd6atagen2026-09-08 08:24 UTC198
        message: impl Into<String>,
96fdf90aacd6atagen2026-09-08 08:24 UTC199
        source: RefreshTokenError,
96fdf90aacd6atagen2026-09-08 08:24 UTC200
    ) -> Self {
96fdf90aacd6atagen2026-09-08 08:24 UTC201
        Self::with_source(classify_refresh_token_error(&source), message, source)
96fdf90aacd6atagen2026-09-08 08:24 UTC202
    }
96fdf90aacd6atagen2026-09-08 08:24 UTC203
96fdf90aacd6atagen2026-09-08 08:24 UTC204
    pub(crate) fn from_recovery(message: impl Into<String>, source: RecoveryError) -> Self {
96fdf90aacd6atagen2026-09-08 08:24 UTC205
        let kind = match &source {
96fdf90aacd6atagen2026-09-08 08:24 UTC206
            RecoveryError::Sdk(source) => classify_sdk_error(source),
96fdf90aacd6atagen2026-09-08 08:24 UTC207
            RecoveryError::SecretStorage(SecretStorageError::Sdk(source)) => {
96fdf90aacd6atagen2026-09-08 08:24 UTC208
                classify_sdk_error(source)
96fdf90aacd6atagen2026-09-08 08:24 UTC209
            }
96fdf90aacd6atagen2026-09-08 08:24 UTC210
            RecoveryError::SecretStorage(SecretStorageError::ImportError { error, .. }) => {
96fdf90aacd6atagen2026-09-08 08:24 UTC211
                match error {
96fdf90aacd6atagen2026-09-08 08:24 UTC212
                    ImportError::Sdk(source) => classify_sdk_error(source),
31ce2453c82fatagen2026-09-24 13:07 UTC213
                    _ => ErrorKind::RecoveryRejected,
96fdf90aacd6atagen2026-09-08 08:24 UTC214
                }
96fdf90aacd6atagen2026-09-08 08:24 UTC215
            }
96fdf90aacd6atagen2026-09-08 08:24 UTC216
            RecoveryError::SecretStorage(SecretStorageError::Verification(source)) => {
96fdf90aacd6atagen2026-09-08 08:24 UTC217
                match source {
96fdf90aacd6atagen2026-09-08 08:24 UTC218
                    ManualVerifyError::Http(source) => classify_http_error(source),
31ce2453c82fatagen2026-09-24 13:07 UTC219
                    _ => ErrorKind::RecoveryRejected,
96fdf90aacd6atagen2026-09-08 08:24 UTC220
                }
96fdf90aacd6atagen2026-09-08 08:24 UTC221
            }
96fdf90aacd6atagen2026-09-08 08:24 UTC222
            RecoveryError::SecretStorage(SecretStorageError::SecretStorageKey(_)) => {
31ce2453c82fatagen2026-09-24 13:07 UTC223
                ErrorKind::RecoveryRejected
96fdf90aacd6atagen2026-09-08 08:24 UTC224
            }
31ce2453c82fatagen2026-09-24 13:07 UTC225
            RecoveryError::SecretStorage(SecretStorageError::Storage(_)) => ErrorKind::Store,
96fdf90aacd6atagen2026-09-08 08:24 UTC226
            RecoveryError::BackupExistsOnServer | RecoveryError::SecretStorage(_) => {
31ce2453c82fatagen2026-09-24 13:07 UTC227
                ErrorKind::RecoveryRejected
96fdf90aacd6atagen2026-09-08 08:24 UTC228
            }
96fdf90aacd6atagen2026-09-08 08:24 UTC229
        };
96fdf90aacd6atagen2026-09-08 08:24 UTC230
        Self::with_source(kind, message, source)
96fdf90aacd6atagen2026-09-08 08:24 UTC231
    }
96fdf90aacd6atagen2026-09-08 08:24 UTC232
96fdf90aacd6atagen2026-09-08 08:24 UTC233
    pub(crate) fn from_verification_request(
96fdf90aacd6atagen2026-09-08 08:24 UTC234
        message: impl Into<String>,
96fdf90aacd6atagen2026-09-08 08:24 UTC235
        source: RequestVerificationError,
96fdf90aacd6atagen2026-09-08 08:24 UTC236
    ) -> Self {
96fdf90aacd6atagen2026-09-08 08:24 UTC237
        let kind = match &source {
96fdf90aacd6atagen2026-09-08 08:24 UTC238
            RequestVerificationError::Sdk(source) => classify_sdk_error(source),
31ce2453c82fatagen2026-09-24 13:07 UTC239
            RequestVerificationError::RoomCreation(_) => ErrorKind::Encryption,
96fdf90aacd6atagen2026-09-08 08:24 UTC240
        };
96fdf90aacd6atagen2026-09-08 08:24 UTC241
        Self::with_source(kind, message, source)
96fdf90aacd6atagen2026-09-08 08:24 UTC242
    }
96fdf90aacd6atagen2026-09-08 08:24 UTC243
}
96fdf90aacd6atagen2026-09-08 08:24 UTC244
31ce2453c82fatagen2026-09-24 13:07 UTC245
impl PartialEq for Error {
31ce2453c82fatagen2026-09-24 13:07 UTC246
    fn eq(&self, other: &Self) -> bool {
31ce2453c82fatagen2026-09-24 13:07 UTC247
        self.kind == other.kind
31ce2453c82fatagen2026-09-24 13:07 UTC248
            && self.message == other.message
31ce2453c82fatagen2026-09-24 13:07 UTC249
            && self.challenge == other.challenge
9a25b6ce66f4atagen2026-10-08 11:15 UTC250
            && self.server == other.server
31ce2453c82fatagen2026-09-24 13:07 UTC251
    }
31ce2453c82fatagen2026-09-24 13:07 UTC252
}
31ce2453c82fatagen2026-09-24 13:07 UTC253
31ce2453c82fatagen2026-09-24 13:07 UTC254
pub(crate) fn classify_sdk_error(source: &matrix_sdk::Error) -> ErrorKind {
96fdf90aacd6atagen2026-09-08 08:24 UTC255
    match source {
96fdf90aacd6atagen2026-09-08 08:24 UTC256
        matrix_sdk::Error::Http(source) => classify_http_error(source),
96fdf90aacd6atagen2026-09-08 08:24 UTC257
        matrix_sdk::Error::OAuth(source) => classify_oauth_error(source),
31ce2453c82fatagen2026-09-24 13:07 UTC258
        matrix_sdk::Error::AuthenticationRequired => ErrorKind::Unauthenticated,
96fdf90aacd6atagen2026-09-08 08:24 UTC259
        matrix_sdk::Error::BadCryptoStoreState
96fdf90aacd6atagen2026-09-08 08:24 UTC260
        | matrix_sdk::Error::CryptoStoreError(_)
96fdf90aacd6atagen2026-09-08 08:24 UTC261
        | matrix_sdk::Error::CrossProcessLockError(_)
96fdf90aacd6atagen2026-09-08 08:24 UTC262
        | matrix_sdk::Error::StateStore(_)
96fdf90aacd6atagen2026-09-08 08:24 UTC263
        | matrix_sdk::Error::EventCacheStore(_)
31ce2453c82fatagen2026-09-24 13:07 UTC264
        | matrix_sdk::Error::MediaStore(_) => ErrorKind::Store,
96fdf90aacd6atagen2026-09-08 08:24 UTC265
        matrix_sdk::Error::NoOlmMachine
96fdf90aacd6atagen2026-09-08 08:24 UTC266
        | matrix_sdk::Error::OlmError(_)
96fdf90aacd6atagen2026-09-08 08:24 UTC267
        | matrix_sdk::Error::MegolmError(_)
31ce2453c82fatagen2026-09-24 13:07 UTC268
        | matrix_sdk::Error::DecryptorError(_) => ErrorKind::Encryption,
31ce2453c82fatagen2026-09-24 13:07 UTC269
        matrix_sdk::Error::Media(_) => ErrorKind::MediaUnavailable,
31ce2453c82fatagen2026-09-24 13:07 UTC270
        matrix_sdk::Error::Timeout => ErrorKind::Network,
31ce2453c82fatagen2026-09-24 13:07 UTC271
        _ => ErrorKind::Other,
96fdf90aacd6atagen2026-09-08 08:24 UTC272
    }
96fdf90aacd6atagen2026-09-08 08:24 UTC273
}
96fdf90aacd6atagen2026-09-08 08:24 UTC274
31ce2453c82fatagen2026-09-24 13:07 UTC275
fn classify_http_error(source: &HttpError) -> ErrorKind {
96fdf90aacd6atagen2026-09-08 08:24 UTC276
    match source {
31ce2453c82fatagen2026-09-24 13:07 UTC277
        HttpError::Reqwest(_) => ErrorKind::Network,
0291516d40b5atagen2026-10-22 08:31 UTC278
        HttpError::Api(_)
0291516d40b5atagen2026-10-22 08:31 UTC279
            if source
0291516d40b5atagen2026-10-22 08:31 UTC280
                .as_client_api_error()
0291516d40b5atagen2026-10-22 08:31 UTC281
                .is_some_and(|api| api.status_code.as_u16() == 429) =>
0291516d40b5atagen2026-10-22 08:31 UTC282
        {
0291516d40b5atagen2026-10-22 08:31 UTC283
            ErrorKind::RateLimited
0291516d40b5atagen2026-10-22 08:31 UTC284
        }
31ce2453c82fatagen2026-09-24 13:07 UTC285
        HttpError::Api(_) => ErrorKind::Server,
96fdf90aacd6atagen2026-09-08 08:24 UTC286
        HttpError::RefreshToken(source) => classify_refresh_token_error(source),
96fdf90aacd6atagen2026-09-08 08:24 UTC287
        HttpError::Cached(source) => classify_http_error(source),
31ce2453c82fatagen2026-09-24 13:07 UTC288
        _ => ErrorKind::Other,
96fdf90aacd6atagen2026-09-08 08:24 UTC289
    }
96fdf90aacd6atagen2026-09-08 08:24 UTC290
}
96fdf90aacd6atagen2026-09-08 08:24 UTC291
31ce2453c82fatagen2026-09-24 13:07 UTC292
fn classify_refresh_token_error(source: &RefreshTokenError) -> ErrorKind {
96fdf90aacd6atagen2026-09-08 08:24 UTC293
    match source {
31ce2453c82fatagen2026-09-24 13:07 UTC294
        RefreshTokenError::RefreshTokenRequired => ErrorKind::Unauthenticated,
96fdf90aacd6atagen2026-09-08 08:24 UTC295
        RefreshTokenError::MatrixAuth(source) => classify_http_error(source),
96fdf90aacd6atagen2026-09-08 08:24 UTC296
        RefreshTokenError::OAuth(source) => classify_oauth_error(source),
96fdf90aacd6atagen2026-09-08 08:24 UTC297
    }
96fdf90aacd6atagen2026-09-08 08:24 UTC298
}
96fdf90aacd6atagen2026-09-08 08:24 UTC299
31ce2453c82fatagen2026-09-24 13:07 UTC300
fn classify_oauth_error(source: &OAuthError) -> ErrorKind {
96fdf90aacd6atagen2026-09-08 08:24 UTC301
    let classify_token_request_error = |source: &_| match source {
31ce2453c82fatagen2026-09-24 13:07 UTC302
        RequestTokenError::Request(_) => ErrorKind::Network,
31ce2453c82fatagen2026-09-24 13:07 UTC303
        RequestTokenError::ServerResponse(_) => ErrorKind::Unauthenticated,
31ce2453c82fatagen2026-09-24 13:07 UTC304
        _ => ErrorKind::Other,
96fdf90aacd6atagen2026-09-08 08:24 UTC305
    };
96fdf90aacd6atagen2026-09-08 08:24 UTC306
    match source {
96fdf90aacd6atagen2026-09-08 08:24 UTC307
        OAuthError::Discovery(source) => match source {
96fdf90aacd6atagen2026-09-08 08:24 UTC308
            OAuthDiscoveryError::Http(source) => classify_http_error(source),
96fdf90aacd6atagen2026-09-08 08:24 UTC309
            OAuthDiscoveryError::Oidc(source) => classify_token_request_error(source),
31ce2453c82fatagen2026-09-24 13:07 UTC310
            _ => ErrorKind::Unauthenticated,
96fdf90aacd6atagen2026-09-08 08:24 UTC311
        },
96fdf90aacd6atagen2026-09-08 08:24 UTC312
        OAuthError::RefreshToken(source) => classify_token_request_error(source),
96fdf90aacd6atagen2026-09-08 08:24 UTC313
        OAuthError::AuthorizationCode(OAuthAuthorizationCodeError::RequestToken(source)) => {
96fdf90aacd6atagen2026-09-08 08:24 UTC314
            classify_token_request_error(source)
96fdf90aacd6atagen2026-09-08 08:24 UTC315
        }
31ce2453c82fatagen2026-09-24 13:07 UTC316
        OAuthError::AuthorizationCode(_) => ErrorKind::Unauthenticated,
96fdf90aacd6atagen2026-09-08 08:24 UTC317
        OAuthError::Logout(source) => match source {
31ce2453c82fatagen2026-09-24 13:07 UTC318
            OAuthTokenRevocationError::Revoke(RequestTokenError::Request(_)) => ErrorKind::Network,
96fdf90aacd6atagen2026-09-08 08:24 UTC319
            OAuthTokenRevocationError::Revoke(RequestTokenError::ServerResponse(_)) => {
31ce2453c82fatagen2026-09-24 13:07 UTC320
                ErrorKind::Unauthenticated
96fdf90aacd6atagen2026-09-08 08:24 UTC321
            }
31ce2453c82fatagen2026-09-24 13:07 UTC322
            _ => ErrorKind::Other,
96fdf90aacd6atagen2026-09-08 08:24 UTC323
        },
31ce2453c82fatagen2026-09-24 13:07 UTC324
        _ => ErrorKind::Unauthenticated,
96fdf90aacd6atagen2026-09-08 08:24 UTC325
    }
96fdf90aacd6atagen2026-09-08 08:24 UTC326
}