err_tools/lib.rs
1#[cfg(doctest)]
2#[doc = include_str!("../README.md")]
3pub struct ReadMeDocTests;
4
5pub mod macros;
6pub mod traceable;
7use std::fmt::{Debug, Display};
8use thiserror::*;
9
10#[derive(Error, Debug, Clone, PartialEq)]
11#[error("{} ({})",.s,.e)]
12pub struct SWrap<E: Debug + Display> {
13 e: E,
14 s: &'static str,
15}
16
17#[derive(Error, Debug, Clone, PartialEq)]
18#[error("{} ({})",.s,.e)]
19pub struct SgWrap<E: Debug + Display> {
20 e: E,
21 s: String,
22}
23
24#[derive(Error, Debug, Clone, PartialEq)]
25#[error("{}",.0)]
26pub struct SError(pub &'static str);
27#[derive(Error, Debug, Clone, PartialEq)]
28#[error("{}",.0)]
29pub struct SgError(pub String);
30
31/**
32* Create an anyhow result from a static str
33* Userful for quick comparisons
34*/
35pub fn e_str<T>(s: &'static str) -> anyhow::Result<T> {
36 Err(SError(s).into())
37}
38
39/**
40* Create an anyhow result from a String
41* Userful for putting info in the string
42*/
43pub fn e_string<T>(s: String) -> anyhow::Result<T> {
44 Err(SgError(s).into())
45}
46
47/**
48* This trait applies to any Option and allows easy handling error cases.
49*/
50pub trait OpError: Sized {
51 type V;
52 /**
53 * Convert option to result with 'static str error
54 *
55 * ```
56 *
57 * use err_tools::*;
58 * fn may_error(op:Option<i32>)-> anyhow::Result<i32> {
59 * let n = op.e_str("option must be provided")?;
60 * Ok(n + 2)
61 * }
62 *
63 * assert_eq!(5, may_error(Some(3)).unwrap());
64 *
65 * assert_eq!("option must be provided", may_error(None).err().unwrap().to_string());
66 *
67 * ```
68 */
69 fn e_str(self, s: &'static str) -> anyhow::Result<Self::V>;
70
71 /**
72 * Convert option to result with error from String
73 *
74 * ```
75 *
76 * use err_tools::*;
77 * fn may_error(op:Option<i32>,other:i32)-> anyhow::Result<i32> {
78 * let n = op.e_string(format!("option must be provided with {}", other))?;
79 * Ok(n + other)
80 * }
81 *
82 * assert_eq!(11, may_error(Some(3),8).unwrap());
83 *
84 * assert_eq!("option must be provided with 10", may_error(None,10).err().unwrap().to_string());
85 *
86 * ```
87 */
88 fn e_string(self, s: String) -> anyhow::Result<Self::V>;
89}
90
91/**
92* A trait to make it easy to wrap errors with string errors on the same line
93*/
94impl<V> OpError for Option<V> {
95 type V = V;
96 fn e_str(self, s: &'static str) -> anyhow::Result<Self::V> {
97 self.ok_or(SError(s).into())
98 }
99 fn e_string(self, s: String) -> anyhow::Result<Self::V> {
100 self.ok_or(SgError(s).into())
101 }
102}
103
104pub trait ResError: Sized {
105 type V;
106 type E: Debug + Display + Send + Sync + 'static;
107
108 /**
109 * Convert option to result with error from String
110 *
111 * ```
112 *
113 * use err_tools::*;
114 * fn may_error(res:Result<i32,SError>)-> anyhow::Result<i32> {
115 * let n = res.e_str("OK must be provided")?;
116 * Ok(n + 2)
117 * }
118 *
119 * assert_eq!(5, may_error(Ok(3)).unwrap());
120 *
121 * assert_eq!("OK must be provided (no num)",
122 * may_error(Err(SError("no num"))).err().unwrap().to_string()
123 * );
124 *
125 * ```
126 */
127 fn e_str(self, s: &'static str) -> anyhow::Result<Self::V>;
128
129 /**
130 * Convert option to result with error from String
131 *
132 * ```
133 *
134 * use err_tools::*;
135 * fn may_error(res:Result<i32,SError>,other:i32)-> anyhow::Result<i32> {
136 * let n = res.e_string(format!("OK must be provided with {}",other))?;
137 * Ok(n + other)
138 *
139 * }
140 *
141 * assert_eq!(9, may_error(Ok(3),6).unwrap());
142 *
143 * assert_eq!("OK must be provided with 10 (no num)",
144 * may_error(Err(SError("no num")),10).err().unwrap().to_string()
145 * );
146 *
147 * ```
148 */
149 fn e_string(self, s: String) -> anyhow::Result<Self::V>;
150}
151
152impl<T, E: Debug + Display + Sync + Send + 'static> ResError for Result<T, E> {
153 type V = T;
154 type E = E;
155 fn e_str(self, s: &'static str) -> anyhow::Result<Self::V> {
156 self.map_err(|e| SWrap { s, e }.into())
157 }
158 fn e_string(self, s: String) -> anyhow::Result<Self::V> {
159 self.map_err(|e| SgWrap { s, e }.into())
160 }
161}