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
use std::fmt;

/// Error types encountered while parsing
#[derive(Debug, PartialEq)]
pub enum ErrorType {
    /// The key of a map isn't a string
    BadKeyType,
    /// The data ended early
    EarlyEnd,
    /// Expected an array
    ExpectedArray,
    /// Expected a `,` in an array
    ExpectedArrayComma,
    /// expected an boolean
    ExpectedBoolean,
    /// Expected an enum
    ExpectedEnum,
    /// Expected a float
    ExpectedFloat,
    /// Expected an integer
    ExpectedInteger,
    /// Expected a map
    ExpectedMap,
    /// Expected an `:` to seperate key and value in an object
    ExpectedObjectColon,
    /// Expected a `,` in an object
    ExpectedMapComma,
    /// Expected the object to end
    ExpectedMapEnd,
    /// Expected a null
    ExpectedNull,
    /// Expected a number
    ExpectedNumber,
    /// Expected a signed number
    ExpectedSigned,
    /// Expected a string
    ExpectedString,
    /// Expected an unsigned number
    ExpectedUnsigned,
    /// Internal error
    InternalError,
    /// Invalid escape sequence
    InvalidEscape,
    /// Invalid exponent in a floating point number
    InvalidExponent,
    /// Invalid number
    InvalidNumber,
    /// Inbalid UTF8 codepoint
    InvalidUTF8,
    /// Invalid Unicode escape sequence
    InvalidUnicodeEscape,
    /// Inbalid Unicode codepoint
    InvlaidUnicodeCodepoint,
    /// Object Key isn't a string
    KeyMustBeAString,
    /// Non structural character
    NoStructure,
    /// Parser Erropr
    Parser,
    /// Early End Of File
    EOF,
    /// Generic serde error
    Serde(String),
    /// Generic syntax error
    Syntax,
    /// Training characters
    TrailingCharacters,
    /// Unexpected character
    UnexpectedCharacter,
    /// Unexpected end
    UnexpectedEnd,
    /// Unterminated string
    UnterminatedString,
    /// Expected Array elements
    ExpectedArrayContent,
    /// Expected Object elements
    ExpectedObjectContent,
    /// Expected Object Key
    ExpectedObjectKey,
    /// Overflow of a limited buffer
    Overflow,
}

/// Parser error
#[derive(Debug, PartialEq)]
pub struct Error {
    /// Byte index it was encountered at
    index: usize,
    /// Current character
    character: char,
    /// Tyep of error
    error: ErrorType,
}

impl Error {
    pub(crate) fn new(index: usize, character: char, error: ErrorType) -> Self {
        Self {
            index,
            character,
            error,
        }
    }
    pub(crate) fn generic(t: ErrorType) -> Self {
        Self {
            index: 0,
            character: '💩', //this is the poop emoji
            error: t,
        }
    }
}

#[cfg_attr(tarpaulin, skip)]
impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(
            f,
            "{:?} at character {} ('{}')",
            self.error, self.index, self.character
        )
    }
}

#[cfg(test)]
mod test {
    use super::*;
    #[test]
    fn fmt() {
        let e = Error::generic(ErrorType::InternalError);
        assert_eq!(
            format!("{}", e),
            "InternalError at character 0 ('\u{1f4a9}')"
        )
    }
}