libqaul_types/error.rs
1//! Error and Result handling
2//!
3//! `libqaul` spans over a large abstraction surface, from drivers all
4//! the way to "business logic" functions in the service API. This
5//! makes communicating errors challenging at times. Generally, no
6//! lower layer `Error` objects are wrapped here, to avoid introducing
7//! new dependencies in service code.
8//!
9//! Instead, `Error` attempts to provide a comprehensive set of
10//! failures modes, that can be returned to communicate a failure,
11//! that then needs tobe interpreted and addressed by an implementing
12//! application. This way, it becomes easier for _your_ service to
13//! wrap errors, or to enumerate them more easily.
14//!
15//! On an `Error` enum, it is also possible to call `help()` to
16//! get a plain text error description of what went wrong, and what it
17//! probably means. These are meant to simplify front-end development
18//! and avoid having applications return arbitrary codes.
19
20use serde::{Deserialize, Serialize};
21use std::{
22 error::Error as StdError,
23 fmt::{self, Display, Formatter},
24 result::Result as StdResult,
25};
26
27/// `libqaul` specific Result with embedded Error
28///
29/// The returned `Error` can sometimes be considered non-fatal. Check
30/// the `Error` documentation for the specific returned variant to
31/// see, what level of fatality it should be interpreted as. Crashing
32/// on every returned `Err(_)` however is a bad idea.
33pub type Result<T> = StdResult<T, Error>;
34
35/// `libqaul` service API error states
36///
37/// All errors that can occur in interaction with the API are encoded
38/// as variants on this enum. In most cases, no additional metadata is
39/// provided and needs to be inferred from whatever context or
40/// function call emitted the error. Check the variant doc comments
41/// for a broad overview, as well as detailed usage instructions.
42///
43/// ## A note on language
44///
45/// Most variants of this enum use either an `Invalid` or `No`
46/// prefix. Invalid data is data that was either not expected or badly
47/// formatted. `No` in this case takes the place of `Unknown`, meaning
48/// that a query could not be fulfilled.
49#[derive(Serialize, Deserialize, Copy, Clone, Debug, PartialEq, Eq)]
50pub enum Error {
51 /// Not authorised to perform this action
52 NotAuthorised,
53 /// The desired user was not known
54 NoUser,
55 /// The provided contact already exists
56 ContactExists,
57 /// The desired contact does not exist
58 NoContact,
59 /// Invalid search query
60 InvalidQuery,
61 /// No data was returned for the provided query
62 NoData,
63 /// Invalid payload (probably too big)
64 InvalidPayload,
65 /// A function callback timed out
66 CallbackTimeout,
67 /// Signature with an unknown public key
68 NoSign,
69 /// Fraudulent signature for a known public key
70 BadSign,
71 /// A generic networking error occured
72 NetworkFault,
73 /// Failed to find a route to this user
74 NoRoute,
75 /// Some serialisation action failed
76 BadSerialise,
77 /// No such service was found
78 NoService,
79 /// A sevice with this name already exists
80 ServiceExists,
81 /// Some internal components failed to communicate
82 CommFault,
83}
84
85impl Error {
86 pub fn help(&self) -> String {
87 match std::env::var("QAUL_LANG").as_ref().map(|s| s.as_str()) {
88 Ok("ar") => "حدث خطأ غير معروف",
89 Ok("de") => "Ein unbekannter Fehler ist aufgetreten",
90 _ => "An unknown Error occured",
91 }
92 .into()
93 }
94}
95
96impl Display for Error {
97 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
98 let msg = match self {
99 Self::NotAuthorised => "Not authorised to perform this action",
100 Self::NoUser => "The desired user was not known",
101 Self::ContactExists => "The provided contact already exists",
102 Self::NoContact => "The desired contact does not exist",
103 Self::InvalidQuery => "Invalid search query",
104 Self::NoData => "No data was returned for the provided query",
105 Self::InvalidPayload => "Invalid payload (probably too big)",
106 Self::CallbackTimeout => "A function callback timed out",
107 Self::NoSign => "Signature with an unknown public key",
108 Self::BadSign => "Fraudulent signature for a known public key",
109 Self::NetworkFault => "A generic networking error occured",
110 Self::NoRoute => "Failed to find a route to this user",
111 Self::BadSerialise => "Some serialisation action failed",
112 Self::NoService => "No such service was found",
113 Self::ServiceExists => "A sevice with this name already exists",
114 Self::CommFault => "Some internal components failed to communicate",
115 };
116 write!(f, "{}", msg)
117 }
118}
119
120impl StdError for Error {}