1#![doc(html_root_url = "https://docs.rs/this-is-fine/0.0.1")]
15#![warn(clippy::pedantic)]
16#![allow(clippy::semicolon_if_nothing_returned)]
17#![no_std]
18
19use core::{
20 fmt::Debug,
21 ops::{Deref, DerefMut},
22};
23
24#[cfg(doctest)]
25pub mod readme {
26 doc_comment::doctest!("../README.md");
27}
28
29#[allow(clippy::doc_markdown)]
34#[must_use]
37pub type Fine<T, E> = (T, Result<(), E>);
38
39pub fn from_inverse<T, E>((value, error): (T, Option<E>)) -> Fine<T, E> {
41 (value, error.map_or(Ok(()), Err))
42}
43
44pub mod prelude {
45 pub use crate::{
46 FineExt, FineExtWhereEDebug, FineExtWhereTDebug, FineExtWhereTDeref, FineExtWhereTDerefMut,
47 FineTransposeExt,
48 };
49}
50
51pub trait FineExt<T, E> {
52 #[must_use]
54 fn is_ok(&self) -> bool;
55
56 #[must_use]
58 fn is_err(&self) -> bool;
59
60 fn ok(self) -> Option<T>;
64
65 fn fine(self) -> T;
67
68 #[must_use = "It's unclear whether you meant to discard the error. Prefer `.fine()` if you do."]
72 fn err(self) -> Option<E>;
73
74 fn not_fine(self) -> Result<T, E>;
80
81 fn as_ref(&self) -> Fine<&T, &E>;
85
86 fn as_mut(&mut self) -> Fine<&mut T, &mut E>;
90
91 fn map<U, F>(self, op: F) -> Fine<U, E>
95 where
96 F: FnOnce(T) -> U;
97
98 fn map_err<F, O>(self, op: O) -> Fine<T, F>
102 where
103 O: FnOnce(E) -> F;
104}
105impl<T, E> FineExt<T, E> for Fine<T, E> {
106 fn is_ok(&self) -> bool {
107 self.1.is_ok()
108 }
109
110 fn is_err(&self) -> bool {
111 self.1.is_err()
112 }
113
114 fn ok(self) -> Option<T> {
115 self.1.is_ok().then(|| self.0)
116 }
117
118 fn fine(self) -> T {
119 self.0
120 }
121
122 fn err(self) -> Option<E> {
123 self.1.err()
124 }
125
126 fn not_fine(self) -> Result<T, E> {
127 self.1?;
128 Ok(self.0)
129 }
130
131 fn as_ref(&self) -> Fine<&T, &E> {
132 (&self.0, self.1.as_ref().err().map_or(Ok(()), Err))
133 }
134
135 fn as_mut(&mut self) -> Fine<&mut T, &mut E> {
136 (&mut self.0, self.1.as_mut().err().map_or(Ok(()), Err))
137 }
138
139 fn map<U, F>(self, op: F) -> Fine<U, E>
140 where
141 F: FnOnce(T) -> U,
142 {
143 (op(self.0), self.1)
144 }
145
146 fn map_err<F, O>(self, op: O) -> Fine<T, F>
147 where
148 O: FnOnce(E) -> F,
149 {
150 (self.0, self.1.map_err(op))
151 }
152}
153
154pub trait FineExtWhereEDebug<T, E>
155where
156 E: Debug,
157{
158 #[track_caller]
164 fn expect(self, msg: &str) -> T;
165
166 #[track_caller]
172 fn unwrap(self) -> T;
173}
174impl<T, E> FineExtWhereEDebug<T, E> for Fine<T, E>
175where
176 E: Debug,
177{
178 #[track_caller]
179 fn expect(self, msg: &str) -> T {
180 self.1.expect(msg);
181 self.0
182 }
183
184 #[track_caller]
185 fn unwrap(self) -> T {
186 self.1.unwrap();
187 self.0
188 }
189}
190
191pub trait FineExtWhereTDebug<T, E>
192where
193 T: Debug,
194{
195 #[track_caller]
201 fn expect_err(self, msg: &str) -> E;
202
203 #[track_caller]
209 fn unwrap_err(self) -> E;
210}
211impl<T, E> FineExtWhereTDebug<T, E> for Fine<T, E>
212where
213 T: Debug,
214{
215 #[track_caller]
216 fn expect_err(self, msg: &str) -> E {
217 self.not_fine().expect_err(msg)
218 }
219
220 #[track_caller]
221 fn unwrap_err(self) -> E {
222 self.not_fine().unwrap_err()
223 }
224}
225
226pub trait FineExtWhereTDeref<T, E>
227where
228 T: Deref,
229{
230 fn as_deref(&self) -> Fine<&<T as Deref>::Target, &E>;
232}
233impl<T, E> FineExtWhereTDeref<T, E> for Fine<T, E>
234where
235 T: Deref,
236{
237 fn as_deref(&self) -> Fine<&<T as Deref>::Target, &E> {
238 self.as_ref().map(Deref::deref)
239 }
240}
241
242pub trait FineExtWhereTDerefMut<T, E>
243where
244 T: DerefMut,
245{
246 fn as_deref_mut(&mut self) -> Fine<&mut <T as Deref>::Target, &mut E>;
248}
249impl<T, E> FineExtWhereTDerefMut<T, E> for Fine<T, E>
250where
251 T: DerefMut,
252{
253 fn as_deref_mut(&mut self) -> Fine<&mut <T as Deref>::Target, &mut E> {
254 self.as_mut().map(DerefMut::deref_mut)
255 }
256}
257
258pub trait FineTransposeExt<T, E0, E1> {
259 fn transpose(self) -> Fine<Fine<T, E1>, E0>;
261}
262impl<T, E0, E1> FineTransposeExt<T, E0, E1> for Fine<Fine<T, E0>, E1> {
263 fn transpose(self) -> Fine<Fine<T, E1>, E0> {
264 let ((t, e0), e1) = self;
265 ((t, e1), e0)
266 }
267}