srcinfo/
error.rs

1use std::error;
2use std::fmt;
3use std::io;
4
5/// Error Line holds a line of text and the line number the line is from.
6#[derive(Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
7pub struct ErrorLine {
8    /// The line number that the  error occurred at
9    pub number: usize,
10    /// The full line containing the error
11    pub line: String,
12}
13
14/// A list of possible errors that may occur when parsing a .SRCINFO.
15///
16/// Variants that hold a string hold the key that caused the error.
17///
18/// UndeclaredArch holds the key that caused the error and the architecture.
19///
20/// IoError holds the underlying IO::Error.
21#[derive(Debug)]
22pub enum ErrorKind {
23    /// pkgbase was specified more than once
24    DuplicatePkgbase,
25    /// An architecture specific field was declared using an architecture
26    /// that has not been declared
27    UndeclaredArch(String, String),
28    /// A key that must be used inside of the pkgbase section was used
29    /// inside of a pkgname section
30    KeyAfterPkgname(String),
31    /// A key that must be used inside of a pkgname section was used
32    /// inside of the pkgbase section
33    KeyBeforePkgbase(String),
34    /// A required field is missing
35    MissingField(String),
36    /// A line has an empty key. E.g. " = foo"
37    EmptyKey,
38    /// A line has an empty value where a value is required. E.g. "foo = "
39    EmptyValue(String),
40    /// An architecture specific field was declared on a field that can not
41    /// be architecture specific
42    NotArchSpecific(String),
43    /// An IoError occurred
44    IoError(io::Error),
45}
46
47impl fmt::Display for ErrorKind {
48    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
49        match self {
50            ErrorKind::DuplicatePkgbase => write!(fmt, "pkgbase already set"),
51            ErrorKind::UndeclaredArch(k, a) => {
52                write!(fmt, "undeclared architecture '{}' in key '{}'", a, k)
53            }
54            ErrorKind::KeyAfterPkgname(k) => write!(fmt, "key '{}' used after pkgname", k),
55            ErrorKind::KeyBeforePkgbase(k) => write!(fmt, "key '{}' used before pkgbase", k),
56            ErrorKind::MissingField(f) => write!(fmt, "field '{}' is required", f),
57            ErrorKind::EmptyKey => write!(fmt, "field has no key"),
58            ErrorKind::EmptyValue(k) => write!(fmt, "key '{}' requires a value", k),
59            ErrorKind::NotArchSpecific(k) => {
60                write!(fmt, "key '{}' can not be architecture specific", k)
61            }
62            ErrorKind::IoError(err) => err.fmt(fmt),
63        }
64    }
65}
66
67/// The error type for .SRCINFO parsing.
68#[derive(Debug)]
69pub struct Error {
70    /// The kind of Error that occurred
71    pub kind: ErrorKind,
72    /// The line where the error occurred
73    pub line: Option<ErrorLine>,
74}
75
76impl error::Error for Error {}
77
78impl fmt::Display for Error {
79    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
80        match self.line {
81            Some(ref line) => write!(fmt, "{}: Line {}: {}", self.kind, line.number, line.line),
82            None => write!(fmt, "{}", self.kind),
83        }
84    }
85}
86
87impl From<io::Error> for Error {
88    fn from(err: io::Error) -> Error {
89        ErrorKind::IoError(err).into()
90    }
91}
92
93impl From<ErrorKind> for Error {
94    fn from(kind: ErrorKind) -> Error {
95        Error { kind, line: None }
96    }
97}
98
99impl Error {
100    /// Create a new Error from a given ErrorKind and ErrorLine.
101    ///
102    /// If the line is none then Errors can be created using the the From/Into traits.
103    pub fn new<S: Into<String>>(kind: ErrorKind, line: S, number: usize) -> Error {
104        let line = line.into();
105        let line = Some(ErrorLine { number, line });
106        Error {
107            line,
108            ..Error::from(kind)
109        }
110    }
111}