dcrypt_api/error/
traits.rs1use super::registry::ERROR_REGISTRY;
4use super::types::{Error, Result};
5use subtle::{Choice, ConditionallySelectable};
6
7pub trait ResultExt<T, E>: Sized {
9 fn wrap_err<F, E2>(self, f: F) -> core::result::Result<T, E2>
11 where
12 F: FnOnce() -> E2;
13
14 fn with_context(self, context: &'static str) -> Result<T>
16 where
17 E: Into<Error>;
18
19 #[cfg(feature = "std")]
20 fn with_message(self, message: impl Into<String>) -> Result<T>
22 where
23 E: Into<Error>;
24}
25
26impl<T, E> ResultExt<T, E> for core::result::Result<T, E> {
27 fn wrap_err<F, E2>(self, f: F) -> core::result::Result<T, E2>
28 where
29 F: FnOnce() -> E2,
30 {
31 self.map_err(|_| f())
32 }
33
34 fn with_context(self, context: &'static str) -> Result<T>
35 where
36 E: Into<Error>,
37 {
38 self.map_err(|e| {
39 let err = e.into();
40 err.with_context(context)
41 })
42 }
43
44 #[cfg(feature = "std")]
45 fn with_message(self, message: impl Into<String>) -> Result<T>
46 where
47 E: Into<Error>,
48 {
49 self.map_err(|e| {
50 let err = e.into();
51 err.with_message(message)
52 })
53 }
54}
55
56pub trait SecureErrorHandling<T, E>: Sized {
58 fn secure_unwrap<F>(self, default: T, on_error: F) -> T
60 where
61 F: FnOnce() -> E;
62}
63
64impl<T, E> SecureErrorHandling<T, E> for core::result::Result<T, E> {
65 fn secure_unwrap<F>(self, default: T, on_error: F) -> T
66 where
67 F: FnOnce() -> E,
68 {
69 match self {
70 Ok(value) => value,
71 Err(_) => {
72 let error = on_error();
74 ERROR_REGISTRY.store(error);
75 default
76 }
77 }
78 }
79}
80
81pub trait ConstantTimeResult<T, E> {
83 fn ct_is_ok(&self) -> bool;
85
86 fn ct_is_err(&self) -> bool;
88
89 fn ct_map<U, F, G>(self, ok_fn: F, err_fn: G) -> U
92 where
93 F: FnOnce(T) -> U,
94 G: FnOnce(E) -> U,
95 U: ConditionallySelectable;
96}
97
98impl<T, E> ConstantTimeResult<T, E> for core::result::Result<T, E> {
99 fn ct_is_ok(&self) -> bool {
100 let is_ok_choice = match self {
102 Ok(_) => Choice::from(1u8),
103 Err(_) => Choice::from(0u8),
104 };
105
106 let mut result = false;
109 result.conditional_assign(&true, is_ok_choice);
110 result
111 }
112
113 fn ct_is_err(&self) -> bool {
114 let is_ok = self.ct_is_ok();
116
117 let is_ok_choice = Choice::from(is_ok as u8);
119
120 let mut result = true;
122 result.conditional_assign(&false, is_ok_choice);
123 result
124 }
125
126 fn ct_map<U, F, G>(self, ok_fn: F, err_fn: G) -> U
127 where
128 F: FnOnce(T) -> U,
129 G: FnOnce(E) -> U,
130 U: ConditionallySelectable,
131 {
132 match self {
135 Ok(t) => {
136 ok_fn(t)
141 }
142 Err(e) => {
143 err_fn(e)
146 }
147 }
148 }
154}
155
156trait ConditionalAssign {
158 fn conditional_assign(&mut self, other: &Self, choice: Choice);
159}
160
161impl ConditionalAssign for bool {
162 fn conditional_assign(&mut self, other: &bool, choice: Choice) {
163 let self_as_u8 = *self as u8;
165 let other_as_u8 = *other as u8;
166
167 let result = u8::conditional_select(&self_as_u8, &other_as_u8, choice);
169
170 *self = result != 0;
172 }
173}