ruspiro_error/lib.rs
1/***********************************************************************************************************************
2 * Copyright (c) 2019 by the authors
3 *
4 * Author: André Borrmann
5 * License: Appache License 2.0
6 **********************************************************************************************************************/
7#![doc(html_root_url = "https://docs.rs/ruspiro-error/0.1.1")]
8#![cfg_attr(not(any(test, doctest)), no_std)]
9
10//! # Basic Error trait
11//!
12//! This is more or less the same as found in Rust std library:
13//! [Error](https://doc.rust-lang.org/std/error/trait.Error.html) but made available in `[no_std]` expecting an
14//! allocator to be in place, which provided with [`ruspiro-allocator`](https://crates.io/crates/ruspiro-allocator).
15
16extern crate alloc;
17use alloc::{boxed::Box, string::String};
18use core::fmt::{Debug, Display};
19
20/// The type that shall be used as `Error` type when returning a [`Result`]. This allows the usage of the
21/// `?` operator on functions or methods.
22pub type BoxError = Box<dyn Error + Send>; // + Send + Sync needed ?
23
24/// The generic Error trait. All actual errors implementing this trait also need to implement `Debug`
25/// and `Display` to provide human readable text of the error.
26pub trait Error: Debug + Display + Send {
27 /// the underlaying source of this error, if any. This allows to "stack" errors while keeping
28 /// track to it's root cause
29 fn source(&self) -> Option<&(dyn Error + 'static)> {
30 None
31 }
32}
33
34impl<'a, E: Error + 'a + Send> From<E> for Box<dyn Error + 'a + Send> {
35 /// Conviniently convert an [`Error`] into a boxed `dyn Error`. This allows simple usage of
36 /// `.into()` calls when returning an `Error` type.
37 fn from(orig: E) -> Box<dyn Error + 'a + Send> {
38 Box::new(orig)
39 }
40}
41
42/// The most generic Error type. This can be used if no specific error type will be implemented and returning an erro
43/// only containing an error message is sufficient.
44///
45/// # Example
46/// ```
47/// # use ruspiro_error::*;
48///
49/// fn some_function() -> Result<(), BoxError> {
50/// Err(
51/// GenericError::with_message("Some Message").into()
52/// )
53/// }
54/// ```
55pub struct GenericError {
56 message: Option<String>,
57}
58
59impl GenericError {
60 /// Create a [GenericError] that does not even contain a custom message
61 ///
62 /// # Example
63 /// ```
64 /// # use ruspiro_error::*;
65 ///
66 /// fn some_function() -> Result<(), BoxError> {
67 /// Err(
68 /// GenericError::default().into()
69 /// )
70 /// }
71 /// ```
72 pub fn default() -> Self {
73 GenericError { message: None }
74 }
75
76 /// Crate a [GenericError] containing the custom error message
77 ///
78 /// # Example
79 /// ```
80 /// # use ruspiro_error::*;
81 ///
82 /// fn some_function() -> Result<(), BoxError> {
83 /// Err(
84 /// GenericError::with_message("Some Message").into()
85 /// )
86 /// }
87 /// ```
88 pub fn with_message(message: &str) -> Self {
89 GenericError {
90 message: Some(message.into()),
91 }
92 }
93}
94
95impl Error for GenericError {}
96impl Display for GenericError {
97 fn fmt(&self, fmt: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
98 match &self.message {
99 Some(msg) => write!(fmt, "Error: {}", msg),
100 None => write!(fmt, "Generic Error"),
101 }
102 }
103}
104
105impl Debug for GenericError {
106 fn fmt(&self, fmt: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
107 // re-use the display implementation in case of debug formatting
108 <GenericError as Display>::fmt(self, fmt)
109 }
110}