atagen

macltok

public
Star0
Watch0
96680d38cc31a0e21893067842e0125dda3314ab
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,
89bc9f8d246datagen2026-10-24 13:40 UTC57
    EventNotFound,
31ce2453c82fatagen2026-09-24 13:07 UTC58
    RoomBusy,
31ce2453c82fatagen2026-09-24 13:07 UTC59
    QueueFull,
31ce2453c82fatagen2026-09-24 13:07 UTC60
    EmptyBody,
31ce2453c82fatagen2026-09-24 13:07 UTC61
    MediaUnknown,
31ce2453c82fatagen2026-09-24 13:07 UTC62
    MediaTooLarge,
31ce2453c82fatagen2026-09-24 13:07 UTC63
    MediaUnavailable,
31ce2453c82fatagen2026-09-24 13:07 UTC64
    VerificationInactive,
31ce2453c82fatagen2026-09-24 13:07 UTC65
    VerificationUnsupported,
31ce2453c82fatagen2026-09-24 13:07 UTC66
    NoCrossSigningIdentity,
31ce2453c82fatagen2026-09-24 13:07 UTC67
    RecoveryRejected,
31ce2453c82fatagen2026-09-24 13:07 UTC68
    Network,
0291516d40b5atagen2026-10-22 08:31 UTC69
    /// the homeserver wants us to slow down. try again later
0291516d40b5atagen2026-10-22 08:31 UTC70
    RateLimited,
31ce2453c82fatagen2026-09-24 13:07 UTC71
    Server,
31ce2453c82fatagen2026-09-24 13:07 UTC72
    Store,
31ce2453c82fatagen2026-09-24 13:07 UTC73
    Timeline,
31ce2453c82fatagen2026-09-24 13:07 UTC74
    Encryption,
31ce2453c82fatagen2026-09-24 13:07 UTC75
    Other,
31ce2453c82fatagen2026-09-24 13:07 UTC76
}
31ce2453c82fatagen2026-09-24 13:07 UTC77
9a25b6ce66f4atagen2026-10-08 11:15 UTC78
/// the homeserver's own answer, worth showing a person as it stands
9a25b6ce66f4atagen2026-10-08 11:15 UTC79
#[derive(Clone, Debug, Eq, PartialEq)]
9a25b6ce66f4atagen2026-10-08 11:15 UTC80
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9a25b6ce66f4atagen2026-10-08 11:15 UTC81
#[non_exhaustive]
9a25b6ce66f4atagen2026-10-08 11:15 UTC82
pub struct ServerError {
9a25b6ce66f4atagen2026-10-08 11:15 UTC83
    pub status: u16,
9a25b6ce66f4atagen2026-10-08 11:15 UTC84
    pub errcode: String,
9a25b6ce66f4atagen2026-10-08 11:15 UTC85
    pub message: String,
9a25b6ce66f4atagen2026-10-08 11:15 UTC86
}
9a25b6ce66f4atagen2026-10-08 11:15 UTC87
9a25b6ce66f4atagen2026-10-08 11:15 UTC88
impl ServerError {
9a25b6ce66f4atagen2026-10-08 11:15 UTC89
    pub(crate) fn find(source: &(dyn std::error::Error + 'static)) -> Option<Self> {
9a25b6ce66f4atagen2026-10-08 11:15 UTC90
        let mut current = Some(source);
9a25b6ce66f4atagen2026-10-08 11:15 UTC91
        while let Some(error) = current {
9a25b6ce66f4atagen2026-10-08 11:15 UTC92
            let api = if let Some(error) = error.downcast_ref::<matrix_sdk::Error>() {
9a25b6ce66f4atagen2026-10-08 11:15 UTC93
                error.as_client_api_error()
9a25b6ce66f4atagen2026-10-08 11:15 UTC94
            } else if let Some(error) = error.downcast_ref::<HttpError>() {
9a25b6ce66f4atagen2026-10-08 11:15 UTC95
                error.as_client_api_error()
9a25b6ce66f4atagen2026-10-08 11:15 UTC96
            } else {
9a25b6ce66f4atagen2026-10-08 11:15 UTC97
                error.downcast_ref::<ruma::api::error::Error>()
9a25b6ce66f4atagen2026-10-08 11:15 UTC98
            };
9a25b6ce66f4atagen2026-10-08 11:15 UTC99
            if let Some(api) = api
9a25b6ce66f4atagen2026-10-08 11:15 UTC100
                && let ruma::api::error::ErrorBody::Standard(body) = &api.body
9a25b6ce66f4atagen2026-10-08 11:15 UTC101
            {
9a25b6ce66f4atagen2026-10-08 11:15 UTC102
                return Some(Self {
9a25b6ce66f4atagen2026-10-08 11:15 UTC103
                    status: api.status_code.as_u16(),
9a25b6ce66f4atagen2026-10-08 11:15 UTC104
                    errcode: body.kind.errcode().to_string(),
9a25b6ce66f4atagen2026-10-08 11:15 UTC105
                    message: body.message.clone(),
9a25b6ce66f4atagen2026-10-08 11:15 UTC106
                });
9a25b6ce66f4atagen2026-10-08 11:15 UTC107
            }
9a25b6ce66f4atagen2026-10-08 11:15 UTC108
            current = error.source();
9a25b6ce66f4atagen2026-10-08 11:15 UTC109
        }
9a25b6ce66f4atagen2026-10-08 11:15 UTC110
        None
9a25b6ce66f4atagen2026-10-08 11:15 UTC111
    }
9a25b6ce66f4atagen2026-10-08 11:15 UTC112
}
9a25b6ce66f4atagen2026-10-08 11:15 UTC113
9a25b6ce66f4atagen2026-10-08 11:15 UTC114
impl std::fmt::Display for ServerError {
9a25b6ce66f4atagen2026-10-08 11:15 UTC115
    fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
9a25b6ce66f4atagen2026-10-08 11:15 UTC116
        write!(formatter, "{} ({})", self.message, self.errcode)
9a25b6ce66f4atagen2026-10-08 11:15 UTC117
    }
9a25b6ce66f4atagen2026-10-08 11:15 UTC118
}
9a25b6ce66f4atagen2026-10-08 11:15 UTC119
9a25b6ce66f4atagen2026-10-08 11:15 UTC120
#[cfg(any(feature = "sqlite", feature = "indexeddb"))]
9a25b6ce66f4atagen2026-10-08 11:15 UTC121
pub(crate) fn classify(source: &(dyn std::error::Error + 'static)) -> ErrorKind {
9a25b6ce66f4atagen2026-10-08 11:15 UTC122
    let mut current = Some(source);
9a25b6ce66f4atagen2026-10-08 11:15 UTC123
    while let Some(error) = current {
9a25b6ce66f4atagen2026-10-08 11:15 UTC124
        if let Some(error) = error.downcast_ref::<matrix_sdk::Error>() {
9a25b6ce66f4atagen2026-10-08 11:15 UTC125
            return classify_sdk_error(error);
9a25b6ce66f4atagen2026-10-08 11:15 UTC126
        }
9a25b6ce66f4atagen2026-10-08 11:15 UTC127
        if let Some(error) = error.downcast_ref::<HttpError>() {
9a25b6ce66f4atagen2026-10-08 11:15 UTC128
            return classify_http_error(error);
9a25b6ce66f4atagen2026-10-08 11:15 UTC129
        }
9a25b6ce66f4atagen2026-10-08 11:15 UTC130
        if let Some(error) = error.downcast_ref::<OAuthError>() {
9a25b6ce66f4atagen2026-10-08 11:15 UTC131
            return classify_oauth_error(error);
9a25b6ce66f4atagen2026-10-08 11:15 UTC132
        }
9a25b6ce66f4atagen2026-10-08 11:15 UTC133
        if let Some(error) = error.downcast_ref::<RefreshTokenError>() {
9a25b6ce66f4atagen2026-10-08 11:15 UTC134
            return classify_refresh_token_error(error);
9a25b6ce66f4atagen2026-10-08 11:15 UTC135
        }
9a25b6ce66f4atagen2026-10-08 11:15 UTC136
        current = error.source();
9a25b6ce66f4atagen2026-10-08 11:15 UTC137
    }
9a25b6ce66f4atagen2026-10-08 11:15 UTC138
    ErrorKind::Other
9a25b6ce66f4atagen2026-10-08 11:15 UTC139
}
9a25b6ce66f4atagen2026-10-08 11:15 UTC140
31ce2453c82fatagen2026-09-24 13:07 UTC141
impl Error {
31ce2453c82fatagen2026-09-24 13:07 UTC142
    pub(crate) fn new(kind: ErrorKind, message: impl Into<String>) -> Self {
96fdf90aacd6atagen2026-09-08 08:24 UTC143
        Self {
96fdf90aacd6atagen2026-09-08 08:24 UTC144
            kind,
96fdf90aacd6atagen2026-09-08 08:24 UTC145
            message: message.into(),
31ce2453c82fatagen2026-09-24 13:07 UTC146
            challenge: None,
9a25b6ce66f4atagen2026-10-08 11:15 UTC147
            server: None,
96fdf90aacd6atagen2026-09-08 08:24 UTC148
            source: None,
96fdf90aacd6atagen2026-09-08 08:24 UTC149
        }
96fdf90aacd6atagen2026-09-08 08:24 UTC150
    }
96fdf90aacd6atagen2026-09-08 08:24 UTC151
96fdf90aacd6atagen2026-09-08 08:24 UTC152
    pub(crate) fn with_source(
31ce2453c82fatagen2026-09-24 13:07 UTC153
        kind: ErrorKind,
96fdf90aacd6atagen2026-09-08 08:24 UTC154
        message: impl Into<String>,
1fe480c16a3catagen2026-09-26 08:44 UTC155
        source: impl std::error::Error + SendOutsideWasm + SyncOutsideWasm + 'static,
96fdf90aacd6atagen2026-09-08 08:24 UTC156
    ) -> Self {
96fdf90aacd6atagen2026-09-08 08:24 UTC157
        Self {
9a25b6ce66f4atagen2026-10-08 11:15 UTC158
            server: ServerError::find(&source),
31ce2453c82fatagen2026-09-24 13:07 UTC159
            source: Some(Arc::new(source)),
31ce2453c82fatagen2026-09-24 13:07 UTC160
            ..Self::new(kind, message)
31ce2453c82fatagen2026-09-24 13:07 UTC161
        }
31ce2453c82fatagen2026-09-24 13:07 UTC162
    }
31ce2453c82fatagen2026-09-24 13:07 UTC163
31ce2453c82fatagen2026-09-24 13:07 UTC164
    pub(crate) fn interrupted() -> Self {
31ce2453c82fatagen2026-09-24 13:07 UTC165
        Self::new(
31ce2453c82fatagen2026-09-24 13:07 UTC166
            ErrorKind::Interrupted,
31ce2453c82fatagen2026-09-24 13:07 UTC167
            "the engine stopped before the operation finished",
31ce2453c82fatagen2026-09-24 13:07 UTC168
        )
31ce2453c82fatagen2026-09-24 13:07 UTC169
    }
31ce2453c82fatagen2026-09-24 13:07 UTC170
31ce2453c82fatagen2026-09-24 13:07 UTC171
    pub(crate) fn room_unknown() -> Self {
31ce2453c82fatagen2026-09-24 13:07 UTC172
        Self::new(
31ce2453c82fatagen2026-09-24 13:07 UTC173
            ErrorKind::RoomUnknown,
31ce2453c82fatagen2026-09-24 13:07 UTC174
            "room is not available in the local store",
31ce2453c82fatagen2026-09-24 13:07 UTC175
        )
31ce2453c82fatagen2026-09-24 13:07 UTC176
    }
31ce2453c82fatagen2026-09-24 13:07 UTC177
31ce2453c82fatagen2026-09-24 13:07 UTC178
    pub(crate) fn interactive_auth(challenge: InteractiveAuthChallenge) -> Self {
31ce2453c82fatagen2026-09-24 13:07 UTC179
        Self {
31ce2453c82fatagen2026-09-24 13:07 UTC180
            challenge: Some(Box::new(challenge)),
31ce2453c82fatagen2026-09-24 13:07 UTC181
            ..Self::new(
31ce2453c82fatagen2026-09-24 13:07 UTC182
                ErrorKind::InteractiveAuthRequired,
31ce2453c82fatagen2026-09-24 13:07 UTC183
                "interactive authentication is required",
31ce2453c82fatagen2026-09-24 13:07 UTC184
            )
96fdf90aacd6atagen2026-09-08 08:24 UTC185
        }
96fdf90aacd6atagen2026-09-08 08:24 UTC186
    }
96fdf90aacd6atagen2026-09-08 08:24 UTC187
96fdf90aacd6atagen2026-09-08 08:24 UTC188
    pub(crate) fn from_sdk(message: impl Into<String>, source: matrix_sdk::Error) -> Self {
96fdf90aacd6atagen2026-09-08 08:24 UTC189
        Self::with_source(classify_sdk_error(&source), message, source)
96fdf90aacd6atagen2026-09-08 08:24 UTC190
    }
96fdf90aacd6atagen2026-09-08 08:24 UTC191
96fdf90aacd6atagen2026-09-08 08:24 UTC192
    pub(crate) fn from_http(message: impl Into<String>, source: HttpError) -> Self {
96fdf90aacd6atagen2026-09-08 08:24 UTC193
        Self::with_source(classify_http_error(&source), message, source)
96fdf90aacd6atagen2026-09-08 08:24 UTC194
    }
31ce2453c82fatagen2026-09-24 13:07 UTC195
96fdf90aacd6atagen2026-09-08 08:24 UTC196
    pub(crate) fn from_refresh_token(
96fdf90aacd6atagen2026-09-08 08:24 UTC197
        message: impl Into<String>,
96fdf90aacd6atagen2026-09-08 08:24 UTC198
        source: RefreshTokenError,
96fdf90aacd6atagen2026-09-08 08:24 UTC199
    ) -> Self {
96fdf90aacd6atagen2026-09-08 08:24 UTC200
        Self::with_source(classify_refresh_token_error(&source), message, source)
96fdf90aacd6atagen2026-09-08 08:24 UTC201
    }
96fdf90aacd6atagen2026-09-08 08:24 UTC202
96fdf90aacd6atagen2026-09-08 08:24 UTC203
    pub(crate) fn from_recovery(message: impl Into<String>, source: RecoveryError) -> Self {
96fdf90aacd6atagen2026-09-08 08:24 UTC204
        let kind = match &source {
96fdf90aacd6atagen2026-09-08 08:24 UTC205
            RecoveryError::Sdk(source) => classify_sdk_error(source),
96fdf90aacd6atagen2026-09-08 08:24 UTC206
            RecoveryError::SecretStorage(SecretStorageError::Sdk(source)) => {
96fdf90aacd6atagen2026-09-08 08:24 UTC207
                classify_sdk_error(source)
96fdf90aacd6atagen2026-09-08 08:24 UTC208
            }
96fdf90aacd6atagen2026-09-08 08:24 UTC209
            RecoveryError::SecretStorage(SecretStorageError::ImportError { error, .. }) => {
96fdf90aacd6atagen2026-09-08 08:24 UTC210
                match error {
96fdf90aacd6atagen2026-09-08 08:24 UTC211
                    ImportError::Sdk(source) => classify_sdk_error(source),
31ce2453c82fatagen2026-09-24 13:07 UTC212
                    _ => ErrorKind::RecoveryRejected,
96fdf90aacd6atagen2026-09-08 08:24 UTC213
                }
96fdf90aacd6atagen2026-09-08 08:24 UTC214
            }
96fdf90aacd6atagen2026-09-08 08:24 UTC215
            RecoveryError::SecretStorage(SecretStorageError::Verification(source)) => {
96fdf90aacd6atagen2026-09-08 08:24 UTC216
                match source {
96fdf90aacd6atagen2026-09-08 08:24 UTC217
                    ManualVerifyError::Http(source) => classify_http_error(source),
31ce2453c82fatagen2026-09-24 13:07 UTC218
                    _ => ErrorKind::RecoveryRejected,
96fdf90aacd6atagen2026-09-08 08:24 UTC219
                }
96fdf90aacd6atagen2026-09-08 08:24 UTC220
            }
96fdf90aacd6atagen2026-09-08 08:24 UTC221
            RecoveryError::SecretStorage(SecretStorageError::SecretStorageKey(_)) => {
31ce2453c82fatagen2026-09-24 13:07 UTC222
                ErrorKind::RecoveryRejected
96fdf90aacd6atagen2026-09-08 08:24 UTC223
            }
31ce2453c82fatagen2026-09-24 13:07 UTC224
            RecoveryError::SecretStorage(SecretStorageError::Storage(_)) => ErrorKind::Store,
96fdf90aacd6atagen2026-09-08 08:24 UTC225
            RecoveryError::BackupExistsOnServer | RecoveryError::SecretStorage(_) => {
31ce2453c82fatagen2026-09-24 13:07 UTC226
                ErrorKind::RecoveryRejected
96fdf90aacd6atagen2026-09-08 08:24 UTC227
            }
96fdf90aacd6atagen2026-09-08 08:24 UTC228
        };
96fdf90aacd6atagen2026-09-08 08:24 UTC229
        Self::with_source(kind, message, source)
96fdf90aacd6atagen2026-09-08 08:24 UTC230
    }
96fdf90aacd6atagen2026-09-08 08:24 UTC231
96fdf90aacd6atagen2026-09-08 08:24 UTC232
    pub(crate) fn from_verification_request(
96fdf90aacd6atagen2026-09-08 08:24 UTC233
        message: impl Into<String>,
96fdf90aacd6atagen2026-09-08 08:24 UTC234
        source: RequestVerificationError,
96fdf90aacd6atagen2026-09-08 08:24 UTC235
    ) -> Self {
96fdf90aacd6atagen2026-09-08 08:24 UTC236
        let kind = match &source {
96fdf90aacd6atagen2026-09-08 08:24 UTC237
            RequestVerificationError::Sdk(source) => classify_sdk_error(source),
31ce2453c82fatagen2026-09-24 13:07 UTC238
            RequestVerificationError::RoomCreation(_) => ErrorKind::Encryption,
96fdf90aacd6atagen2026-09-08 08:24 UTC239
        };
96fdf90aacd6atagen2026-09-08 08:24 UTC240
        Self::with_source(kind, message, source)
96fdf90aacd6atagen2026-09-08 08:24 UTC241
    }
96fdf90aacd6atagen2026-09-08 08:24 UTC242
}
96fdf90aacd6atagen2026-09-08 08:24 UTC243
31ce2453c82fatagen2026-09-24 13:07 UTC244
impl PartialEq for Error {
31ce2453c82fatagen2026-09-24 13:07 UTC245
    fn eq(&self, other: &Self) -> bool {
31ce2453c82fatagen2026-09-24 13:07 UTC246
        self.kind == other.kind
31ce2453c82fatagen2026-09-24 13:07 UTC247
            && self.message == other.message
31ce2453c82fatagen2026-09-24 13:07 UTC248
            && self.challenge == other.challenge
9a25b6ce66f4atagen2026-10-08 11:15 UTC249
            && self.server == other.server
31ce2453c82fatagen2026-09-24 13:07 UTC250
    }
31ce2453c82fatagen2026-09-24 13:07 UTC251
}
31ce2453c82fatagen2026-09-24 13:07 UTC252
31ce2453c82fatagen2026-09-24 13:07 UTC253
pub(crate) fn classify_sdk_error(source: &matrix_sdk::Error) -> ErrorKind {
96fdf90aacd6atagen2026-09-08 08:24 UTC254
    match source {
96fdf90aacd6atagen2026-09-08 08:24 UTC255
        matrix_sdk::Error::Http(source) => classify_http_error(source),
96fdf90aacd6atagen2026-09-08 08:24 UTC256
        matrix_sdk::Error::OAuth(source) => classify_oauth_error(source),
31ce2453c82fatagen2026-09-24 13:07 UTC257
        matrix_sdk::Error::AuthenticationRequired => ErrorKind::Unauthenticated,
96fdf90aacd6atagen2026-09-08 08:24 UTC258
        matrix_sdk::Error::BadCryptoStoreState
96fdf90aacd6atagen2026-09-08 08:24 UTC259
        | matrix_sdk::Error::CryptoStoreError(_)
96fdf90aacd6atagen2026-09-08 08:24 UTC260
        | matrix_sdk::Error::CrossProcessLockError(_)
96fdf90aacd6atagen2026-09-08 08:24 UTC261
        | matrix_sdk::Error::StateStore(_)
96fdf90aacd6atagen2026-09-08 08:24 UTC262
        | matrix_sdk::Error::EventCacheStore(_)
31ce2453c82fatagen2026-09-24 13:07 UTC263
        | matrix_sdk::Error::MediaStore(_) => ErrorKind::Store,
96fdf90aacd6atagen2026-09-08 08:24 UTC264
        matrix_sdk::Error::NoOlmMachine
96fdf90aacd6atagen2026-09-08 08:24 UTC265
        | matrix_sdk::Error::OlmError(_)
96fdf90aacd6atagen2026-09-08 08:24 UTC266
        | matrix_sdk::Error::MegolmError(_)
31ce2453c82fatagen2026-09-24 13:07 UTC267
        | matrix_sdk::Error::DecryptorError(_) => ErrorKind::Encryption,
31ce2453c82fatagen2026-09-24 13:07 UTC268
        matrix_sdk::Error::Media(_) => ErrorKind::MediaUnavailable,
31ce2453c82fatagen2026-09-24 13:07 UTC269
        matrix_sdk::Error::Timeout => ErrorKind::Network,
31ce2453c82fatagen2026-09-24 13:07 UTC270
        _ => ErrorKind::Other,
96fdf90aacd6atagen2026-09-08 08:24 UTC271
    }
96fdf90aacd6atagen2026-09-08 08:24 UTC272
}
96fdf90aacd6atagen2026-09-08 08:24 UTC273
31ce2453c82fatagen2026-09-24 13:07 UTC274
fn classify_http_error(source: &HttpError) -> ErrorKind {
96fdf90aacd6atagen2026-09-08 08:24 UTC275
    match source {
31ce2453c82fatagen2026-09-24 13:07 UTC276
        HttpError::Reqwest(_) => ErrorKind::Network,
0291516d40b5atagen2026-10-22 08:31 UTC277
        HttpError::Api(_)
0291516d40b5atagen2026-10-22 08:31 UTC278
            if source
0291516d40b5atagen2026-10-22 08:31 UTC279
                .as_client_api_error()
0291516d40b5atagen2026-10-22 08:31 UTC280
                .is_some_and(|api| api.status_code.as_u16() == 429) =>
0291516d40b5atagen2026-10-22 08:31 UTC281
        {
0291516d40b5atagen2026-10-22 08:31 UTC282
            ErrorKind::RateLimited
0291516d40b5atagen2026-10-22 08:31 UTC283
        }
31ce2453c82fatagen2026-09-24 13:07 UTC284
        HttpError::Api(_) => ErrorKind::Server,
96fdf90aacd6atagen2026-09-08 08:24 UTC285
        HttpError::RefreshToken(source) => classify_refresh_token_error(source),
96fdf90aacd6atagen2026-09-08 08:24 UTC286
        HttpError::Cached(source) => classify_http_error(source),
31ce2453c82fatagen2026-09-24 13:07 UTC287
        _ => ErrorKind::Other,
96fdf90aacd6atagen2026-09-08 08:24 UTC288
    }
96fdf90aacd6atagen2026-09-08 08:24 UTC289
}
96fdf90aacd6atagen2026-09-08 08:24 UTC290
31ce2453c82fatagen2026-09-24 13:07 UTC291
fn classify_refresh_token_error(source: &RefreshTokenError) -> ErrorKind {
96fdf90aacd6atagen2026-09-08 08:24 UTC292
    match source {
31ce2453c82fatagen2026-09-24 13:07 UTC293
        RefreshTokenError::RefreshTokenRequired => ErrorKind::Unauthenticated,
96fdf90aacd6atagen2026-09-08 08:24 UTC294
        RefreshTokenError::MatrixAuth(source) => classify_http_error(source),
96fdf90aacd6atagen2026-09-08 08:24 UTC295
        RefreshTokenError::OAuth(source) => classify_oauth_error(source),
96fdf90aacd6atagen2026-09-08 08:24 UTC296
    }
96fdf90aacd6atagen2026-09-08 08:24 UTC297
}
96fdf90aacd6atagen2026-09-08 08:24 UTC298
31ce2453c82fatagen2026-09-24 13:07 UTC299
fn classify_oauth_error(source: &OAuthError) -> ErrorKind {
96fdf90aacd6atagen2026-09-08 08:24 UTC300
    let classify_token_request_error = |source: &_| match source {
31ce2453c82fatagen2026-09-24 13:07 UTC301
        RequestTokenError::Request(_) => ErrorKind::Network,
31ce2453c82fatagen2026-09-24 13:07 UTC302
        RequestTokenError::ServerResponse(_) => ErrorKind::Unauthenticated,
31ce2453c82fatagen2026-09-24 13:07 UTC303
        _ => ErrorKind::Other,
96fdf90aacd6atagen2026-09-08 08:24 UTC304
    };
96fdf90aacd6atagen2026-09-08 08:24 UTC305
    match source {
96fdf90aacd6atagen2026-09-08 08:24 UTC306
        OAuthError::Discovery(source) => match source {
96fdf90aacd6atagen2026-09-08 08:24 UTC307
            OAuthDiscoveryError::Http(source) => classify_http_error(source),
96fdf90aacd6atagen2026-09-08 08:24 UTC308
            OAuthDiscoveryError::Oidc(source) => classify_token_request_error(source),
31ce2453c82fatagen2026-09-24 13:07 UTC309
            _ => ErrorKind::Unauthenticated,
96fdf90aacd6atagen2026-09-08 08:24 UTC310
        },
96fdf90aacd6atagen2026-09-08 08:24 UTC311
        OAuthError::RefreshToken(source) => classify_token_request_error(source),
96fdf90aacd6atagen2026-09-08 08:24 UTC312
        OAuthError::AuthorizationCode(OAuthAuthorizationCodeError::RequestToken(source)) => {
96fdf90aacd6atagen2026-09-08 08:24 UTC313
            classify_token_request_error(source)
96fdf90aacd6atagen2026-09-08 08:24 UTC314
        }
31ce2453c82fatagen2026-09-24 13:07 UTC315
        OAuthError::AuthorizationCode(_) => ErrorKind::Unauthenticated,
96fdf90aacd6atagen2026-09-08 08:24 UTC316
        OAuthError::Logout(source) => match source {
31ce2453c82fatagen2026-09-24 13:07 UTC317
            OAuthTokenRevocationError::Revoke(RequestTokenError::Request(_)) => ErrorKind::Network,
96fdf90aacd6atagen2026-09-08 08:24 UTC318
            OAuthTokenRevocationError::Revoke(RequestTokenError::ServerResponse(_)) => {
31ce2453c82fatagen2026-09-24 13:07 UTC319
                ErrorKind::Unauthenticated
96fdf90aacd6atagen2026-09-08 08:24 UTC320
            }
31ce2453c82fatagen2026-09-24 13:07 UTC321
            _ => ErrorKind::Other,
96fdf90aacd6atagen2026-09-08 08:24 UTC322
        },
31ce2453c82fatagen2026-09-24 13:07 UTC323
        _ => ErrorKind::Unauthenticated,
96fdf90aacd6atagen2026-09-08 08:24 UTC324
    }
96fdf90aacd6atagen2026-09-08 08:24 UTC325
}