• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

djeedai / weldr / 4256884197

pending completion
4256884197

Pull #23

github

GitHub
Merge dcf4e406b into aae1bff12
Pull Request #23: Bump min Rust version to 1.56

1489 of 1581 relevant lines covered (94.18%)

1.44 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

90.0
/lib/src/error.rs
1
//! Error management
2

3
use std::convert::From;
4
use std::fmt;
5

6
/// Generic error for all weldr operations.
7
#[derive(Debug)]
8
pub enum Error {
9
    /// An error encountered while parsing some LDraw file content.
10
    Parse(ParseError),
11

12
    /// An error encountered while resolving a sub-file reference.
13
    Resolve(ResolveError),
14
}
15

16
/// Error related to parsing the content of an LDraw file.
17
#[derive(Debug)]
18
pub struct ParseError {
19
    /// Filename of the sub-file reference, generally relative to some canonical catalog path(s).
20
    pub filename: String,
21

22
    /// Optional underlying error raised by the internal parser.
23
    pub parse_error: Option<Box<dyn std::error::Error>>,
24
}
25

26
/// Error related to resolving a sub-file reference of a source file.
27
#[derive(Debug)]
28
pub struct ResolveError {
29
    /// Filename of the sub-file reference, generally relative to some canonical catalog path(s).
30
    pub filename: String,
31

32
    /// Optional underlying error raised by the resolver implementation.
33
    pub resolve_error: Option<Box<dyn std::error::Error>>,
34
}
35

36
impl ParseError {
37
    /// Create a [`ParseError`] that stems from an arbitrary error of an underlying parser.
38
    pub fn new(filename: &str, err: impl Into<Box<dyn std::error::Error>>) -> Self {
2✔
39
        ParseError {
40
            filename: filename.to_string(),
2✔
41
            parse_error: Some(err.into()),
4✔
42
        }
43
    }
44

45
    /// Create a [`ParseError`] that stems from a [`nom`] parsing error, capturing the [`nom::error::ErrorKind`]
46
    /// from the underlying parser which failed.
47
    pub fn new_from_nom(filename: &str, err: &nom::Err<(&[u8], nom::error::ErrorKind)>) -> Self {
1✔
48
        ParseError {
49
            filename: filename.to_string(),
1✔
50
            parse_error: match err {
1✔
51
                nom::Err::Incomplete(_) => None,
52
                nom::Err::Error((_, e)) => {
53
                    // Discard input slice due to lifetime constraint
54
                    let e2: nom::Err<_> = nom::Err::Error(*e);
55
                    Some(e2.into())
56
                }
57
                nom::Err::Failure((_, e)) => {
58
                    // Discard input slice due to lifetime constraint
59
                    let e2: nom::Err<_> = nom::Err::Failure(*e);
60
                    Some(e2.into())
61
                }
62
            },
63
        }
64
    }
65
}
66

67
impl ResolveError {
68
    /// Create a [`ResolveError`] that stems from an arbitrary error of an underlying resolution error.
69
    pub fn new(filename: &str, err: impl Into<Box<dyn std::error::Error>>) -> Self {
3✔
70
        ResolveError {
71
            filename: filename.to_string(),
3✔
72
            resolve_error: Some(err.into()),
6✔
73
        }
74
    }
75

76
    /// Create a [`ResolveError`] without any underlying error.
77
    pub fn new_raw(filename: &str) -> Self {
3✔
78
        ResolveError {
79
            filename: filename.to_string(),
3✔
80
            resolve_error: None,
81
        }
82
    }
83
}
84

85
impl fmt::Display for Error {
86
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1✔
87
        match self {
1✔
88
            Error::Parse(ParseError {
×
89
                filename,
1✔
90
                parse_error,
1✔
91
            }) => write!(f, "parse error in file '{}': {:?}", filename, parse_error),
1✔
92
            Error::Resolve(ResolveError {
×
93
                filename,
1✔
94
                resolve_error,
1✔
95
            }) => write!(
1✔
96
                f,
×
97
                "resolve error for filename '{}': {:?}",
98
                filename, resolve_error
×
99
            ),
100
        }
101
    }
102
}
103

104
impl std::error::Error for Error {
105
    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
1✔
106
        None
1✔
107
        // match self {
108
        //     Error::Parse(ParseError {
109
        //         filename,
110
        //         parse_error,
111
        //     }) => parse_error,
112
        //     Error::Resolve(ResolveError {
113
        //         filename,
114
        //         resolve_error,
115
        //     }) => resolve_error,
116
        // }
117
    }
118
}
119

120
impl From<ResolveError> for Error {
121
    fn from(e: ResolveError) -> Self {
2✔
122
        Error::Resolve(e)
2✔
123
    }
124
}
125

126
impl From<ParseError> for Error {
127
    fn from(e: ParseError) -> Self {
1✔
128
        Error::Parse(e)
1✔
129
    }
130
}
131

132
#[cfg(test)]
133
mod tests {
134

135
    use super::*;
136

137
    fn get_error() -> Result<u32, Error> {
1✔
138
        let underlying = Error::Parse(ParseError {
1✔
139
            filename: "low_level.ldr".to_string(),
1✔
140
            parse_error: None,
1✔
141
        });
142
        Err(Error::Resolve(ResolveError::new(
1✔
143
            "test_file.ldr",
144
            underlying,
1✔
145
        )))
146
    }
147

148
    #[test]
149
    fn test_error() {
3✔
150
        match get_error() {
1✔
151
            Err(e) => eprintln!("Error: {}", e),
1✔
152
            _ => {}
153
        };
154
    }
155

156
    #[test]
157
    fn test_new_from_nom() {
3✔
158
        let nom_error: nom::Err<(&[u8], nom::error::ErrorKind)> =
1✔
159
            nom::Err::Error((&b""[..], nom::error::ErrorKind::Alpha));
160
        let parse_error = ParseError::new_from_nom("file", &nom_error);
1✔
161
        assert_eq!(parse_error.filename, "file");
2✔
162
        assert!(parse_error.parse_error.is_some());
2✔
163
    }
164

165
    #[test]
166
    fn test_source() {
3✔
167
        let resolve_error = ResolveError::new_raw("file");
1✔
168
        let error: Error = resolve_error.into();
1✔
169
        assert!(std::error::Error::source(&error).is_none());
2✔
170
    }
171

172
    #[test]
173
    fn test_from() {
3✔
174
        let resolve_error = ResolveError::new_raw("file");
1✔
175
        let error: Error = resolve_error.into();
1✔
176
        eprintln!("err: {}", error);
2✔
177
        match &error {
1✔
178
            Error::Resolve(resolve_error) => assert_eq!(resolve_error.filename, "file"),
2✔
179
            _ => panic!("Unexpected error type."),
×
180
        }
181

182
        let parse_error = ParseError::new("file", error);
1✔
183
        let error: Error = parse_error.into();
1✔
184
        eprintln!("err: {}", error);
2✔
185
        match &error {
1✔
186
            Error::Parse(parse_error) => assert_eq!(parse_error.filename, "file"),
2✔
187
            _ => panic!("Unexpected error type."),
×
188
        }
189
    }
190
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc