Skip to content

Commit c314fdc

Browse files
authored
Merge pull request #163 from kornelski/public-api
Public API cleanups
2 parents bfd0d35 + c5b1a6e commit c314fdc

File tree

3 files changed

+47
-81
lines changed

3 files changed

+47
-81
lines changed

src/encoder.rs

Lines changed: 21 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -7,39 +7,33 @@ use std::borrow::Cow;
77

88
use weezl::{BitOrder, encode::Encoder as LzwEncoder};
99

10-
use crate::traits::{WriteBytesExt};
10+
use crate::traits::WriteBytesExt;
1111
use crate::common::{AnyExtension, Block, DisposalMethod, Extension, Frame};
1212

13+
/// The image has incorrect properties, making it impossible to encode as a gif.
1314
#[derive(Debug)]
14-
enum FormatErrorKind {
15+
#[non_exhaustive]
16+
pub enum EncodingFormatError {
1517
/// The image has too many colors.
1618
TooManyColors,
1719
/// The image has no color palette which is required.
1820
MissingColorPalette,
19-
}
20-
21-
/// The image has incorrect properties, making it impossible to encode as a gif.
22-
#[derive(Debug)]
23-
pub struct EncodingFormatError {
24-
kind: FormatErrorKind
21+
/// LZW data is not valid for GIF. This may happen when wrong buffer is given to `write_lzw_pre_encoded_frame`
22+
InvalidMinCodeSize,
2523
}
2624

2725
impl error::Error for EncodingFormatError {}
2826
impl fmt::Display for EncodingFormatError {
27+
#[cold]
2928
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
30-
match self.kind {
31-
FormatErrorKind::TooManyColors => write!(fmt, "the image has too many colors"),
32-
FormatErrorKind::MissingColorPalette => write!(fmt, "the GIF format requires a color palette but none was given")
29+
match self {
30+
Self::TooManyColors => write!(fmt, "the image has too many colors"),
31+
Self::MissingColorPalette => write!(fmt, "the GIF format requires a color palette but none was given"),
32+
Self::InvalidMinCodeSize => write!(fmt, "LZW data is invalid"),
3333
}
3434
}
3535
}
3636

37-
impl From<FormatErrorKind> for EncodingFormatError {
38-
fn from(kind: FormatErrorKind) -> Self {
39-
EncodingFormatError { kind }
40-
}
41-
}
42-
4337
#[derive(Debug)]
4438
/// Encoding error.
4539
pub enum EncodingError {
@@ -50,6 +44,7 @@ pub enum EncodingError {
5044
}
5145

5246
impl fmt::Display for EncodingError {
47+
#[cold]
5348
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
5449
match self {
5550
EncodingError::Io(err) => err.fmt(fmt),
@@ -59,6 +54,7 @@ impl fmt::Display for EncodingError {
5954
}
6055

6156
impl error::Error for EncodingError {
57+
#[cold]
6258
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
6359
match self {
6460
EncodingError::Io(err) => Some(err),
@@ -68,24 +64,19 @@ impl error::Error for EncodingError {
6864
}
6965

7066
impl From<io::Error> for EncodingError {
67+
#[cold]
7168
fn from(err: io::Error) -> Self {
7269
EncodingError::Io(err)
7370
}
7471
}
7572

7673
impl From<EncodingFormatError> for EncodingError {
74+
#[cold]
7775
fn from(err: EncodingFormatError) -> Self {
7876
EncodingError::Format(err)
7977
}
8078
}
8179

82-
impl From<FormatErrorKind> for EncodingError {
83-
fn from(kind: FormatErrorKind) -> Self {
84-
EncodingError::Format(kind.into())
85-
}
86-
}
87-
88-
8980
/// Number of repetitions
9081
#[derive(Copy, Clone, Debug)]
9182
pub enum Repeat {
@@ -159,7 +150,7 @@ impl<W: Write> Encoder<W> {
159150
flags |= 0b1000_0000;
160151
let num_colors = palette.len() / 3;
161152
if num_colors > 256 {
162-
return Err(EncodingError::from(FormatErrorKind::TooManyColors));
153+
return Err(EncodingError::from(EncodingFormatError::TooManyColors));
163154
}
164155
// Size of global color table.
165156
flags |= flag_size(num_colors);
@@ -201,14 +192,14 @@ impl<W: Write> Encoder<W> {
201192
flags |= 0b1000_0000;
202193
let num_colors = palette.len() / 3;
203194
if num_colors > 256 {
204-
return Err(EncodingError::from(FormatErrorKind::TooManyColors));
195+
return Err(EncodingError::from(EncodingFormatError::TooManyColors));
205196
}
206197
flags |= flag_size(num_colors);
207198
writer.write_le(flags)?;
208199
self.write_color_table(palette)
209200
},
210201
None => if !self.global_palette {
211-
Err(EncodingError::from(FormatErrorKind::MissingColorPalette))
202+
Err(EncodingError::from(EncodingFormatError::MissingColorPalette))
212203
} else {
213204
writer.write_le(flags).map_err(Into::into)
214205
}
@@ -246,7 +237,7 @@ impl<W: Write> Encoder<W> {
246237
let writer = self.w.as_mut().unwrap();
247238
let num_colors = table.len() / 3;
248239
if num_colors > 256 {
249-
return Err(EncodingError::from(FormatErrorKind::TooManyColors));
240+
return Err(EncodingError::from(EncodingFormatError::TooManyColors));
250241
}
251242
let size = flag_size(num_colors);
252243
writer.write_all(&table[..num_colors * 3])?;
@@ -318,7 +309,7 @@ impl<W: Write> Encoder<W> {
318309
// empty data is allowed
319310
if let Some(&min_code_size) = frame.buffer.get(0) {
320311
if min_code_size > 11 || min_code_size < 2 {
321-
return Err(EncodingError::from(io::Error::new(io::ErrorKind::InvalidInput, "invalid code size")));
312+
return Err(EncodingError::Format(EncodingFormatError::InvalidMinCodeSize));
322313
}
323314
}
324315

@@ -429,5 +420,5 @@ fn flag_size(size: usize) -> u8 {
429420

430421
#[test]
431422
fn error_cast() {
432-
let _ : Box<dyn error::Error> = EncodingError::from(FormatErrorKind::MissingColorPalette).into();
423+
let _ : Box<dyn error::Error> = EncodingError::from(EncodingFormatError::MissingColorPalette).into();
433424
}

src/reader/decoder.rs

Lines changed: 23 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -33,21 +33,6 @@ impl error::Error for DecodingFormatError {
3333
}
3434
}
3535

36-
impl DecodingFormatError {
37-
// Cold hints the optimizer that the error paths are less likely.
38-
//
39-
// This function isn't inlined to reduce code size
40-
// when it's often used with a string literal.
41-
#[cold]
42-
fn new(
43-
err: impl Into<Box<dyn error::Error + Send + Sync>>,
44-
) -> Self {
45-
DecodingFormatError {
46-
underlying: err.into(),
47-
}
48-
}
49-
}
50-
5136
#[derive(Debug)]
5237
/// Decoding error.
5338
pub enum DecodingError {
@@ -58,11 +43,11 @@ pub enum DecodingError {
5843
}
5944

6045
impl DecodingError {
61-
#[inline]
62-
pub(crate) fn format(
63-
err: impl Into<Box<dyn error::Error + Send + Sync>>,
64-
) -> Self {
65-
DecodingError::Format(DecodingFormatError::new(err))
46+
#[cold]
47+
pub(crate) fn format(err: &'static str) -> Self {
48+
DecodingError::Format(DecodingFormatError {
49+
underlying: err.into(),
50+
})
6651
}
6752
}
6853

@@ -93,6 +78,13 @@ impl From<io::Error> for DecodingError {
9378
}
9479
}
9580

81+
impl From<io::ErrorKind> for DecodingError {
82+
#[cold]
83+
fn from(err: io::ErrorKind) -> Self {
84+
DecodingError::Io(io::Error::from(err))
85+
}
86+
}
87+
9688
impl From<DecodingFormatError> for DecodingError {
9789
#[inline]
9890
fn from(err: DecodingFormatError) -> Self {
@@ -118,6 +110,7 @@ pub enum FrameDataType {
118110

119111
/// Indicates whether a certain object has been decoded
120112
#[derive(Debug)]
113+
#[non_exhaustive]
121114
pub enum Decoded<'a> {
122115
/// Decoded nothing.
123116
Nothing,
@@ -257,11 +250,11 @@ impl LzwReader {
257250
Ok(LzwStatus::Done | LzwStatus::Ok) => {},
258251
Ok(LzwStatus::NoProgress) => {
259252
if self.check_for_end_code {
260-
return Err(io::Error::new(io::ErrorKind::InvalidData, "No end code in lzw stream"));
253+
return Err(io::Error::new(io::ErrorKind::InvalidData, "no end code in lzw stream"));
261254
}
262255
},
263-
Err(LzwError::InvalidCode) => {
264-
return Err(io::Error::new(io::ErrorKind::InvalidData, "invalid code in LZW stream").into());
256+
Err(err @ LzwError::InvalidCode) => {
257+
return Err(io::Error::new(io::ErrorKind::InvalidData, err).into());
265258
}
266259
}
267260
Ok((decoded.consumed_in, decoded.consumed_out))
@@ -272,7 +265,6 @@ impl LzwReader {
272265
pub struct StreamingDecoder {
273266
state: State,
274267
lzw_reader: LzwReader,
275-
skip_extensions: bool,
276268
skip_frame_decoding: bool,
277269
check_frame_consistency: bool,
278270
allow_unknown_blocks: bool,
@@ -289,7 +281,6 @@ pub struct StreamingDecoder {
289281

290282
/// One version number of the GIF standard.
291283
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
292-
#[non_exhaustive]
293284
pub enum Version {
294285
/// Version 87a, from May 1987.
295286
V87a,
@@ -324,7 +315,6 @@ impl StreamingDecoder {
324315
StreamingDecoder {
325316
state: Magic(0, [0; 6]),
326317
lzw_reader: LzwReader::new(options.check_for_end_code),
327-
skip_extensions: true,
328318
skip_frame_decoding: options.skip_frame_decoding,
329319
check_frame_consistency: options.check_frame_consistency,
330320
allow_unknown_blocks: options.allow_unknown_blocks,
@@ -435,15 +425,6 @@ impl StreamingDecoder {
435425
self.version
436426
}
437427

438-
/// Configure whether extensions are saved or skipped.
439-
#[deprecated = "Does not work as intended. In fact, doesn't do anything. This may disappear soon."]
440-
pub fn set_extensions(&mut self, extensions: Extensions) {
441-
self.skip_extensions = match extensions {
442-
Extensions::Skip => true,
443-
Extensions::Save => false,
444-
}
445-
}
446-
447428
fn next_state(&mut self, buf: &[u8], write_into: &mut OutputBuffer<'_>) -> Result<(usize, Decoded<'_>), DecodingError> {
448429
macro_rules! goto (
449430
($n:expr, $state:expr) => ({
@@ -464,7 +445,7 @@ impl StreamingDecoder {
464445
})
465446
);
466447

467-
let b = *buf.get(0).ok_or_else(|| DecodingError::format("empty buf"))?;
448+
let b = *buf.get(0).ok_or_else(|| io::ErrorKind::UnexpectedEof)?;
468449

469450
match self.state {
470451
Magic(i, mut version) => if i < 6 {
@@ -474,7 +455,7 @@ impl StreamingDecoder {
474455
self.version = match &version[3..] {
475456
b"87a" => Version::V87a,
476457
b"89a" => Version::V89a,
477-
_ => return Err(DecodingError::format("unsupported GIF version"))
458+
_ => return Err(DecodingError::format("malformed GIF header"))
478459
};
479460
goto!(U16Byte1(U16Value::ScreenWidth, b))
480461
} else {
@@ -533,7 +514,7 @@ impl StreamingDecoder {
533514
let global_table = global_flags & 0x80 != 0;
534515
let table_size = if global_table {
535516
let table_size = PLTE_CHANNELS * (1 << ((global_flags & 0b111) + 1) as usize);
536-
self.global_color_table.try_reserve_exact(table_size).map_err(|_| io::Error::from(io::ErrorKind::OutOfMemory))?;
517+
self.global_color_table.try_reserve_exact(table_size).map_err(|_| io::ErrorKind::OutOfMemory)?;
537518
table_size
538519
} else {
539520
0usize
@@ -587,7 +568,7 @@ impl StreamingDecoder {
587568
if local_table {
588569
let entries = PLTE_CHANNELS * (1 << (table_size + 1));
589570
let mut pal = Vec::new();
590-
pal.try_reserve_exact(entries).map_err(|_| io::Error::from(io::ErrorKind::OutOfMemory))?;
571+
pal.try_reserve_exact(entries).map_err(|_| io::ErrorKind::OutOfMemory)?;
591572
frame.palette = Some(pal);
592573
goto!(LocalPalette(entries))
593574
} else {
@@ -664,9 +645,7 @@ impl StreamingDecoder {
664645
}
665646
}
666647
} else {
667-
Err(DecodingError::format(
668-
"unknown extention block encountered"
669-
))
648+
Err(DecodingError::format("unknown block type encountered"))
670649
}
671650
}
672651
SkipBlock(left) => {
@@ -717,7 +696,7 @@ impl StreamingDecoder {
717696
(len, len)
718697
},
719698
OutputBuffer::Vec(vec) => {
720-
vec.try_reserve(n).map_err(|_| io::Error::from(io::ErrorKind::OutOfMemory))?;
699+
vec.try_reserve(n).map_err(|_| io::ErrorKind::OutOfMemory)?;
721700
vec.extend_from_slice(&buf[..n]);
722701
(n, n)
723702
},
@@ -787,5 +766,5 @@ impl StreamingDecoder {
787766

788767
#[test]
789768
fn error_cast() {
790-
let _ : Box<dyn error::Error> = DecodingError::Format(DecodingFormatError::new("testing")).into();
769+
let _ : Box<dyn error::Error> = DecodingError::format("testing").into();
791770
}

src/reader/mod.rs

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -194,9 +194,7 @@ impl<R: Read> ReadDecoder<R> {
194194
let (consumed, result) = {
195195
let buf = self.reader.fill_buf()?;
196196
if buf.is_empty() {
197-
return Err(DecodingError::format(
198-
"unexpected EOF"
199-
))
197+
return Err(io::ErrorKind::UnexpectedEof.into());
200198
}
201199

202200
// Dead code checks the lifetimes that the later mem::transmute can't.
@@ -328,9 +326,7 @@ impl<R> Decoder<R> where R: Read {
328326
let (width, height) = (frame.width, frame.height);
329327
let pixel_bytes = self.memory_limit
330328
.buffer_size(self.color_output, width, height)
331-
.ok_or_else(|| {
332-
DecodingError::format("image is too large to decode")
333-
})?;
329+
.ok_or_else(|| io::Error::new(io::ErrorKind::OutOfMemory, "image is too large"))?;
334330

335331
debug_assert_eq!(
336332
pixel_bytes, self.buffer_size(),
@@ -412,7 +408,7 @@ impl<R> Decoder<R> where R: Read {
412408
ColorOutput::RGBA => {
413409
let buffer_size = buf.len() / N_CHANNELS;
414410
if buffer_size == 0 {
415-
return Err(DecodingError::Io(io::Error::new(io::ErrorKind::InvalidInput, "odd-sized buffer")));
411+
return Err(DecodingError::format("odd-sized buffer"));
416412
}
417413
if self.buffer.len() < buffer_size {
418414
self.buffer.resize(buffer_size, 0);

0 commit comments

Comments
 (0)