dexparser/
error.rs

1use failure::Fail;
2
3#[derive(Debug, Fail, Clone)]
4pub enum DexParserError {
5    #[fail(display = "file unexpectedly ended early: expected {} bytes", needed)]
6    EndedEarly {
7        needed: usize
8    },
9    #[fail(display = "could not parse file: {}", reason)]
10    ParsingFailed {
11        reason: String
12    },
13    #[fail(display = "could not decode string to UTF8: may be malformed")]
14    EncodingError
15}
16
17impl<E: std::fmt::Debug + Clone> From<nom::Err<E>> for DexParserError {
18    fn from(e: nom::Err<E>) -> Self {
19        match e {
20            nom::Err::Incomplete(ref needed) => {
21                match needed {
22                    nom::Needed::Unknown => DexParserError::ParsingFailed { reason: "file ended early".to_string() },
23                    nom::Needed::Size(size) => DexParserError::EndedEarly { needed: *size }
24                }
25            },
26            nom::Err::Error(ctx) => {
27                match ctx {
28                    nom::Context::Code(pos, kind) => {
29                        DexParserError::ParsingFailed { reason: format!("parsing failed at byte {:?}: parser {:?}", pos, kind) }
30                    },
31                    nom::Context::List(errors) => {
32                        let reason = errors.iter()
33                            .map(|(pos, kind)| format!("parsing failed at byte {:?}: parser {:?}", pos, kind))
34                            .collect::<Vec<String>>()
35                            .join(": ");
36
37                        DexParserError::ParsingFailed { reason }
38                    }
39                }
40            },
41            nom::Err::Failure(ctx) => {
42                match ctx {
43                    nom::Context::Code(pos, kind) => {
44                        DexParserError::ParsingFailed { reason: format!("parsing failed at byte {:?}: parser {:?}", pos, kind) }
45                    },
46                    nom::Context::List(errors) => {
47                        let reason = errors.iter()
48                            .map(|(pos, kind)| format!("parsing failed at byte {:?}: parser {:?}", pos, kind))
49                            .collect::<Vec<String>>()
50                            .join(": ");
51
52                        DexParserError::ParsingFailed { reason }
53                    }
54                }
55            }
56        }
57    }
58}
59
60impl From<&'static str> for DexParserError {
61    fn from(e: &'static str) -> Self {
62        DexParserError::ParsingFailed { reason: e.to_string() }
63    }
64}
65
66impl From<String> for DexParserError {
67    fn from(e: String) -> Self {
68        DexParserError::ParsingFailed { reason: e }
69    }
70}
71
72impl From<::std::string::FromUtf8Error> for DexParserError {
73    fn from(_e: ::std::string::FromUtf8Error) -> Self {
74        DexParserError::ParsingFailed { reason: "could not parse string as UTF8".to_string() }
75    }
76}
77
78impl From<DexParserError> for nom::Err<&[u8]> {
79    fn from(e: DexParserError) -> Self {
80        // TODO - work out how to build a proper error here, or avoid converting back and forth
81        nom::Err::Failure(nom::Context::Code(b"Failed to parse DEX file", nom::ErrorKind::Custom(0)))
82    }
83}