nogo/error_handling/
mod.rs

1/// This module is responsible for all error-handling related
2/// tasks
3
4pub mod validation;
5
6use std::io::{self, Write};
7use std::error::Error;
8use std::fmt;
9
10
11/// Define a new type for nogo errors
12#[derive(Debug)]
13pub enum NogoErrorKind {
14    IncorrectNumberOfArgs,
15    IncorrectTypes,
16    InvalidBoardDimensions,
17    CantOpenFileForSaving,
18    CantOpenFileForReading,
19    ErrorReadingGameFile,
20    EOFWaitingForUserInput,
21    SystemIOError,
22    ParsingError,
23}
24
25#[derive(Debug)]
26pub struct NogoError<'a> {
27    kind: NogoErrorKind,
28    status: i32,
29    general: &'a str,
30    specific: &'a str,
31}
32
33impl<'a> fmt::Display for NogoError<'a> {
34    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
35        write!(f, "{}", self.specific)
36    }
37}
38
39impl<'a> Error for NogoError<'a> {
40    fn description(&self) -> &str {
41        self.specific
42    }
43}
44
45impl<'a> NogoError<'a> {
46    pub fn new(kind: NogoErrorKind) -> Self {
47        let mut error = NogoError {
48            kind: kind,
49            status: 0,
50            general: "",
51            specific: "",
52        };
53
54        match error.kind {
55            NogoErrorKind::IncorrectNumberOfArgs => {
56                error.status = 1;
57                error.general = "Program started with incorrect number of arguments";
58            }
59
60            NogoErrorKind::IncorrectTypes => {
61                error.status = 2;
62                error.general = "Invalid type(s)";
63            }
64
65            NogoErrorKind::InvalidBoardDimensions => {
66                error.status = 3;
67                error.general = "Invalid board dimension(s)";
68            }
69
70            NogoErrorKind::CantOpenFileForReading => {
71                error.status = 4;
72                error.general = "Unable to open save file";
73            }
74
75            NogoErrorKind::ErrorReadingGameFile => {
76                error.status = 5;
77                error.general = "Incorrect save file contents";
78            }
79
80            NogoErrorKind::EOFWaitingForUserInput => {
81                error.status = 6;
82                error.general = "End of input from user";
83            }
84
85            NogoErrorKind::CantOpenFileForSaving => {
86                error.status = 7;
87                error.general = "Unable to open new save file";
88            }
89
90            NogoErrorKind::SystemIOError => {
91                error.status = 8;
92                error.general = "System IO error";
93            }
94
95            NogoErrorKind::ParsingError => {
96                error.status = 9;
97                error.general = "Error while parsing value";
98            }
99        }
100
101        error
102    }
103
104    pub fn kind(&self) -> &NogoErrorKind {
105        &self.kind
106    }
107
108    pub fn status(&self) -> i32 {
109        self.status
110    }
111
112    pub fn general(&self) -> &'a str {
113        &self.general
114    }
115
116    pub fn specific(&self) -> &'a str {
117        &self.specific
118    }
119
120    pub fn set_specific(&mut self, msg: &'a str) {
121        self.specific = msg;
122    }
123}
124
125/// to allow conversion from io::Error into NogoError
126impl<'a> ::std::convert::From<io::Error> for NogoError<'a> {
127    fn from(_: io::Error) -> Self {
128        NogoError::new(NogoErrorKind::SystemIOError)
129    }
130}
131
132/// to allow conversion from std::num::ParseIntError into NogoError
133impl<'a> ::std::convert::From<::std::num::ParseIntError> for NogoError<'a> {
134    fn from(_: ::std::num::ParseIntError) -> Self {
135        NogoError::new(NogoErrorKind::ParsingError)
136    }
137}
138
139
140/// define an alias for NogoError for easier handling
141pub type Result<'a, T> = ::std::result::Result<T, NogoError<'a>>;
142
143
144/// The API
145
146/// normal exit
147pub fn clean_exit() {
148    println!("\nThank you for playing nogo!\n");
149    ::std::process::exit(0);
150}
151
152/// exit with error code
153pub fn exit_with_error(error: NogoError) {
154    writeln!(io::stderr(), "Error: {}", error.description()).unwrap();
155    ::std::process::exit(error.status());
156}
157
158
159/// helper method to throw a properly constructed error object
160pub fn construct_error(specific: &str, kind: NogoErrorKind) -> NogoError {
161    let mut err = NogoError::new(kind);
162    err.set_specific(specific);
163    err
164}