Skip to main content

thruput_sdk/
throw.rs

1/// Extension trait for replacing an error with a contract exception.
2pub trait OrThrow<T> {
3    /// On `Err`, throw `exn` as a contract exception. On `Ok`, return the value.
4    fn or_throw<E: crate::Exn>(self, exn: E) -> T;
5}
6
7impl<T, Err> OrThrow<T> for Result<T, Err> {
8    #[cfg_attr(not(target_arch = "riscv32"), track_caller)]
9    fn or_throw<E: crate::Exn>(self, exn: E) -> T {
10        match self {
11            Ok(v) => v,
12            Err(_) => throw(exn),
13        }
14    }
15}
16
17impl<T> OrThrow<T> for Option<T> {
18    #[cfg_attr(not(target_arch = "riscv32"), track_caller)]
19    fn or_throw<E: crate::Exn>(self, exn: E) -> T {
20        match self {
21            Some(v) => v,
22            None => throw(exn),
23        }
24    }
25}
26
27#[cfg_attr(not(target_arch = "riscv32"), track_caller)]
28pub fn throw<E>(exn: E) -> !
29where
30    E: crate::Exn,
31{
32    let exn = crate::exn::cross_exn::ContractExn::new(exn);
33    crate::contract_abort_encoded(&exn)
34}
35
36#[cfg(test)]
37mod tests {
38    use super::*;
39    use crate::exn::Exn;
40    use crate::xdr::*;
41
42    #[derive(Debug, Clone, PartialEq, ReadXDR, WriteXDR)]
43    #[repr(i32)]
44    enum TestExn {
45        Boom = 1,
46    }
47    impl Exn for TestExn {
48        const SELECTOR: u64 = 0xDEAD;
49    }
50
51    #[test]
52    fn or_throw_ok_returns_value() {
53        let result: Result<i32, &str> = Ok(42);
54        assert_eq!(result.or_throw(TestExn::Boom), 42);
55    }
56}