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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
use std::cmp::PartialEq;
use std::fmt::{Display, Formatter};
use std::mem;

/// Possible Configuration errors when either setting or creating a new configuration that may occur
#[derive(Debug)]
pub enum ConfigError {
    ///character set provided isn't of length 64
    /// # Example:
    /// ```
    /// let character_set = &[
    ///     'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q',
    ///     'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
    ///     'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y',
    ///     'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+',
    /// ]; // Throws Error because Length is 63 and not 64
    /// ```
    CharacterSetLengthError,
    /// padding character provided is already used in character set
    /// # Example:
    /// ```
    /// let character_set = &[
    ///     'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q',
    ///     'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
    ///     'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y',
    ///     'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/',
    /// ];
    /// let pad = &Some('/'); // Throws Error because '/' is already taken in the character set
    /// ```
    NotUniquePaddingError,
    /// character set provided has duplicate characters
    /// # Example:
    /// ```
    /// let character_set = &[
    ///     'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q',
    ///     'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
    ///     'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y',
    ///     'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '+',
    /// ]; // Throws Error because '+' is defined twice in the character set
    /// ```
    DuplicateCharacterError,
    /// Character in character set isn't representable
    /// # Example:
    /// ```
    /// let character_set = &[
    ///     'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q',
    ///     'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
    ///     'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y',
    ///     'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '\0',
    /// ]; // Throws Error because '\0' isn't representable
    /// ```
    CharacterSetUnrepresentableCharacter,
    /// Padding character isn't representable
    /// # Example:
    /// ```
    /// let pad = &Some('\n'); // Throws Error because '\n' isn't representable
    /// ```
    PaddingUnrepresentableCharacter,
}

impl Display for ConfigError {
    fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
        match self {
            ConfigError::CharacterSetLengthError => {
                f.write_str("Provided Character set length isn't 64")
            }
            ConfigError::NotUniquePaddingError => {
                f.write_str("Padding character provided is already used in character set")
            }
            ConfigError::DuplicateCharacterError => {
                f.write_str("At least one duplicate character found in character set")
            }
            ConfigError::CharacterSetUnrepresentableCharacter => {
                f.write_str("Character set has at leaset one unrepresentable character")
            }
            ConfigError::PaddingUnrepresentableCharacter => {
                f.write_str("Padding is a character that is unrepresentable")
            }
        }
    }
}

impl std::error::Error for ConfigError {
    fn description(&self) -> &str {
        match *self {
            ConfigError::CharacterSetLengthError => "Provided Character set length isn't 64",
            ConfigError::NotUniquePaddingError => {
                "Padding character provided is already used in character set"
            }
            ConfigError::DuplicateCharacterError => {
                "At least one duplicate character found in character set"
            }
            ConfigError::CharacterSetUnrepresentableCharacter => {
                "Character set has at leaset one unrepresentable character"
            }
            ConfigError::PaddingUnrepresentableCharacter => {
                "Padding is a character that is unrepresentable"
            }
        }
    }
}

impl PartialEq for ConfigError {
    fn eq(&self, other: &ConfigError) -> bool {
        mem::discriminant(self) == mem::discriminant(other)
    }
}

/// Possible errors when decoding Base64 number
#[derive(Debug)]
pub enum Base64Error {
    /// Unsigned Overflow when decoding Base64 number to unsigned
    ///
    /// Only applies to
    /// [Base64::decode_to_unsigned](../struct.Base64.html#method.decode_to_unsigned)
    /// # Example:
    /// ```
    /// use lb64::{Base64, config::MIME};
    ///
    /// let b64 = Base64::new_random(999, MIME);
    /// match b64.decode_to_unsigned() {
    ///     Ok(value) => println!("This is impossible"),
    ///     Err(e) => println!("{}", e), // Base64Error::OverflowError occurred
    /// }
    /// ```
    OverflowError,
    /// Invalid character in Base64 provided &str
    ///
    /// Only applies to [Base64::new_from_string](../struct.Base64.html#method.new_from_string)
    /// # Example:
    /// ```
    /// use lb64::{Base64, config::MIME};
    ///
    /// match Base64::new_from_string(&"^_^", MIME) {
    ///     Ok(value) => println!("This is impossible"),
    ///     Err(e) => println!("{}", e), // Base64Error::InvalidBase64CharacterError occurred
    /// }
    /// ```
    InvalidBase64CharacterError,
}

impl Display for Base64Error {
    fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
        match *self {
            Base64Error::OverflowError => {
                f.write_str("Unsigned Overflow when decoding Base64 to unsigned")
            }
            Base64Error::InvalidBase64CharacterError => {
                f.write_str("Invalid character in provided Base64 &str")
            }
        }
    }
}

impl std::error::Error for Base64Error {
    fn description(&self) -> &str {
        match *self {
            Base64Error::OverflowError => {
                "Unsigned Overflow occured when decoding Base64 to unsigned"
            }
            Base64Error::InvalidBase64CharacterError => "Invalid character in provided Base64 &str",
        }
    }
}

impl PartialEq for Base64Error {
    fn eq(&self, other: &Base64Error) -> bool {
        mem::discriminant(self) == mem::discriminant(other)
    }
}