1use crate::ffi::ErrorCode;
2use std::collections::TryReserveError;
3use std::error;
4use std::fmt;
5use std::io;
6use std::num::NonZeroU32;
7
8#[derive(Copy, Clone)]
9pub struct Error(NonZeroU32);
10
11pub type Result<T, E = Error> = std::result::Result<T, E>;
12
13impl ErrorCode {
14 #[must_use]
16 pub fn as_str(&self) -> &'static str {
17 let s = self.c_description();
18 let s = s.get(..s.len() - 1).unwrap_or_default(); std::str::from_utf8(s).unwrap_or("")
20 }
21
22 #[inline]
24 pub fn to_result(self) -> Result<(), Error> {
25 match NonZeroU32::new(self.0) {
26 None => Ok(()),
27 Some(err) => Err(Error(err)),
28 }
29 }
30}
31
32impl Error {
33 #[cold]
35 #[must_use]
36 pub const fn new(code: u32) -> Self {
37 Self(if let Some(s) = NonZeroU32::new(code) { s } else { panic!() })
38 }
39}
40
41impl From<ErrorCode> for Result<(), Error> {
42 #[cold]
43 fn from(err: ErrorCode) -> Self {
44 err.to_result()
45 }
46}
47
48impl From<Error> for ErrorCode {
49 #[inline(always)]
50 fn from(err: Error) -> Self {
51 Self(err.0.get())
52 }
53}
54
55impl fmt::Debug for Error {
56 #[cold]
57 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
58 write!(f, "{} ({})", ErrorCode(self.0.get()).as_str(), self.0)
59 }
60}
61
62impl fmt::Debug for ErrorCode {
63 #[cold]
64 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
65 write!(f, "{} ({})", self.as_str(), self.0)
66 }
67}
68
69impl fmt::Display for Error {
70 #[cold]
71 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
72 f.write_str(ErrorCode(self.0.get()).as_str())
73 }
74}
75
76impl error::Error for Error {}
77
78#[doc(hidden)]
79impl std::convert::From<io::Error> for Error {
80 #[cold]
81 fn from(err: io::Error) -> Self {
82 match err.kind() {
83 io::ErrorKind::NotFound | io::ErrorKind::UnexpectedEof => Self::new(78),
84 io::ErrorKind::OutOfMemory => Self::new(83),
85 _ => Self::new(79),
86 }
87 }
88}
89
90impl ErrorCode {
95 #[cold]
96 #[must_use]
97 pub fn c_description(&self) -> &'static [u8] {
98 match self.0 {
99 0 => "no error, everything went ok\0",
100 1 => "nothing done yet\0",
101
102 10 => "end of input memory reached without huffman end code\0",
104
105 11 => "error in code tree made it jump outside of huffman tree\0",
107
108 13..=15 => "problem while processing dynamic deflate block\0",
110 16 => "unexisting code while processing dynamic deflate block\0",
111 18 => "invalid distance code while inflating\0",
112 17 | 19 | 22 => "end of out buffer memory reached while inflating\0",
113 20 => "invalid deflate block BTYPE encountered while decoding\0",
114 21 => "NLEN is not ones complement of LEN in a deflate block\0",
115
116 23 => "end of in buffer memory reached while inflating\0",
121 24 => "invalid FCHECK in zlib header\0",
122 25 => "invalid compression method in zlib header\0",
123 26 => "FDICT encountered in zlib header while it\'s not used for PNG\0",
124 27 => "PNG file is smaller than a PNG header\0",
125 28 => "incorrect PNG signature, it\'s no PNG or corrupted\0",
127 29 => "first chunk is not the header chunk\0",
128 30 => "chunk length too large, chunk broken off at end of file\0",
129 31 => "illegal PNG color type or bpp\0",
130 32 => "illegal PNG compression method\0",
131 33 => "illegal PNG filter method\0",
132 34 => "illegal PNG interlace method\0",
133 35 => "chunk length of a chunk is too large or the chunk too small\0",
134 36 => "illegal PNG filter type encountered\0",
135 37 => "illegal bit depth for this color type given\0",
136 38 => "the palette is too big\0",
137 39 => "more palette alpha values given in tRNS chunk than there are colors in the palette\0",
139 40 => "tRNS chunk has wrong size for greyscale image\0",
140 41 => "tRNS chunk has wrong size for RGB image\0",
141 42 => "tRNS chunk appeared while it was not allowed for this color type\0",
142 43 => "bKGD chunk has wrong size for palette image\0",
143 44 => "bKGD chunk has wrong size for greyscale image\0",
144 45 => "bKGD chunk has wrong size for RGB image\0",
145 48 => "empty input buffer given to decoder. Maybe caused by non-existing file?\0",
146 49 | 50 => "jumped past memory while generating dynamic huffman tree\0",
147 51 => "jumped past memory while inflating huffman block\0",
148 52 => "jumped past memory while inflating\0",
149 53 => "size of zlib data too small\0",
150 54 => "repeat symbol in tree while there was no value symbol yet\0",
151
152 55 => "jumped past tree while generating huffman tree\0",
156 56 => "given output image colortype or bitdepth not supported for color conversion\0",
157 57 => "invalid CRC encountered (checking CRC can be disabled)\0",
158 58 => "invalid ADLER32 encountered (checking ADLER32 can be disabled)\0",
159 59 => "requested color conversion not supported\0",
160 60 => "invalid window size given in the settings of the encoder (must be 0-32768)\0",
161 61 => "invalid BTYPE given in the settings of the encoder (only 0, 1 and 2 are allowed)\0",
162
163 62 => "conversion from color to greyscale not supported\0",
165 63 => "length of a chunk too long, max allowed for PNG is 2147483647 bytes per chunk\0",
166
167 64 => "the length of the END symbol 256 in the Huffman tree is 0\0",
170 66 => "the length of a text chunk keyword given to the encoder is longer than the maximum of 79 bytes\0",
171 67 => "the length of a text chunk keyword given to the encoder is smaller than the minimum of 1 byte\0",
172 68 => "tried to encode a PLTE chunk with a palette that has less than 1 or more than 256 colors\0",
173 69 => "unknown chunk type with \'critical\' flag encountered by the decoder\0",
174 71 => "unexisting interlace mode given to encoder (must be 0 or 1)\0",
175 72 => "while decoding, unexisting compression method encountering in zTXt or iTXt chunk (it must be 0)\0",
176 73 => "invalid tIME chunk size\0",
177 74 => "invalid pHYs chunk size\0",
178 75 => "no null termination char found while decoding text chunk\0",
180 76 => "iTXt chunk too short to contain required bytes\0",
181 77 => "integer overflow in buffer size\0",
182 78 => "failed to open file for reading\0",
183
184 79 => "failed to open file for writing\0",
186 80 => "tried creating a tree of 0 symbols\0",
187 81 => "lazy matching at pos 0 is impossible\0",
188 82 => "color conversion to palette requested while a color isn\'t in palette\0",
189 83 => "memory allocation failed\0",
190 84 => "given image too small to contain all pixels to be encoded\0",
191 86 => "impossible offset in lz77 encoding (internal bug)\0",
192 87 => "must provide custom zlib function pointer if LODEPNG_COMPILE_ZLIB is not defined\0",
193 88 => "invalid filter strategy given for EncoderSettings.filter_strategy\0",
194 89 => "text chunk keyword too short or long: must have size 1-79\0",
195
196 90 => "windowsize must be a power of two\0",
198 91 => "invalid decompressed idat size\0",
199 92 => "too many pixels, not supported\0",
200 93 => "zero width or height is invalid\0",
201 94 => "header chunk must have a size of 13 bytes\0",
202 _ => "unknown error code\0",
203 }.as_bytes()
204 }
205}
206
207impl From<TryReserveError> for Error {
208 #[cold]
209 fn from(_: TryReserveError) -> Self {
210 Self(NonZeroU32::new(83).unwrap())
211 }
212}
213
214#[test]
215fn error_str() {
216 assert_eq!(ErrorCode(83).as_str(), "memory allocation failed");
217}