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
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
use std::fmt;

// ------------------------------------------------------------------------------------------------
// Public Macros
// ------------------------------------------------------------------------------------------------

// ------------------------------------------------------------------------------------------------
// Public Types
// ------------------------------------------------------------------------------------------------

///
/// Common `Error` type, mainly used for `FromStr` failures.
///
#[derive(Debug)]
pub enum CodeParseError {
    /// The string to parse was either too short or too long.
    InvalidLength { type_name: String, length: usize },
    /// The value is incorrectly formatted
    InvalidFormat { type_name: String, value: String },
    /// The value contains an invalid character
    InvalidCharacter { type_name: String, c: char },
    /// The string value did not represent a known value.
    UnknownValue { type_name: String, value: String },
    /// An error in check digit calculation/verification.
    CheckDigit(Box<dyn std::error::Error>),
}

// ------------------------------------------------------------------------------------------------
// Public Functions
// ------------------------------------------------------------------------------------------------

pub fn invalid_length<S>(type_name: S, length: usize) -> CodeParseError
where
    S: Into<String>,
{
    CodeParseError::InvalidLength {
        type_name: type_name.into(),
        length,
    }
}

pub fn invalid_format<S1, S2>(type_name: S1, value: S2) -> CodeParseError
where
    S1: Into<String>,
    S2: Into<String>,
{
    CodeParseError::InvalidFormat {
        type_name: type_name.into(),
        value: value.into(),
    }
}

pub fn invalid_character<S, C>(type_name: S, c: C) -> CodeParseError
where
    S: Into<String>,
    C: Into<char>,
{
    CodeParseError::InvalidCharacter {
        type_name: type_name.into(),
        c: c.into(),
    }
}

pub fn unknown_value<S1, S2>(type_name: S1, value: S2) -> CodeParseError
where
    S1: Into<String>,
    S2: Into<String>,
{
    CodeParseError::UnknownValue {
        type_name: type_name.into(),
        value: value.into(),
    }
}

// ------------------------------------------------------------------------------------------------
// Private Types
// ------------------------------------------------------------------------------------------------

// ------------------------------------------------------------------------------------------------
// Implementations
// ------------------------------------------------------------------------------------------------

impl fmt::Display for CodeParseError {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(
            f,
            "{}",
            match self {
                Self::InvalidLength { type_name, length } => format!(
                    "The string passed is an invalid length for the type `{}`; length: {}",
                    type_name, length
                ),
                Self::InvalidFormat { type_name, value } => format!(
                    "The string passed is incorrectly formatted for type `{}`; value: {:?}",
                    type_name, value
                ),
                Self::InvalidCharacter { type_name, c } => format!(
                    "The string passed contains characters not legal for type `{}`; character: {:?}",
                    type_name, c
                ),
                Self::UnknownValue { type_name, value } => format!(
                    "The string passed is an invalid length for the not a known value of type `{}`; value: {:?}",
                    type_name, value
                ),
                Self::CheckDigit(e) => e.to_string(),
            }
        )
    }
}

impl std::error::Error for CodeParseError {}

// ------------------------------------------------------------------------------------------------
// Private Functions
// ------------------------------------------------------------------------------------------------

// ------------------------------------------------------------------------------------------------
// Modules
// ------------------------------------------------------------------------------------------------