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
//! Error handling of MPQ Parsing

pub use crate::parser;
use nom::error::ErrorKind;
use nom::error::ParseError;
use thiserror::Error;

/// Holds the result of parsing progress and the possibly failures
pub type MPQResult<I, O> = Result<(I, O), MPQParserError>;

/// Error handling for upstream crates to use
#[derive(Error, Debug)]
pub enum MPQParserError {
    /// Mising Archive Header
    #[error("Missing Archive Header")]
    MissingArchiveHeader,
    /// A section magic was Unexpected
    #[error("Unexpected Section")]
    UnexpectedSection,
    /// Unable to parse the byte aligned data types
    #[error("Nom ByteAligned Error {0}")]
    ByteAligned(String),
    /// An I/O Error
    #[error("IO Error")]
    IoError(#[from] std::io::Error),
    /// The Hash Table Entry wasn't found for a filename
    #[error("Hash Table Entry not found {0}")]
    HashTableEntryNotFound(String),
    /// Unable to decrypt mpq data with key
    #[error("Unable to decrypt data with key: {0}")]
    DecryptionDataWithKey(String),
    /// Incoming data, missing bytes
    #[error("Missing bytes")]
    IncompleteData,
    /// Invalid HashType number
    #[error("Invalid HashType number: {0}")]
    InvalidHashType(u32),
}

/// Conversion of errors from byte aligned parser
impl<I> From<nom::Err<nom::error::Error<I>>> for MPQParserError
where
    I: Clone + std::fmt::Debug,
{
    fn from(err: nom::Err<nom::error::Error<I>>) -> Self {
        match err {
            nom::Err::Incomplete(_) => {
                unreachable!("This library is compatible with only complete parsers, not streaming")
            }
            nom::Err::Error(e) => MPQParserError::ByteAligned(format!("{:?}", e)),
            nom::Err::Failure(e) => MPQParserError::ByteAligned(format!("{:?}", e)),
        }
    }
}

impl<I> ParseError<I> for MPQParserError
where
    I: Clone,
{
    fn from_error_kind(_input: I, kind: ErrorKind) -> Self {
        MPQParserError::ByteAligned(format!("{:?}", kind))
    }

    fn append(_input: I, _kind: ErrorKind, other: Self) -> Self {
        other
    }
}