Skip to main content

ferrijs_std/utils/
result.rs

1// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2// SPDX-License-Identifier: Apache-2.0
3#![allow(clippy::uninlined_format_args)]
4
5use std::{fmt::Write, result::Result as StdResult};
6
7use rquickjs::{Ctx, Exception, Result};
8
9pub trait ResultExt<T> {
10    fn or_throw_msg(self, ctx: &Ctx, msg: &str) -> Result<T>;
11    fn or_throw_range(self, ctx: &Ctx, msg: &str) -> Result<T>;
12    fn or_throw_type(self, ctx: &Ctx, msg: &str) -> Result<T>;
13    fn or_throw(self, ctx: &Ctx) -> Result<T>;
14}
15
16pub trait OptionExt<T> {
17    fn and_then_ok<U, E, F>(self, f: F) -> StdResult<Option<U>, E>
18    where
19        F: FnOnce(T) -> StdResult<Option<U>, E>;
20
21    fn unwrap_or_else_ok<E, F>(self, f: F) -> StdResult<T, E>
22    where
23        F: FnOnce() -> StdResult<T, E>;
24}
25
26impl<T, E: std::fmt::Display> ResultExt<T> for StdResult<T, E> {
27    fn or_throw_msg(self, ctx: &Ctx, msg: &str) -> Result<T> {
28        self.map_err(|e| {
29            let mut message = String::with_capacity(100);
30            message.push_str(msg);
31            message.push_str(". ");
32            write!(message, "{}", e).unwrap();
33            Exception::throw_message(ctx, &message)
34        })
35    }
36
37    fn or_throw_range(self, ctx: &Ctx, msg: &str) -> Result<T> {
38        self.map_err(|e| {
39            let mut message = String::with_capacity(100);
40            if !message.is_empty() {
41                message.push_str(msg);
42                message.push_str(". ");
43            }
44            write!(message, "{}", e).unwrap();
45            Exception::throw_range(ctx, &message)
46        })
47    }
48
49    fn or_throw_type(self, ctx: &Ctx, msg: &str) -> Result<T> {
50        self.map_err(|e| {
51            let mut message = String::with_capacity(100);
52            if !msg.is_empty() {
53                message.push_str(msg);
54                message.push_str(". ");
55            }
56            write!(message, "{}", e).unwrap();
57            Exception::throw_type(ctx, &message)
58        })
59    }
60
61    fn or_throw(self, ctx: &Ctx) -> Result<T> {
62        self.map_err(|err| Exception::throw_message(ctx, &err.to_string()))
63    }
64}
65
66impl<T> ResultExt<T> for Option<T> {
67    fn or_throw_msg(self, ctx: &Ctx, msg: &str) -> Result<T> {
68        self.ok_or_else(|| Exception::throw_message(ctx, msg))
69    }
70
71    fn or_throw_range(self, ctx: &Ctx, msg: &str) -> Result<T> {
72        self.ok_or_else(|| Exception::throw_range(ctx, msg))
73    }
74
75    fn or_throw_type(self, ctx: &Ctx, msg: &str) -> Result<T> {
76        self.ok_or_else(|| Exception::throw_type(ctx, msg))
77    }
78
79    fn or_throw(self, ctx: &Ctx) -> Result<T> {
80        self.ok_or_else(|| Exception::throw_message(ctx, "Value is not present"))
81    }
82}
83
84impl<T> OptionExt<T> for Option<T> {
85    fn and_then_ok<U, E, F>(self, f: F) -> StdResult<Option<U>, E>
86    where
87        F: FnOnce(T) -> StdResult<Option<U>, E>,
88    {
89        match self {
90            Some(v) => f(v),
91            None => Ok(None),
92        }
93    }
94
95    fn unwrap_or_else_ok<E, F>(self, f: F) -> StdResult<T, E>
96    where
97        F: FnOnce() -> StdResult<T, E>,
98    {
99        match self {
100            Some(v) => Ok(v),
101            None => f(),
102        }
103    }
104}