1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
use std::{error::Error, fmt};

// Macro to declare type-specific InvalidValue error type.
macro_rules! invalid_value_error {
    ($name:literal, $error:ident, $value_type:ty) => {
        #[doc = concat!("Invalid ", $name, ".")]
        #[derive(Clone, Copy, Debug, PartialEq)]
        // Value type may not be `Eq` (e.g. f64).
        #[allow(clippy::derive_partial_eq_without_eq)]
        pub struct $error {
            /// The invalid value.
            pub value: $value_type,
            /// The reason why it's invalid.
            pub reason: &'static str,
        }

        impl $error {
            pub(crate) const fn new(
                value: $value_type,
                reason: &'static str,
            ) -> Self {
                Self { value, reason }
            }
        }

        impl fmt::Display for $error {
            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
                write!(
                    f,
                    "invalid {} (got {:?}): {}",
                    $name, self.value, self.reason
                )
            }
        }

        impl Error for $error {
            fn source(&self) -> Option<&(dyn Error + 'static)> {
                None
            }
        }
    };
}

invalid_value_error!("resolution", InvalidResolution, Option<u8>);
invalid_value_error!("cell index", InvalidCellIndex, Option<u64>);
invalid_value_error!("vertex index", InvalidVertexIndex, Option<u64>);
invalid_value_error!(
    "directed edge index",
    InvalidDirectedEdgeIndex,
    Option<u64>
);
invalid_value_error!("latitude/longitude", InvalidLatLng, f64);
invalid_value_error!("cell edge", InvalidEdge, u8);
invalid_value_error!("cell vertex", InvalidVertex, u8);
invalid_value_error!("icosahedron face", InvalidFace, u8);
invalid_value_error!("base cell", InvalidBaseCell, u8);
invalid_value_error!("direction", InvalidDirection, u8);