Oregami
Repositories/oxedyne/fe2o3

oxedyne/fe2o3/fe2o3_core/src/macros/fallible.rs

7.0 KiB, 55 runs

created by r1870400018:98, which is this file's identity for as long as the history lasts, whatever it is later renamed to

download · who wrote it · its history

1#[macro_export]
2/// Shortcut for attempt to convert type.
3///
4///```
5/// use oxedyne_fe2o3_core::prelude::*;
6///
7/// fn main() -> Outcome<()> {
8/// let n = 42u32;
9/// let n1 = try_into!(usize, n);
10/// let n2 = res!(TryInto::<usize>::try_into(n));
11/// assert_eq!(n1, n2);
12/// Ok(())
13/// }
14///
15///```
16macro_rules! try_into {
17 ($typ:tt, $expr:expr) => {
18 match TryInto::<$typ>::try_into($expr) {
19 Ok(v) => v,
20 Err(e) => return Err(err!(e,
21 "Could not convert {:?} into {:?}.", $expr, std::any::type_name::<$typ>();
22 Bug, Conversion)),
23 }
24 }
25}
26
27#[macro_export]
28/// Shortcut for attempt to add integers that can overflow.
29///
30///```
31/// use oxedyne_fe2o3_core::prelude::*;
32///
33/// fn main() -> Outcome<()> {
34/// //let sum = try_add!(255u8, 1); // Will return an overflow error
35/// let sum = try_add!(254u8, 1); // No error, returns value
36/// Ok(())
37/// }
38///
39///```
40macro_rules! try_add {
41 ($n1:expr, $n2:expr $(,)?) => {
42 match $n1.checked_add($n2) {
43 Some(result) => result,
44 None => return Err(err!(
45 "Attempt to add {} and {} (type {}) resulted in integer overflow.",
46 $n1, $n2, fmt_typ!($n1);
47 Integer, Overflow)),
48 }
49 }
50}
51
52#[macro_export]
53/// Shortcut for attempt to subtract integers that can underflow.
54///
55///```
56/// use oxedyne_fe2o3_core::prelude::*;
57///
58/// fn main() -> Outcome<()> {
59/// //let sum = try_sub!(1u8, 2); // Will return an overflow error
60/// let sum = try_sub!(2u8, 1); // No error, returns value
61/// Ok(())
62/// }
63///
64///```
65macro_rules! try_sub {
66 ($n1:expr, $n2:expr $(,)?) => {
67 match $n1.checked_sub($n2) {
68 Some(result) => result,
69 None => return Err(err!(
70 "Attempt to subtract {} from {} (type {}) resulted in integer underflow.",
71 $n2, $n1, fmt_typ!($n1);
72 Integer, Underflow)),
73 }
74 }
75}
76
77#[macro_export]
78/// Shortcut for attempt to multiply integers that can overflow.
79///
80///```
81/// use oxedyne_fe2o3_core::prelude::*;
82///
83/// fn main() -> Outcome<()> {
84/// //let prod = try_mul!(17u8, 17); // Will return an overflow error
85/// let prod = try_mul!(15u8, 15); // No error, returns value
86/// Ok(())
87/// }
88///
89///```
90macro_rules! try_mul {
91 ($n1:expr, $n2:expr $(,)?) => {
92 match $n1.checked_mul($n2) {
93 Some(result) => result,
94 None => return Err(err!(
95 "Attempt to multiply {} and {} (type {}) resulted in integer overflow.",
96 $n1, $n2, fmt_typ!($n1);
97 Integer, Overflow)),
98 }
99 }
100}
101
102#[macro_export]
103/// Shortcut for attempt to divide integers, checking for division by zero.
104///
105///```
106/// use oxedyne_fe2o3_core::prelude::*;
107///
108/// fn main() -> Outcome<()> {
109/// //let div = try_div!(17u8, 0); // Will return an error
110/// let div = try_div!(15u8, 4); // No error, returns value
111/// Ok(())
112/// }
113///
114///```
115macro_rules! try_div {
116 ($n1:expr, $n2:expr $(,)?) => {
117 match $n1.checked_div($n2) {
118 Some(result) => result,
119 None => return Err(err!(
120 "Attempt to divide {} by {} (type {}).",
121 $n1, $n2, fmt_typ!($n1);
122 Integer, ZeroDenominator)),
123 }
124 }
125}
126
127#[macro_export]
128/// Shortcut for attempt to find the remainder after division, checking for division by zero.
129///
130///```
131/// use oxedyne_fe2o3_core::prelude::*;
132///
133/// fn main() -> Outcome<()> {
134/// //let rem = try_rem!(17u8, 0); // Will return an error
135/// let rem = try_rem!(15u8, 4); // No error, returns value
136/// Ok(())
137/// }
138///
139///```
140macro_rules! try_rem {
141 ($n1:expr, $n2:expr $(,)?) => {
142 match $n1.checked_rem($n2) {
143 Some(result) => result,
144 None => return Err(err!(
145 "Attempt to find the remainder when {} is divided by {} (type {}).",
146 $n1, $n2, fmt_typ!($n1);
147 Integer, ZeroDenominator)),
148 }
149 }
150}
151
152#[macro_export]
153/// Shortcut for check on whether the given expression fits within range. Intended for numbers but
154/// works for anything that is `std::cmp::PartialOrd`. The user is responsible for ensuring valid
155/// specification or inference of types.
156///
157///```
158/// use oxedyne_fe2o3_core::prelude::*;
159///
160/// fn main() -> Outcome<()> {
161/// //let n = try_range!(3u8, 5u8, 17u8); // Will return an error
162/// let n = try_range!(6u8, 5u8, 17u8); // No error, returns 6u8
163/// Ok(())
164/// }
165///
166///```
167macro_rules! try_range {
168 ($n:expr, $min:expr, $max:expr $(,)?) => {
169 match (&$n, &$min, &$max) {
170 (n, min, max) if std::cmp::PartialOrd::lt(n, min) || std::cmp::PartialOrd::gt(n, max) => {
171 return Err(err!(
172 "{} is outside range [{}, {}].", $n, $min, $max;
173 Numeric, Range));
174 }
175 _ => $n,
176 }
177 };
178}
179
180/// Implement some basic traits for native integers.
181#[macro_export]
182macro_rules! impls_for_native_integer {
183 ($t:ty, $n:literal) => {
184
185 impl oxedyne_fe2o3_core::byte::FromBytes for $t {
186 fn from_bytes(buf: &[u8]) -> Outcome<(Self, usize)> {
187 const BYTE_LEN: usize = std::mem::size_of::<$t>();
188 if buf.len() < BYTE_LEN {
189 return Err(err!(
190 "Not enough bytes to decode, require at least {} \
191 for a {}, slice is of length {}.",
192 BYTE_LEN, std::any::type_name::<Self>(), buf.len();
193 Bytes, Invalid, Input, Decode, Missing));
194 }
195 let n = <$t>::from_be_bytes(res!(
196 <[u8; BYTE_LEN]>::try_from(&buf[0..BYTE_LEN]),
197 Decode, Bytes, Integer,
198 ));
199 Ok((n, BYTE_LEN))
200 }
201 }
202
203 impl oxedyne_fe2o3_core::byte::FromByteArray for $t {
204 fn from_byte_array<const L: usize>(buf: [u8; L]) -> Outcome<Self> {
205 const BYTE_LEN: usize = std::mem::size_of::<$t>();
206 if L < BYTE_LEN {
207 return Err(err!(
208 "Not enough bytes to decode, require at least {} \
209 for a {}, array is of length {}.",
210 BYTE_LEN, std::any::type_name::<Self>(), L;
211 Bytes, Invalid, Input, Decode, Missing));
212 }
213 Ok(<$t>::from_be_bytes(res!(
214 <[u8; BYTE_LEN]>::try_from(&buf[0..BYTE_LEN]),
215 Decode, Bytes, Integer,
216 )))
217 }
218 }
219
220 impl oxedyne_fe2o3_core::byte::ToBytes for $t {
221 fn to_bytes(&self, mut buf: Vec<u8>) -> Outcome<Vec<u8>> {
222 buf.extend_from_slice(&self.to_be_bytes());
223 Ok(buf)
224 }
225 }
226
227 impl oxedyne_fe2o3_core::byte::ToByteArray<$n> for $t {
228 fn to_byte_array(&self) -> [u8; $n] {
229 self.to_be_bytes()
230 }
231 }
232
233 impl oxedyne_fe2o3_core::string::ToHexString for $t {}
234 }
235}