Skip to main content

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}