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
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
// libovgu-canteen - A canteen parser module for ovgu.
//
// Copyright (C) 2017
//     Fin Christensen <christensen.fin@gmail.com>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

use failure::Fail;
use derive_more::Display;

use crate::CanteenDescription;

#[derive(Display, Debug)]
pub enum IdentifierKind {
    #[display(fmt = "additive")]
    Additive,
    #[display(fmt = "allergenic")]
    Allergenic,
    #[display(fmt = "symbol")]
    Symbol,
}

#[derive(Debug, Fail)]
pub enum Error {
    #[fail(display = "Fetch failed for '{}'", url)]
    Fetch {
        url: String,
        #[fail(cause)]
        cause: hyper::Error,
    },
    #[fail(display = "Response from webserver contains invalid UTF-8")]
    ResponseEncoding {
        #[fail(cause)]
        cause: std::str::Utf8Error,
    },
    #[fail(display = "Identifier for {} with name '{}' is not known! This is a bug in rust-ovgu-canteen. Please file an issue on github: https://github.com/fin-ger/rust-ovgu-canteen/issues", kind, name)]
    InvalidIdentifier {
        kind: IdentifierKind,
        name: String,
    },
    #[fail(display = "Could not retrieve information needed to construct '{}' for type '{}'!", member, object)]
    NotAvailable {
        object: &'static str,
        member: &'static str,
    },
    #[fail(display = "Could not parse value for '{}' in type '{}'!", member, object)]
    InvalidValue {
        object: &'static str,
        member: &'static str,
        #[fail(cause)]
        cause: Box<dyn Fail>,
    },
    #[fail(display = "Could not merge canteen {:?} with {:?}, as description is not matching!", us, them)]
    CouldNotMerge {
        us: CanteenDescription,
        them: CanteenDescription,
    },
}


/*
/// The `Error` enum represents several different error types that are used
/// by results in this crate.
#[derive(Debug)]
pub enum Error {
    /// This error is used when a creation of something failed.
    ///
    ///  * The first parameter is used to define *what* failed to create.
    ///  * The second parameter is used to provide a string representation
    ///    from *which* the creation failed.
    ///  * The third parameter contains the previous error.
    ///
    /// # Examples
    ///
    /// ```
    /// use ovgu_canteen::Error;
    ///
    /// let data = String::from("five");
    /// let number = match data.as_str()
    /// {
    ///     "five" => Ok(5),
    ///     _ => Err(Error::Creation("number", data, None)),
    /// };
    /// ```
    Creation(&'static str, String, Option<Box<dyn std::error::Error>>),

    /// This error is used when something is not available or cannot be found.
    ///
    ///  * The first parameter is used to define what is *affected* by this error.
    ///  * The second parameter is used to define what *item* is not available.
    ///  * The third parameter contains the previous error.
    ///
    /// # Examples
    ///
    /// ```
    /// use ovgu_canteen::Error;
    ///
    /// let data = ["foo"];
    /// let mut iter = data.iter();
    /// let result = iter.next().ok_or(Error::NotAvailable("result", "foo", None));
    /// ```
    NotAvailable(&'static str, &'static str, Option<Box<dyn std::error::Error>>),

    /// This error is used when invalid data got passed.
    ///
    ///  * The first parameter is used to define what is *affected* by this error.
    ///  * The second parameter is used to define what *item* is invalid.
    ///  * The third parameter contains the previous error.
    ///
    /// # Examples
    ///
    /// ```
    /// use ovgu_canteen::Error;
    ///
    /// let data = String::from("42");
    /// let number = data.parse::<f32>()
    ///     .map_err(|e| Error::InvalidValue("number", "data", Some(Box::new(e))));
    /// ```
    InvalidValue(&'static str, &'static str, Option<Box<dyn std::error::Error>>),
}

impl std::fmt::Display for Error {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        match *self {
            Error::Creation(ref what, ref input, ref err) => {
                match *err {
                    Some(ref err_box) => {
                        write!(
                            f,
                            "Error creating {} from '{}' - Reason: {}",
                            what,
                            input,
                            err_box
                        )
                    }
                    None => write!(f, "Error creating {} from '{}'!", what, input),
                }
            }
            Error::NotAvailable(ref what, ref thing, ref err) => {
                match *err {
                    Some(ref err_box) => {
                        write!(
                            f,
                            "Error {} is unavailable for {} - Reason: {}",
                            what,
                            thing,
                            err_box
                        )
                    }
                    None => write!(f, "Error {} is unavailable for {}!", what, thing),
                }
            }
            Error::InvalidValue(ref what, ref val, ref err) => {
                match *err {
                    Some(ref err_box) => {
                        write!(f, "Error parsing {} '{}' - Reason: {}", what, val, err_box)
                    }
                    None => write!(f, "Error parsing {} '{}'!", what, val),
                }
            }
        }
    }
}

impl std::error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::Creation(..) => "Cannot create instance",
            Error::NotAvailable(..) => "Cannot find requested value",
            Error::InvalidValue(..) => "Cannot parse given value",
        }
    }
}
*/