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
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
use crate::providers::gif::block::GctMissingColor;
/// An error obtained when parsing a GIF file.
#[derive(Clone, Debug, PartialEq, PartialOrd)]
pub enum GifConstructionError {
/// Attempted to parse out magic number, but none was present.
NoMagicNumber,
/// The magic number was incorrect.
WeirdMagicNumber([u8; 3]),
/// There weren't enough bytes in the stream to get the GIF version for the
/// file's header.
///
/// This feature is required, so the parse failed.
NoGifVersion,
/// The GIF did not contain the required logical screen descriptor.
LogicalScreenDescriptorMissingData,
/// The LSD said that there should be a GCT, but a triplet was missing.
GlobalColorTableMissingTriplet {
/// The number of RGB triplets expected in the GCT.
expected_triplet_ct: u16,
/// The triplet that wasn't found.
errant_triplet: u8,
/// The color that wasn't found.
missing_color: GctMissingColor,
},
/// Unknown block found during the repeatable block section.
UnknownBlockFound {
/// The block's first byte.
byte: u8,
},
/// Unknown extension type found during the repeatable block section.
UnknownExtensionFound {
/// The block's label byte.
label: u8,
},
/// Extension had an unexpected block size.
ExtensionHasWeirdBlockSize {
/// The block size reported.
got: u8,
/// The block size expected by the extension type.
expected: u8,
},
/// The GIF 87a (1987 rev. a) specification does not support extension
/// blocks, but one was present anyway.
ExtensionFoundInGif87,
/// Not enough bytes were found.
NotEnoughBytes,
/// Block terminator was not `0x00`, but something else.
BlockTerminatorMismatch(
/// The value found instead of `0x00`.
u8,
),
/// The image descriptor had no separator.
ImageDescriptorNoSeparator,
/// The image descriptor has the wrong separator.
///
/// It should be `0x2c`.
ImageDescriptorSeparatorWrong(
/// The incorrect separator that we found.
u8,
),
/// The image descriptor is missing data.
///
/// Please check logs for more information.
ImageDescriptorMissingData,
/// The table-based image data block was missing its LZW
/// size field.
TableBasedImageDataNoLzw,
/// The graphics control extension block is missing data.
///
/// Please check logs for more information.
GraphicExtMissingData,
/// Comment extension was missing data.
///
/// Please check logs for more information.
CommentExtMissingData,
/// The app extension is missing data.
///
/// Please check logs for more information.
AppExtMissingData,
/// The plain text extension is missing data.
///
/// Please check the logs for more information.
PlainTextExtMissingData,
/// The trailer block was missing.
TrailerMissing,
}
impl core::error::Error for GifConstructionError {}
impl core::fmt::Display for GifConstructionError {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
match self {
GifConstructionError::NoMagicNumber => {
f.write_str("Attempted to parse out magic number, but none was present.")
}
GifConstructionError::WeirdMagicNumber(found) => write!(
f,
"The given file was not a GIF. \
First bytes should be `[G, I, F]`, but got: `{found:x?}`!",
),
GifConstructionError::NoGifVersion => f.write_str(
"There weren't enough bytes in the stream to get the \
GIF version for the file's header.",
),
GifConstructionError::LogicalScreenDescriptorMissingData => {
f.write_str("The GIF did not contain the required logical screen descriptor.")
}
GifConstructionError::GlobalColorTableMissingTriplet {
expected_triplet_ct,
errant_triplet,
missing_color,
} => write!(
f,
"The global color table is missing a triplet. \
Errant triplet was {errant_triplet}/{expected_triplet_ct} \
on color {missing_color:?}."
),
GifConstructionError::UnknownBlockFound { byte } => write!(
f,
"Unknown block found when parsing repeatable blocks. \
Block's first byte: `0x{byte:x}`",
),
GifConstructionError::UnknownExtensionFound { label } => write!(
f,
"Unknown extension found when parsing repeatable blocks. \
Extension's label: `0x{label:x}`",
),
GifConstructionError::ExtensionHasWeirdBlockSize { got, expected } => {
write!(
f,
"Extension had an unexpected block size! \
Got: {got} bytes, but expected: {expected} bytes."
)
}
GifConstructionError::ExtensionFoundInGif87 => f.write_str(
"A GIF of version 87a contained an extension, which violates the standard.",
),
GifConstructionError::NotEnoughBytes => {
f.write_str("Parser expected more bytes, but the input ran out of data.")
}
GifConstructionError::BlockTerminatorMismatch(got) => {
write!(
f,
"Expected block terminator (`0x00`), but found: `0x{got:x}`."
)
}
GifConstructionError::ImageDescriptorNoSeparator => {
f.write_str("An image descriptor had no separator.")
}
GifConstructionError::ImageDescriptorSeparatorWrong(got) => write!(
f,
"Expected separator in image descriptor (`0x2c`), but found: `0x{got:x}`."
),
GifConstructionError::ImageDescriptorMissingData => {
f.write_str("An image descriptor was missing required fields.")
}
GifConstructionError::TableBasedImageDataNoLzw => {
f.write_str("Table-based image data is missing its LZW size field.")
}
GifConstructionError::GraphicExtMissingData => {
f.write_str("Graphic control extension is missing data.")
}
GifConstructionError::CommentExtMissingData => {
f.write_str("Comment extension is missing data.")
}
GifConstructionError::AppExtMissingData => {
f.write_str("Application extension is missing data.")
}
GifConstructionError::PlainTextExtMissingData => {
f.write_str("Plain-text extension is missing data.")
}
GifConstructionError::TrailerMissing => f.write_str(
"The provided GIF file abrupted stopped without its required trailer (end) block.",
),
}
}
}