relay_dynamic_config/
error_boundary.rs1use std::error::Error;
2use std::sync::Arc;
3
4use serde::{Deserialize, Deserializer, Serialize, Serializer};
5use serde_json::Value;
6
7#[derive(Clone, Debug)]
11pub enum ErrorBoundary<T> {
12 Err(Arc<dyn Error + Send + Sync + 'static>),
14 Ok(T),
16}
17
18impl<T> ErrorBoundary<T> {
19 #[inline]
21 #[allow(unused)]
22 pub fn is_ok(&self) -> bool {
23 match *self {
24 Self::Ok(_) => true,
25 Self::Err(_) => false,
26 }
27 }
28
29 #[inline]
31 #[allow(unused)]
32 pub fn is_err(&self) -> bool {
33 !self.is_ok()
34 }
35
36 #[inline]
38 pub fn ok(self) -> Option<T> {
39 match self {
40 ErrorBoundary::Err(_) => None,
41 ErrorBoundary::Ok(value) => Some(value),
42 }
43 }
44
45 pub fn as_ref(&self) -> ErrorBoundary<&T> {
47 match self {
48 Self::Ok(t) => ErrorBoundary::Ok(t),
49 Self::Err(e) => ErrorBoundary::Err(Arc::clone(e)),
50 }
51 }
52
53 #[inline]
55 pub fn unwrap_or_else<F>(self, op: F) -> T
56 where
57 F: FnOnce(&(dyn Error + 'static)) -> T,
58 {
59 match self {
60 Self::Ok(t) => t,
61 Self::Err(e) => op(e.as_ref()),
62 }
63 }
64
65 pub fn get_or_insert_with<F>(&mut self, f: F) -> &mut T
68 where
69 F: FnOnce() -> T,
70 {
71 if let Self::Err(_) = self {
72 *self = Self::Ok(f());
73 }
74
75 match self {
78 Self::Ok(t) => t,
79 Self::Err(_) => unsafe { std::hint::unreachable_unchecked() },
80 }
81 }
82}
83
84impl<T> Default for ErrorBoundary<T>
85where
86 T: Default,
87{
88 fn default() -> Self {
89 Self::Ok(T::default())
90 }
91}
92
93impl<'de, T> Deserialize<'de> for ErrorBoundary<T>
94where
95 T: Deserialize<'de>,
96{
97 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
98 where
99 D: Deserializer<'de>,
100 {
101 let value = Value::deserialize(deserializer)?;
102 Ok(match T::deserialize(value) {
103 Ok(t) => Self::Ok(t),
104 Err(error) => Self::Err(Arc::new(error)),
105 })
106 }
107}
108
109impl<T> Serialize for ErrorBoundary<T>
110where
111 T: Serialize,
112{
113 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
114 where
115 S: Serializer,
116 {
117 let option = match *self {
118 Self::Ok(ref t) => Some(t),
119 Self::Err(_) => None,
120 };
121
122 option.serialize(serializer)
123 }
124}
125
126#[cfg(test)]
127mod tests {
128 use super::*;
129
130 #[test]
131 fn test_deserialize_ok() {
132 let boundary = serde_json::from_str::<ErrorBoundary<u32>>("42").unwrap();
133 assert!(boundary.is_ok());
134 }
135
136 #[test]
137 fn test_deserialize_err() {
138 let boundary = serde_json::from_str::<ErrorBoundary<u32>>("-1").unwrap();
139 assert!(boundary.is_err());
140 }
141
142 #[test]
143 fn test_deserialize_syntax_err() {
144 serde_json::from_str::<ErrorBoundary<u32>>("---")
145 .expect_err("syntax errors should bubble through");
146 }
147
148 #[test]
149 fn test_serialize_ok() {
150 let boundary = ErrorBoundary::Ok(42);
151 assert_eq!(serde_json::to_string(&boundary).unwrap(), "42");
152 }
153
154 #[test]
155 fn test_serialize_err() {
156 let boundary = ErrorBoundary::<u32>::Err(Arc::new(std::fmt::Error));
157 assert_eq!(serde_json::to_string(&boundary).unwrap(), "null");
158 }
159}