libsignal_protocol/
errors.rs

1use std::{
2    convert::TryFrom,
3    fmt::{self, Display, Formatter},
4};
5
6#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, failure_derive::Fail)]
7#[allow(missing_docs)]
8pub enum InternalError {
9    NoMemory,
10    InvalidArgument,
11    Unknown,
12    DuplicateMessage,
13    InvalidKey,
14    InvalidKeyId,
15    InvalidMAC,
16    InvalidMessage,
17    InvalidVersion,
18    LegacyMessage,
19    NoSession,
20    StaleKeyExchange,
21    UntrustedIdentity,
22    VerifySignatureVerificationFailed,
23    InvalidProtoBuf,
24    FPVersionMismatch,
25    FPIdentMismatch,
26    Other(i32),
27}
28
29impl InternalError {
30    /// Try to figure out what type of error a code corresponds to.
31    pub fn from_error_code(code: i32) -> Option<InternalError> {
32        match code {
33            sys::SG_ERR_NOMEM => Some(InternalError::NoMemory),
34            sys::SG_ERR_INVAL => Some(InternalError::InvalidArgument),
35            sys::SG_ERR_UNKNOWN => Some(InternalError::Unknown),
36            sys::SG_ERR_DUPLICATE_MESSAGE => {
37                Some(InternalError::DuplicateMessage)
38            },
39            sys::SG_ERR_INVALID_KEY => Some(InternalError::InvalidKey),
40            sys::SG_ERR_INVALID_KEY_ID => Some(InternalError::InvalidKeyId),
41            sys::SG_ERR_INVALID_MAC => Some(InternalError::InvalidMAC),
42            sys::SG_ERR_INVALID_MESSAGE => Some(InternalError::InvalidMessage),
43            sys::SG_ERR_INVALID_VERSION => Some(InternalError::InvalidVersion),
44            sys::SG_ERR_LEGACY_MESSAGE => Some(InternalError::LegacyMessage),
45            sys::SG_ERR_NO_SESSION => Some(InternalError::NoSession),
46            sys::SG_ERR_STALE_KEY_EXCHANGE => {
47                Some(InternalError::StaleKeyExchange)
48            },
49            sys::SG_ERR_UNTRUSTED_IDENTITY => {
50                Some(InternalError::UntrustedIdentity)
51            },
52            sys::SG_ERR_VRF_SIG_VERIF_FAILED => {
53                Some(InternalError::VerifySignatureVerificationFailed)
54            },
55            sys::SG_ERR_INVALID_PROTO_BUF => {
56                Some(InternalError::InvalidProtoBuf)
57            },
58            sys::SG_ERR_FP_VERSION_MISMATCH => {
59                Some(InternalError::FPVersionMismatch)
60            },
61            sys::SG_ERR_FP_IDENT_MISMATCH => {
62                Some(InternalError::FPIdentMismatch)
63            },
64            _ => None,
65        }
66    }
67
68    /// Get the code which corresponds to this error.
69    pub fn code(self) -> i32 {
70        match self {
71            InternalError::NoMemory => sys::SG_ERR_NOMEM,
72            InternalError::InvalidArgument => sys::SG_ERR_INVAL,
73            InternalError::Unknown => sys::SG_ERR_UNKNOWN,
74            InternalError::DuplicateMessage => sys::SG_ERR_DUPLICATE_MESSAGE,
75            InternalError::InvalidKey => sys::SG_ERR_INVALID_KEY,
76            InternalError::InvalidKeyId => sys::SG_ERR_INVALID_KEY_ID,
77            InternalError::InvalidMAC => sys::SG_ERR_INVALID_MAC,
78            InternalError::InvalidMessage => sys::SG_ERR_INVALID_MESSAGE,
79            InternalError::InvalidVersion => sys::SG_ERR_INVALID_VERSION,
80            InternalError::LegacyMessage => sys::SG_ERR_LEGACY_MESSAGE,
81            InternalError::NoSession => sys::SG_ERR_NO_SESSION,
82            InternalError::StaleKeyExchange => sys::SG_ERR_STALE_KEY_EXCHANGE,
83            InternalError::UntrustedIdentity => sys::SG_ERR_UNTRUSTED_IDENTITY,
84            InternalError::VerifySignatureVerificationFailed => {
85                sys::SG_ERR_VRF_SIG_VERIF_FAILED
86            },
87            InternalError::InvalidProtoBuf => sys::SG_ERR_INVALID_PROTO_BUF,
88            InternalError::FPVersionMismatch => sys::SG_ERR_FP_VERSION_MISMATCH,
89            InternalError::FPIdentMismatch => sys::SG_ERR_FP_IDENT_MISMATCH,
90            InternalError::Other(c) => c,
91        }
92    }
93}
94
95/// A helper trait for going from an [`InternalError`] to a `Result`.
96pub trait FromInternalErrorCode: Sized {
97    /// Make the conversion.
98    fn into_result(self) -> Result<(), InternalError>;
99}
100
101/// A helper trait for going from a `Result` to an [`InternalError`].
102pub trait IntoInternalErrorCode: Sized {
103    /// Make the conversion.
104    fn into_code(self) -> i32;
105}
106
107impl FromInternalErrorCode for isize {
108    fn into_result(self) -> Result<(), InternalError> {
109        i32::try_from(self).expect("Overflow").into_result()
110    }
111}
112
113impl FromInternalErrorCode for i32 {
114    fn into_result(self) -> Result<(), InternalError> {
115        if self == 0 {
116            return Ok(());
117        }
118
119        match InternalError::from_error_code(self) {
120            None => Err(InternalError::Other(self)),
121            Some(e) => Err(e),
122        }
123    }
124}
125
126impl<T> IntoInternalErrorCode for Result<T, InternalError> {
127    fn into_code(self) -> i32 {
128        match self {
129            Ok(_) => 0,
130            Err(e) => e.code(),
131        }
132    }
133}
134
135impl From<InternalError> for i32 {
136    fn from(other: InternalError) -> i32 { other.code() }
137}
138
139impl Display for InternalError {
140    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
141        match self {
142            InternalError::NoMemory => write!(f, "No Memory"),
143            InternalError::InvalidArgument => write!(f, "Invalid argument"),
144            InternalError::Unknown => write!(f, "Unknown error"),
145            InternalError::DuplicateMessage => write!(f, "Duplicate message"),
146            InternalError::InvalidKey => write!(f, "Invalid key"),
147            InternalError::InvalidKeyId => write!(f, "Invalid key ID"),
148            InternalError::InvalidMAC => write!(f, "Invalid MAC"),
149            InternalError::InvalidMessage => write!(f, "Invalid message"),
150            InternalError::InvalidVersion => write!(f, "Invalid version"),
151            InternalError::LegacyMessage => write!(f, "Legacy message"),
152            InternalError::NoSession => write!(f, "No session"),
153            InternalError::StaleKeyExchange => write!(f, "Stale key exchange"),
154            InternalError::UntrustedIdentity => write!(f, "Untrusted identity"),
155            InternalError::VerifySignatureVerificationFailed => {
156                write!(f, "Verifying signature failed")
157            },
158            InternalError::InvalidProtoBuf => write!(f, "Invalid protobuf"),
159            InternalError::FPVersionMismatch => {
160                write!(f, "FP version mismatched")
161            },
162            InternalError::FPIdentMismatch => write!(f, "FP ident mismatched"),
163            InternalError::Other(code) => write!(f, "Unknown error {}", code),
164        }
165    }
166}