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
use roxmltree::TextPos;
#[cfg(feature = "backtrace")]
use std::backtrace::Backtrace;
use std::fmt::{Display, Formatter};

/// All kinds of error that can happen during the parsing of an BulletML document.
#[derive(Error, Debug, new)]
pub enum ParseError {
    #[error("I/O error")]
    Io {
        #[from]
        source: std::io::Error,
        #[cfg(feature = "backtrace")]
        #[new(value = "Backtrace::capture()")]
        backtrace: Backtrace,
    },

    #[error("Xml error")]
    Xml {
        #[from]
        source: roxmltree::Error,
        #[cfg(feature = "backtrace")]
        #[new(value = "Backtrace::capture()")]
        backtrace: Backtrace,
    },

    #[error("Unexpected element {element} at position {pos}")]
    UnexpectedElement {
        element: String,
        pos: ParseErrorPos,
        #[cfg(feature = "backtrace")]
        #[new(value = "Backtrace::capture()")]
        backtrace: Backtrace,
    },
    #[error("Missing attribute {attribute} in element {element} at position {pos}")]
    MissingAttribute {
        attribute: String,
        element: String,
        pos: ParseErrorPos,
        #[cfg(feature = "backtrace")]
        #[new(value = "Backtrace::capture()")]
        backtrace: Backtrace,
    },
    #[error("Unexpected node of type {node_type} at position {pos}")]
    UnexpectedNodeType {
        node_type: String,
        pos: ParseErrorPos,
        #[cfg(feature = "backtrace")]
        #[new(value = "Backtrace::capture()")]
        backtrace: Backtrace,
    },

    #[error("Unrecognized BulletML type {bml_type} at position {pos}")]
    UnrecognizedBmlType {
        bml_type: String,
        pos: ParseErrorPos,
        #[cfg(feature = "backtrace")]
        #[new(value = "Backtrace::capture()")]
        backtrace: Backtrace,
    },
    #[error("Unrecognized direction type {dir_type} at position {pos}")]
    UnrecognizedDirectionType {
        dir_type: String,
        pos: ParseErrorPos,
        #[cfg(feature = "backtrace")]
        #[new(value = "Backtrace::capture()")]
        backtrace: Backtrace,
    },
    #[error("Unrecognized speed type {speed_type} at position {pos}")]
    UnrecognizedSpeedType {
        speed_type: String,
        pos: ParseErrorPos,
        #[cfg(feature = "backtrace")]
        #[new(value = "Backtrace::capture()")]
        backtrace: Backtrace,
    },
    #[error("Unrecognized acceleration direction type {accel_dir_type} at position {pos}")]
    UnrecognizedAccelDirType {
        accel_dir_type: String,
        pos: ParseErrorPos,
        #[cfg(feature = "backtrace")]
        #[new(value = "Backtrace::capture()")]
        backtrace: Backtrace,
    },

    #[error("Expression error at position {pos}")]
    Expression {
        source: fasteval::Error,
        pos: ParseErrorPos,
        #[cfg(feature = "backtrace")]
        #[new(value = "Backtrace::capture()")]
        backtrace: Backtrace,
    },
}

#[derive(Copy, Clone, Eq, PartialEq, Debug)]
pub struct ParseErrorPos {
    pub row: u32,
    pub col: u32,
}

impl ParseErrorPos {
    pub fn row(&self) -> u32 {
        self.row
    }

    pub fn col(&self) -> u32 {
        self.col
    }
}

impl Display for ParseErrorPos {
    fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
        f.write_fmt(format_args!("{}:{}", self.row, self.col))
    }
}

impl From<TextPos> for ParseErrorPos {
    fn from(text_pos: TextPos) -> Self {
        ParseErrorPos {
            row: text_pos.row,
            col: text_pos.col,
        }
    }
}