1#![no_std]
25
26pub trait OptionExt {
28 type Output;
30 fn unwrap_or_default_log(self) -> Self::Output;
32 fn unwrap_or_else_log(self, f: impl FnOnce() -> Self::Output) -> Self::Output;
34 fn unwrap_or_log(self, default: Self::Output) -> Self::Output;
36}
37
38pub trait ResultExt {
40 type Output;
42 fn unwrap_or_default_log(self) -> Self::Output;
44 fn unwrap_or_else_log(self, f: impl FnOnce() -> Self::Output) -> Self::Output;
46 fn unwrap_or_log(self, default: Self::Output) -> Self::Output;
48}
49
50pub trait ResultExtNoDbg {
55 type Output;
57 fn unwrap_or_default_log(self) -> Self::Output;
59 fn unwrap_or_else_log(self, f: impl FnOnce() -> Self::Output) -> Self::Output;
61 fn unwrap_or_log(self, default: Self::Output) -> Self::Output;
63}
64
65impl<T: Default> OptionExt for Option<T> {
66 type Output = T;
67
68 #[track_caller]
69 fn unwrap_or_default_log(self) -> T {
70 if let Some(x) = self {
71 x
72 } else {
73 option_error();
74 T::default()
75 }
76 }
77
78 #[track_caller]
79 fn unwrap_or_else_log(self, f: impl FnOnce() -> T) -> T {
80 if let Some(x) = self {
81 x
82 } else {
83 option_error();
84 f()
85 }
86 }
87
88 #[track_caller]
89 fn unwrap_or_log(self, default: T) -> T {
90 if let Some(x) = self {
91 x
92 } else {
93 option_error();
94 default
95 }
96 }
97}
98
99impl<T: Default, E: core::fmt::Debug> ResultExt for Result<T, E> {
100 type Output = T;
101
102 #[track_caller]
103 fn unwrap_or_default_log(self) -> T {
104 match self {
105 Ok(x) => x,
106 Err(err) => {
107 result_error(&err);
108 T::default()
109 }
110 }
111 }
112
113 #[track_caller]
114 fn unwrap_or_else_log(self, f: impl FnOnce() -> T) -> T {
115 match self {
116 Ok(x) => x,
117 Err(err) => {
118 result_error(&err);
119 f()
120 }
121 }
122 }
123
124 #[track_caller]
125 fn unwrap_or_log(self, default: T) -> T {
126 match self {
127 Ok(x) => x,
128 Err(err) => {
129 result_error(&err);
130 default
131 }
132 }
133 }
134}
135
136impl<T: Default, E> ResultExtNoDbg for Result<T, E> {
137 type Output = T;
138
139 #[track_caller]
140 fn unwrap_or_default_log(self) -> T {
141 if let Ok(x) = self {
142 x
143 } else {
144 no_dbg_error();
145 T::default()
146 }
147 }
148
149 #[track_caller]
150 fn unwrap_or_else_log(self, f: impl FnOnce() -> T) -> T {
151 if let Ok(x) = self {
152 x
153 } else {
154 no_dbg_error();
155 f()
156 }
157 }
158
159 #[track_caller]
160 fn unwrap_or_log(self, default: T) -> T {
161 if let Ok(x) = self {
162 x
163 } else {
164 no_dbg_error();
165 default
166 }
167 }
168}
169
170#[cold]
171#[inline(never)]
172#[track_caller]
173fn option_error() {
174 let caller = core::panic::Location::caller();
175 log::warn!("{caller} encountered `None`");
176}
177
178#[cold]
179#[inline(never)]
180#[track_caller]
181fn result_error(err: &dyn core::fmt::Debug) {
182 let caller = core::panic::Location::caller();
183 log::warn!("{caller} encountered `Err({err:?})`");
184}
185
186#[cold]
187#[inline(never)]
188#[track_caller]
189fn no_dbg_error() {
190 let caller = core::panic::Location::caller();
191 log::warn!("{caller} encountered `Err(_)`");
192}