Skip to main content

exiftool_rs/
error.rs

1use std::io;
2
3/// All errors that can occur in exiftool operations.
4#[derive(Debug, thiserror::Error)]
5pub enum Error {
6    #[error("I/O error: {0}")]
7    Io(#[from] io::Error),
8
9    #[error("unsupported file type: {0}")]
10    UnsupportedFileType(String),
11
12    #[error("invalid data: {0}")]
13    InvalidData(String),
14
15    #[error("tag not found: {0}")]
16    TagNotFound(String),
17
18    #[error("invalid TIFF header")]
19    InvalidTiffHeader,
20
21    #[error("invalid EXIF data: {0}")]
22    InvalidExif(String),
23
24    #[error("invalid IPTC data: {0}")]
25    InvalidIptc(String),
26
27    #[error("invalid XMP data: {0}")]
28    InvalidXmp(String),
29
30    #[error("truncated data: expected {expected} bytes, got {actual}")]
31    TruncatedData { expected: usize, actual: usize },
32
33    #[error("value conversion error: {0}")]
34    ConversionError(String),
35}
36
37pub type Result<T> = std::result::Result<T, Error>;
38
39#[cfg(test)]
40mod tests {
41    use super::*;
42
43    #[test]
44    fn display_io_error() {
45        let err = Error::Io(io::Error::new(io::ErrorKind::NotFound, "gone"));
46        let s = format!("{}", err);
47        assert!(s.contains("I/O error"), "got: {}", s);
48        assert!(s.contains("gone"), "got: {}", s);
49    }
50
51    #[test]
52    fn display_unsupported_file_type() {
53        let err = Error::UnsupportedFileType("xyz".into());
54        assert_eq!(format!("{}", err), "unsupported file type: xyz");
55    }
56
57    #[test]
58    fn display_invalid_data() {
59        let err = Error::InvalidData("bad header".into());
60        assert_eq!(format!("{}", err), "invalid data: bad header");
61    }
62
63    #[test]
64    fn display_tag_not_found() {
65        let err = Error::TagNotFound("FooBar".into());
66        assert_eq!(format!("{}", err), "tag not found: FooBar");
67    }
68
69    #[test]
70    fn display_invalid_tiff_header() {
71        let err = Error::InvalidTiffHeader;
72        assert_eq!(format!("{}", err), "invalid TIFF header");
73    }
74
75    #[test]
76    fn display_invalid_exif() {
77        let err = Error::InvalidExif("offset overflow".into());
78        assert_eq!(format!("{}", err), "invalid EXIF data: offset overflow");
79    }
80
81    #[test]
82    fn display_invalid_iptc() {
83        let err = Error::InvalidIptc("bad record".into());
84        assert_eq!(format!("{}", err), "invalid IPTC data: bad record");
85    }
86
87    #[test]
88    fn display_invalid_xmp() {
89        let err = Error::InvalidXmp("malformed xml".into());
90        assert_eq!(format!("{}", err), "invalid XMP data: malformed xml");
91    }
92
93    #[test]
94    fn display_truncated_data() {
95        let err = Error::TruncatedData {
96            expected: 100,
97            actual: 50,
98        };
99        assert_eq!(
100            format!("{}", err),
101            "truncated data: expected 100 bytes, got 50"
102        );
103    }
104
105    #[test]
106    fn display_conversion_error() {
107        let err = Error::ConversionError("not a number".into());
108        assert_eq!(format!("{}", err), "value conversion error: not a number");
109    }
110
111    #[test]
112    fn io_error_from_conversion() {
113        let io_err = io::Error::new(io::ErrorKind::PermissionDenied, "no access");
114        let err: Error = io_err.into();
115        assert!(matches!(err, Error::Io(_)));
116    }
117}