smooth_operator/
lib.rs

1#![cfg_attr(not(feature = "std"), no_std)]
2
3#[doc(inline)]
4pub use smooth_operator_impl::checked;
5
6/// Checked arithmetics error.
7#[derive(Copy, Clone)]
8pub struct Error {
9    /// The original expression given to the [`checked`] macro.
10    pub expr: &'static str,
11    // Index of the operator that has failed within the `expr`.
12    #[doc(hidden)]
13    pub __op_ix: usize,
14    // Length of the operator that has failed within the `expr`.
15    #[doc(hidden)]
16    pub __op_len: usize,
17}
18
19#[cfg(feature = "std")]
20impl std::error::Error for Error {}
21
22impl core::fmt::Debug for Error {
23    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
24        f.debug_struct("Error")
25            .field("expr", &self.expr)
26            .finish_non_exhaustive()
27    }
28}
29
30impl core::fmt::Display for Error {
31    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
32        let Error {
33            expr,
34            __op_ix: op_ix,
35            __op_len: op_len,
36        } = self;
37        let (prefix, rest) = expr.split_at(op_ix.saturating_sub(*op_len));
38        let (op, suffix) = rest.split_at(*op_len);
39        write!(f, "Failure in: {prefix} 》{op}《 {suffix}")
40    }
41}
42
43#[cfg(test)]
44mod test {
45    use super::checked;
46
47    #[test]
48    fn test_basic_use() {
49        let result = checked!(1_u64 + 2 + 3).unwrap();
50        assert_eq!(result, 6);
51
52        let mut accum = 0i32;
53        checked!(accum += 1i32 + 1 + 1 + 1).unwrap();
54        assert_eq!(accum, 4);
55
56        let x = u64::MAX - 1;
57        let result = checked!(x + 1 + 1).unwrap_err().to_string();
58        assert_eq!(result, "Failure in: x + 1  》+《  1");
59
60        let result = checked!(-1_i64).unwrap();
61        assert_eq!(result, -1);
62
63        let result = checked!(-i64::MIN).unwrap_err().to_string();
64        assert_eq!(result, "Failure in:  》-《  i64 :: MIN");
65
66        let result = checked!(u64::MAX << 123).unwrap_err().to_string();
67        assert_eq!(result, "Failure in: u64 :: MAX  》<<《  123");
68    }
69}