ucglib/build/opcode/
error.rs

1// Copyright 2019 Jeremy Wall
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14use std::convert::From;
15use std::fmt;
16use std::fmt::Display;
17use std::io;
18
19use crate::ast::Position;
20use crate::build::opcode::convert;
21
22#[derive(Debug)]
23pub struct Error {
24    message: String,
25    pos: Option<Position>,
26    call_stack: Vec<Position>,
27}
28
29impl Error {
30    pub fn new(msg: String, pos: Position) -> Self {
31        Self {
32            message: msg,
33            pos: Some(pos),
34            call_stack: Vec::new(),
35        }
36    }
37
38    pub fn with_pos(mut self, pos: Position) -> Self {
39        self.pos = Some(pos);
40        self
41    }
42
43    pub fn push_call_stack(&mut self, pos: Position) {
44        self.call_stack.push(pos);
45    }
46}
47
48macro_rules! decorate_error {
49    ($pos:expr => $result:expr) => {
50        match $result {
51            Ok(v) => Ok(v),
52            Err(e) => Err(e.with_pos($pos.clone())),
53        }
54    };
55}
56
57macro_rules! decorate_call {
58    ($pos:expr => $result:expr) => {
59        match $result {
60            Ok(v) => Ok(v),
61            Err(mut e) => {
62                e.push_call_stack($pos.clone());
63                Err(e)
64            }
65        }
66    };
67}
68
69impl From<regex::Error> for Error {
70    fn from(e: regex::Error) -> Self {
71        Error {
72            message: format!("{}", e),
73            pos: None,
74            call_stack: Vec::new(),
75        }
76    }
77}
78
79impl From<std::io::Error> for Error {
80    fn from(e: std::io::Error) -> Self {
81        let msg = match e.kind() {
82            io::ErrorKind::NotFound | io::ErrorKind::Other => {
83                format!("OSError: Path not found: {}", e)
84            }
85            _ => format!("{}", e),
86        };
87        Error {
88            message: msg,
89            pos: None,
90            call_stack: Vec::new(),
91        }
92    }
93}
94
95impl From<convert::Error> for Error {
96    fn from(e: convert::Error) -> Self {
97        Error {
98            message: e.message(),
99            pos: None,
100            call_stack: Vec::new(),
101        }
102    }
103}
104
105impl Display for Error {
106    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
107        if let Some(ref pos) = self.pos {
108            write!(f, "{} at {}", self.message, pos)?;
109        } else {
110            write!(f, "{}", self.message)?;
111        }
112        if !self.call_stack.is_empty() {
113            for p in self.call_stack.iter() {
114                write!(f, "\nVIA: {}", p)?;
115            }
116        }
117        Ok(())
118    }
119}
120
121impl std::error::Error for Error {}