1use std::any::Any;
8use std::error::Error;
9use std::fmt::{self, Debug, Display};
10use misc::{Saturated, InvalidSentinel, SignedInfinity};
11
12macro_rules! Desc {
13 (
14 ($desc:expr)
15 pub struct $name:ident<$t:ident> $_body:tt;
16 ) => {
17 impl<$t> Display for $name<$t> {
18 fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
19 write!(fmt, $desc)
20 }
21 }
22
23 impl<$t> Error for $name<$t> where $t: Any {
24 fn description(&self) -> &str {
25 $desc
26 }
27 }
28 };
29}
30
31macro_rules! DummyDebug {
32 (
33 () pub enum $name:ident<$t:ident> {
34 $(#[doc=$_doc:tt] $vname:ident($_vpay:ident),)+
35 }
36 ) => {
37 impl<$t> Debug for $name<$t> {
38 fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
39 let msg = match *self {
40 $($name::$vname(_) => stringify!($vname),)+
41 };
42 write!(fmt, concat!(stringify!($name), "::{}(..)"), msg)
43 }
44 }
45 };
46
47 (
48 () pub struct $name:ident<$t:ident>(pub $_pay:ident);
49 ) => {
50 impl<$t> Debug for $name<$t> {
51 fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
52 write!(fmt, concat!(stringify!($name), "(..)"))
53 }
54 }
55 };
56}
57
58macro_rules! EnumDesc {
59 (
60 ($($vname:ident => $vdesc:expr,)+)
61 pub enum $name:ident $_body:tt
62 ) => {
63 impl Display for $name {
64 fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
65 write!(fmt, "{}",
66 match *self { $($name::$vname => $vdesc,)+ })
67 }
68 }
69
70 impl Error for $name {
71 fn description(&self) -> &str {
72 match *self { $($name::$vname => $vdesc,)+ }
73 }
74 }
75 };
76
77 (
78 ($($vname:ident => $vdesc:expr,)+)
79 pub enum $name:ident<$t:ident> $_body:tt
80 ) => {
81 impl<$t> Display for $name<$t> {
82 fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
83 write!(fmt, "{}",
84 match *self { $($name::$vname(..) => $vdesc,)+ })
85 }
86 }
87
88 impl<$t> Error for $name<$t> where $t: Any {
89 fn description(&self) -> &str {
90 match *self { $($name::$vname(..) => $vdesc,)+ }
91 }
92 }
93 };
94}
95
96macro_rules! FromName {
97 (
98 ($fname:ident)
99 pub enum $name:ident<$t:ident> $_body:tt
100 ) => {
101 impl<$t> From<$fname<$t>> for $name<$t> {
102 #[inline]
103 fn from(e: $fname<$t>) -> Self {
104 $name::$fname(e.into_inner())
105 }
106 }
107 };
108
109 (
110 ($fname:ident<$t:ident>)
111 pub enum $name:ident $_body:tt
112 ) => {
113 impl<$t> From<$fname<$t>> for $name {
114 #[inline]
115 fn from(_: $fname<$t>) -> Self {
116 $name::$fname
117 }
118 }
119 };
120}
121
122macro_rules! FromNoError {
123 (
124 () pub enum $name:ident $_body:tt
125 ) => {
126 impl From<NoError> for $name {
127 #[inline]
128 fn from(_: NoError) -> Self {
129 panic!(concat!("cannot convert NoError into ", stringify!($name)))
130 }
131 }
132 };
133
134 (
135 () pub enum $name:ident<$t:ident> $_body:tt
136 ) => {
137 impl<$t> From<NoError> for $name<$t> {
138 fn from(_: NoError) -> Self {
139 panic!(concat!("cannot convert NoError into ", stringify!($name)))
140 }
141 }
142 };
143
144 (
145 () pub struct $name:ident<$t:ident> $_body:tt;
146 ) => {
147 impl<$t> From<NoError> for $name<$t> {
148 fn from(_: NoError) -> Self {
149 panic!(concat!("cannot convert NoError into ", stringify!($name)))
150 }
151 }
152 };
153}
154
155macro_rules! FromRemap {
156 (
157 ($from:ident($($vname:ident),+))
158 pub enum $name:ident $_body:tt
159 ) => {
160 impl From<$from> for $name {
161 #[inline]
162 fn from(e: $from) -> Self {
163 match e {
164 $($from::$vname => $name::$vname,)+
165 }
166 }
167 }
168 };
169
170 (
171 ($from:ident<$t:ident>($($vname:ident),+))
172 pub enum $name:ident $_body:tt
173 ) => {
174 impl<$t> From<$from<$t>> for $name {
175 #[inline]
176 fn from(e: $from<$t>) -> Self {
177 match e {
178 $($from::$vname(..) => $name::$vname,)+
179 }
180 }
181 }
182 };
183
184 (
185 ($from:ident($($vname:ident),+))
186 pub enum $name:ident<$t:ident> $_body:tt
187 ) => {
188 impl<$t> From<$from<$t>> for $name<$t> {
189 #[inline]
190 fn from(e: $from<$t>) -> Self {
191 match e {
192 $($from::$vname(v) => $name::$vname(v),)+
193 }
194 }
195 }
196 };
197}
198
199macro_rules! IntoInner {
200 (
201 () pub enum $name:ident<$t:ident> {
202 $(#[doc=$_doc:tt] $vname:ident($_vpay:ident),)+
203 }
204 ) => {
205 impl<$t> $name<$t> {
206 #[inline]
208 pub fn into_inner(self) -> $t {
209 match self { $($name::$vname(v))|+ => v }
210 }
211 }
212 };
213
214 (
215 () pub struct $name:ident<$t:ident>(pub $_pay:ident);
216 ) => {
217 impl<$t> $name<$t> {
218 #[inline]
220 pub fn into_inner(self) -> $t {
221 self.0
222 }
223 }
224 };
225}
226
227custom_derive!{
228 #[derive(
234 Copy, Clone, Eq, PartialEq, Ord, PartialOrd,
235 IntoInner, DummyDebug, FromNoError,
236 EnumDesc(
237 NegOverflow => "conversion resulted in negative overflow",
238 PosOverflow => "conversion resulted in positive overflow",
239 Unrepresentable => "could not convert unrepresentable value",
240 ),
241 FromName(Unrepresentable),
242 FromName(NegOverflow),
243 FromName(PosOverflow),
244 FromRemap(RangeError(NegOverflow, PosOverflow))
245 )]
246 pub enum GeneralError<T> {
247 NegOverflow(T),
249
250 PosOverflow(T),
252
253 Unrepresentable(T),
255 }
256}
257
258impl<T> From<FloatError<T>> for GeneralError<T> {
259 #[inline]
260 fn from(e: FloatError<T>) -> GeneralError<T> {
261 use self::FloatError as F;
262 use self::GeneralError as G;
263 match e {
264 F::NegOverflow(v) => G::NegOverflow(v),
265 F::PosOverflow(v) => G::PosOverflow(v),
266 F::NotANumber(v) => G::Unrepresentable(v),
267 }
268 }
269}
270
271custom_derive! {
272 #[derive(
278 Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug,
279 FromNoError,
280 EnumDesc(
281 NegOverflow => "conversion resulted in negative overflow",
282 PosOverflow => "conversion resulted in positive overflow",
283 Unrepresentable => "could not convert unrepresentable value",
284 ),
285 FromName(Unrepresentable<T>),
286 FromName(NegOverflow<T>),
287 FromName(PosOverflow<T>),
288 FromRemap(RangeErrorKind(NegOverflow, PosOverflow)),
289 FromRemap(RangeError<T>(NegOverflow, PosOverflow)),
290 FromRemap(GeneralError<T>(NegOverflow, PosOverflow, Unrepresentable))
291 )]
292 pub enum GeneralErrorKind {
293 NegOverflow,
295
296 PosOverflow,
298
299 Unrepresentable,
301 }
302}
303
304impl<T> From<FloatError<T>> for GeneralErrorKind {
305 #[inline]
306 fn from(e: FloatError<T>) -> GeneralErrorKind {
307 use self::FloatError as F;
308 use self::GeneralErrorKind as G;
309 match e {
310 F::NegOverflow(..) => G::NegOverflow,
311 F::PosOverflow(..) => G::PosOverflow,
312 F::NotANumber(..) => G::Unrepresentable,
313 }
314 }
315}
316
317#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug)]
323pub enum NoError {}
324
325impl Display for NoError {
326 fn fmt(&self, _: &mut fmt::Formatter) -> Result<(), fmt::Error> {
327 unreachable!()
328 }
329}
330
331impl Error for NoError {
332 fn description(&self) -> &str {
333 unreachable!()
334 }
335}
336
337custom_derive! {
338 #[derive(
340 Copy, Clone, Eq, PartialEq, Ord, PartialOrd,
341 IntoInner, DummyDebug, FromNoError,
342 Desc("could not convert unrepresentable value")
343 )]
344 pub struct Unrepresentable<T>(pub T);
345}
346
347custom_derive! {
348 #[derive(
350 Copy, Clone, Eq, PartialEq, Ord, PartialOrd,
351 IntoInner, DummyDebug, FromNoError,
352 Desc("conversion resulted in negative overflow")
353 )]
354 pub struct NegOverflow<T>(pub T);
355}
356
357custom_derive! {
358 #[derive(
360 Copy, Clone, Eq, PartialEq, Ord, PartialOrd,
361 IntoInner, DummyDebug, FromNoError,
362 Desc("conversion resulted in positive overflow")
363 )]
364 pub struct PosOverflow<T>(pub T);
365}
366
367custom_derive! {
368 #[derive(
372 Copy, Clone, Eq, PartialEq, Ord, PartialOrd,
373 IntoInner, DummyDebug, FromNoError,
374 EnumDesc(
375 NegOverflow => "conversion resulted in negative overflow",
376 PosOverflow => "conversion resulted in positive overflow",
377 NotANumber => "conversion target does not support not-a-number",
378 ),
379 FromName(NegOverflow),
380 FromName(PosOverflow),
381 FromRemap(RangeError(NegOverflow, PosOverflow))
382 )]
383 pub enum FloatError<T> {
384 NegOverflow(T),
386
387 PosOverflow(T),
389
390 NotANumber(T),
392 }
393}
394
395custom_derive! {
396 #[derive(
400 Copy, Clone, Eq, PartialEq, Ord, PartialOrd,
401 IntoInner, DummyDebug, FromNoError,
402 EnumDesc(
403 NegOverflow => "conversion resulted in negative overflow",
404 PosOverflow => "conversion resulted in positive overflow",
405 ),
406 FromName(NegOverflow),
407 FromName(PosOverflow)
408 )]
409 pub enum RangeError<T> {
410 NegOverflow(T),
412
413 PosOverflow(T),
415 }
416}
417
418custom_derive! {
419 #[derive(
425 Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug,
426 FromNoError,
427 EnumDesc(
428 NegOverflow => "conversion resulted in negative overflow",
429 PosOverflow => "conversion resulted in positive overflow",
430 ),
431 FromName(NegOverflow<T>),
432 FromName(PosOverflow<T>),
433 FromRemap(RangeError<T>(NegOverflow, PosOverflow))
434 )]
435 pub enum RangeErrorKind {
436 NegOverflow,
438
439 PosOverflow,
441 }
442}
443
444pub trait Saturate {
448 type Output;
450
451 fn saturate(self) -> Self::Output;
459}
460
461impl<T, U> Saturate for Result<T, FloatError<U>>
462where T: Saturated {
463 type Output = Result<T, Unrepresentable<U>>;
464
465 #[inline]
466 fn saturate(self) -> Self::Output {
467 use self::FloatError::*;
468 match self {
469 Ok(v) => Ok(v),
470 Err(NegOverflow(_)) => Ok(T::saturated_min()),
471 Err(PosOverflow(_)) => Ok(T::saturated_max()),
472 Err(NotANumber(v)) => Err(Unrepresentable(v))
473 }
474 }
475}
476
477impl<T, U> Saturate for Result<T, RangeError<U>>
478where T: Saturated {
479 type Output = Result<T, NoError>;
480
481 #[inline]
482 fn saturate(self) -> Self::Output {
483 use self::RangeError::*;
484 match self {
485 Ok(v) => Ok(v),
486 Err(NegOverflow(_)) => Ok(T::saturated_min()),
487 Err(PosOverflow(_)) => Ok(T::saturated_max())
488 }
489 }
490}
491
492impl<T> Saturate for Result<T, RangeErrorKind>
493where T: Saturated {
494 type Output = Result<T, NoError>;
495
496 #[inline]
497 fn saturate(self) -> Self::Output {
498 use self::RangeErrorKind::*;
499 match self {
500 Ok(v) => Ok(v),
501 Err(NegOverflow) => Ok(T::saturated_min()),
502 Err(PosOverflow) => Ok(T::saturated_max())
503 }
504 }
505}
506
507pub trait UnwrapOk<T> {
511 fn unwrap_ok(self) -> T;
517}
518
519impl<T> UnwrapOk<T> for Result<T, NoError> {
520 #[inline]
521 fn unwrap_ok(self) -> T {
522 match self {
523 Ok(v) => v,
524 Err(no_error) => match no_error {},
525 }
526 }
527}
528
529pub trait UnwrapOrInf {
533 type Output;
535
536 fn unwrap_or_inf(self) -> Self::Output;
540}
541
542pub trait UnwrapOrInvalid {
546 type Output;
548
549 fn unwrap_or_invalid(self) -> Self::Output;
553}
554
555pub trait UnwrapOrSaturate {
559 type Output;
561
562 fn unwrap_or_saturate(self) -> Self::Output;
566}
567
568impl<T, E> UnwrapOrInf for Result<T, E>
569where T: SignedInfinity, E: Into<RangeErrorKind> {
570 type Output = T;
571 #[inline]
572 fn unwrap_or_inf(self) -> T {
573 use self::RangeErrorKind::*;
574 match self.map_err(Into::into) {
575 Ok(v) => v,
576 Err(NegOverflow) => T::neg_infinity(),
577 Err(PosOverflow) => T::pos_infinity(),
578 }
579 }
580}
581
582impl<T, E> UnwrapOrInvalid for Result<T, E>
583where T: InvalidSentinel {
584 type Output = T;
585 #[inline]
586 fn unwrap_or_invalid(self) -> T {
587 match self {
588 Ok(v) => v,
589 Err(..) => T::invalid_sentinel(),
590 }
591 }
592}
593
594impl<T, E> UnwrapOrSaturate for Result<T, E>
595where T: Saturated, E: Into<RangeErrorKind> {
596 type Output = T;
597 #[inline]
598 fn unwrap_or_saturate(self) -> T {
599 use self::RangeErrorKind::*;
600 match self.map_err(Into::into) {
601 Ok(v) => v,
602 Err(NegOverflow) => T::saturated_min(),
603 Err(PosOverflow) => T::saturated_max(),
604 }
605 }
606}