1
//! Error types.
2

            
3
use thiserror::Error;
4

            
5
use crate::ffi;
6

            
7
/// Wraps all error types returned by `minion-sys`.
8
#[derive(Debug, Error)]
9
#[non_exhaustive]
10
pub enum MinionError {
11
    /// An error has occurred during the execution of Minion.
12
    #[error("runtime error: `{0}.to_string()`")]
13
    RuntimeError(#[from] RuntimeError),
14

            
15
    /// The input model uses Minion features that are not yet implemented in `minion_rs`.
16
    #[error("not implemented: {0}")]
17
    NotImplemented(String),
18

            
19
    /// Catch-all error.
20
    #[error(transparent)]
21
    Other(#[from] anyhow::Error), // source and Display delegate to anyhow::Error
22
}
23

            
24
/// Errors thrown by Minion during execution.
25
///
26
/// These represent internal Minion C++ exceptions translated into Rust.
27
///
28
/// Invalid usage of this library should throw an error before Minion is even run. Therefore, these
29
/// should be quite rare. Consider creating an issue on
30
/// [Github](https://github.com/conjure-cp/conjure-oxide) if these occur regularly!
31
#[derive(Debug, Error, Eq, PartialEq)]
32
#[non_exhaustive]
33
pub enum RuntimeError {
34
    // These closely follow the ReturnCodes found in Minion's libwrapper.cpp.
35
    /// The model given to Minion is invalid.
36
    #[error("the given instance is invalid")]
37
    InvalidInstance,
38

            
39
    /// The solver exceeded its time limit.
40
    #[error("solver timed out")]
41
    Timeout,
42

            
43
    /// The solver ran out of memory.
44
    #[error("solver ran out of memory")]
45
    MemoryError,
46

            
47
    /// An unknown error has occurred.
48
    #[error("an unknown error has occurred while running minion")]
49
    UnknownError,
50
}
51

            
52
// Minion's ReturnCodes are passed over FFI as ints.
53
// Convert them to their appropriate error.
54
impl From<u32> for RuntimeError {
55
    fn from(return_code: u32) -> Self {
56
        match return_code {
57
            #[allow(non_upper_case_globals)]
58
            ffi::ReturnCodes_INVALID_INSTANCE => RuntimeError::InvalidInstance,
59
            #[allow(non_upper_case_globals)]
60
            ffi::ReturnCodes_TIMEOUT => RuntimeError::Timeout,
61
            #[allow(non_upper_case_globals)]
62
            ffi::ReturnCodes_MEMORY_ERROR => RuntimeError::MemoryError,
63
            _ => RuntimeError::UnknownError,
64
        }
65
    }
66
}