ferrijs_std/utils/
result.rs1#![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}