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
//! Errors for printpdf

use std::error::Error as IError;
use std::io::Error as IoError;
use rusttype::Error as RusttypeError;
use std::fmt;

/// error_chain and failure are certainly nice, but completely overengineered
/// for this use-case. For example, neither of them allow error localization.
/// Additionally, debugging macros can get hairy really quick and matching with
/// `*e.kind()` or doing From conversions for other errors is really hard to do.
///
/// So in this case, the best form of error handling is to use the simple Rust-native
/// way: Just enums, `From` + pattern matching. No macros, except for this one.
///
/// What this macro does is (simplified): `impl From<$a> for $b { $b::$variant(error) }`
macro_rules! impl_from {
    ($from:ident, $to:ident::$variant:ident) => (
        impl From<$from> for $to {
            fn from(err: $from) -> Self {
                $to::$variant(err.into())
            }
        }
    )
}

#[derive(Debug)]
pub enum Error {
    /// External: std::io::Error
    Io(IoError),
    /// External: rusttype::Error
    Rusttype(RusttypeError),
    /// PDF error
    Pdf(PdfError),
    /// Indexing error (please report if this happens, shouldn't happen)
    Index(IndexError),
}

#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum PdfError {
    FontFaceError,
}

impl fmt::Display for PdfError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Invalid or corrupt font face")
    }
}

impl IError for PdfError {}

#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum IndexError {
    PdfPageIndexError,
    PdfLayerIndexError,
    PdfMarkerIndexError,
}

impl fmt::Display for IndexError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use self::IndexError::*;
        write!(f, "{}", match *self {
            PdfPageIndexError => "Page index out of bounds",
            PdfLayerIndexError => "PDF layer index out of bounds",
            PdfMarkerIndexError => "PDF layer index out of bounds",
        })
    }
}

impl IError for IndexError {}

impl_from!(IoError, Error::Io);
impl_from!(RusttypeError, Error::Rusttype);
impl_from!(PdfError, Error::Pdf);
impl_from!(IndexError, Error::Index);

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use self::Error::*;
        match *self {
            Io(ref e) => write!(f, "{}", e),
            Rusttype(ref e) => write!(f, "{}", e),
            Pdf(ref e) => write!(f, "{}", e),
            Index(ref e) => write!(f, "{}", e),
        }
    }
}

impl IError for Error {}