@@ -184,33 +184,36 @@ impl<W: Write> Encoder<W> {
184
184
frame. needs_user_input ,
185
185
frame. transparent ,
186
186
) ) ?;
187
- let writer = self . w . as_mut ( ) . unwrap ( ) ;
188
- writer. write_le ( Block :: Image as u8 ) ?;
189
- writer. write_le ( frame. left ) ?;
190
- writer. write_le ( frame. top ) ?;
191
- writer. write_le ( frame. width ) ?;
192
- writer. write_le ( frame. height ) ?;
193
187
let mut flags = 0 ;
194
188
if frame. interlaced {
195
189
flags |= 0b0100_0000 ;
196
190
}
197
- match frame. palette {
191
+ let palette = match frame. palette {
198
192
Some ( ref palette) => {
199
193
flags |= 0b1000_0000 ;
200
194
let num_colors = palette. len ( ) / 3 ;
201
195
if num_colors > 256 {
202
196
return Err ( EncodingError :: from ( EncodingFormatError :: TooManyColors ) ) ;
203
197
}
204
198
flags |= flag_size ( num_colors) ;
205
- writer. write_le ( flags) ?;
206
- self . write_color_table ( palette)
199
+ Some ( palette)
207
200
} ,
208
- None => if !self . global_palette {
209
- Err ( EncodingError :: from ( EncodingFormatError :: MissingColorPalette ) )
210
- } else {
211
- writer. write_le ( flags) . map_err ( Into :: into)
212
- }
201
+ None if self . global_palette => None ,
202
+ _ => return Err ( EncodingError :: from ( EncodingFormatError :: MissingColorPalette ) )
203
+ } ;
204
+ let mut tmp = tmp_buf :: < 10 > ( ) ;
205
+ tmp. write_le ( Block :: Image as u8 ) ?;
206
+ tmp. write_le ( frame. left ) ?;
207
+ tmp. write_le ( frame. top ) ?;
208
+ tmp. write_le ( frame. width ) ?;
209
+ tmp. write_le ( frame. height ) ?;
210
+ tmp. write_le ( flags) ?;
211
+ let writer = self . writer ( ) ?;
212
+ tmp. finish ( & mut * writer) ?;
213
+ if let Some ( palette) = palette {
214
+ writer. write_all ( palette) ?;
213
215
}
216
+ Ok ( ( ) )
214
217
}
215
218
216
219
fn write_image_block ( & mut self , data : & [ u8 ] ) -> Result < ( ) , EncodingError > {
@@ -219,7 +222,7 @@ impl<W: Write> Encoder<W> {
219
222
. map_err ( |_| io:: Error :: from ( io:: ErrorKind :: OutOfMemory ) ) ?;
220
223
lzw_encode ( data, & mut self . buffer ) ;
221
224
222
- let writer = self . w . as_mut ( ) . unwrap ( ) ;
225
+ let writer = self . w . as_mut ( ) . ok_or ( io :: Error :: from ( io :: ErrorKind :: Unsupported ) ) ? ;
223
226
Self :: write_encoded_image_block ( writer, & self . buffer )
224
227
}
225
228
@@ -243,13 +246,13 @@ impl<W: Write> Encoder<W> {
243
246
}
244
247
245
248
fn write_color_table ( & mut self , table : & [ u8 ] ) -> Result < ( ) , EncodingError > {
246
- let writer = self . w . as_mut ( ) . unwrap ( ) ;
249
+ let writer = self . writer ( ) ? ;
247
250
let num_colors = table. len ( ) / 3 ;
248
251
if num_colors > 256 {
249
252
return Err ( EncodingError :: from ( EncodingFormatError :: TooManyColors ) ) ;
250
253
}
251
- let size = flag_size ( num_colors) ;
252
254
writer. write_all ( & table[ ..num_colors * 3 ] ) ?;
255
+ let size = flag_size ( num_colors) ;
253
256
// Waste some space as of gif spec
254
257
for _ in 0 ..( ( 2 << size) - num_colors) {
255
258
writer. write_all ( & [ 0 , 0 , 0 ] ) ?;
@@ -267,26 +270,30 @@ impl<W: Write> Encoder<W> {
267
270
if let Repetitions ( Repeat :: Finite ( 0 ) ) = extension {
268
271
return Ok ( ( ) ) ;
269
272
}
270
- let writer = self . w . as_mut ( ) . unwrap ( ) ;
273
+ let writer = self . writer ( ) ? ;
271
274
writer. write_le ( Block :: Extension as u8 ) ?;
272
275
match extension {
273
276
Control { flags, delay, trns } => {
274
- writer. write_le ( Extension :: Control as u8 ) ?;
275
- writer. write_le ( 4u8 ) ?;
276
- writer. write_le ( flags) ?;
277
- writer. write_le ( delay) ?;
278
- writer. write_le ( trns) ?;
277
+ let mut tmp = tmp_buf :: < 6 > ( ) ;
278
+ tmp. write_le ( Extension :: Control as u8 ) ?;
279
+ tmp. write_le ( 4u8 ) ?;
280
+ tmp. write_le ( flags) ?;
281
+ tmp. write_le ( delay) ?;
282
+ tmp. write_le ( trns) ?;
283
+ tmp. finish ( & mut * writer) ?;
279
284
}
280
285
Repetitions ( repeat) => {
281
- writer. write_le ( Extension :: Application as u8 ) ?;
282
- writer. write_le ( 11u8 ) ?;
283
- writer. write_all ( b"NETSCAPE2.0" ) ?;
284
- writer. write_le ( 3u8 ) ?;
285
- writer. write_le ( 1u8 ) ?;
286
- match repeat {
287
- Repeat :: Finite ( no) => writer. write_le ( no) ?,
288
- Repeat :: Infinite => writer. write_le ( 0u16 ) ?,
289
- }
286
+ let mut tmp = tmp_buf :: < 17 > ( ) ;
287
+ tmp. write_le ( Extension :: Application as u8 ) ?;
288
+ tmp. write_le ( 11u8 ) ?;
289
+ tmp. write_all ( b"NETSCAPE2.0" ) ?;
290
+ tmp. write_le ( 3u8 ) ?;
291
+ tmp. write_le ( 1u8 ) ?;
292
+ tmp. write_le ( match repeat {
293
+ Repeat :: Finite ( no) => no,
294
+ Repeat :: Infinite => 0u16 ,
295
+ } ) ?;
296
+ tmp. finish ( & mut * writer) ?;
290
297
}
291
298
}
292
299
writer. write_le ( 0u8 ) . map_err ( Into :: into)
@@ -298,7 +305,7 @@ impl<W: Write> Encoder<W> {
298
305
/// identifier (e.g. `Extension::Application as u8`). `data` are the extension payload blocks. If any
299
306
/// contained slice has a lenght > 255 it is automatically divided into sub-blocks.
300
307
pub fn write_raw_extension ( & mut self , func : AnyExtension , data : & [ & [ u8 ] ] ) -> io:: Result < ( ) > {
301
- let writer = self . w . as_mut ( ) . unwrap ( ) ;
308
+ let writer = self . writer ( ) ? ;
302
309
writer. write_le ( Block :: Extension as u8 ) ?;
303
310
writer. write_le ( func. 0 ) ?;
304
311
for block in data {
@@ -323,19 +330,20 @@ impl<W: Write> Encoder<W> {
323
330
}
324
331
325
332
self . write_frame_header ( frame) ?;
326
- let writer = self . w . as_mut ( ) . unwrap ( ) ;
333
+ let writer = self . writer ( ) ? ;
327
334
Self :: write_encoded_image_block ( writer, & frame. buffer )
328
335
}
329
336
330
337
/// Writes the logical screen desriptor
331
338
fn write_screen_desc ( & mut self , flags : u8 ) -> io:: Result < ( ) > {
332
- let writer = self . w . as_mut ( ) . unwrap ( ) ;
333
- writer. write_all ( b"GIF89a" ) ?;
334
- writer. write_le ( self . width ) ?;
335
- writer. write_le ( self . height ) ?;
336
- writer. write_le ( flags) ?; // packed field
337
- writer. write_le ( 0u8 ) ?; // bg index
338
- writer. write_le ( 0u8 ) // aspect ratio
339
+ let mut tmp = tmp_buf :: < 13 > ( ) ;
340
+ tmp. write_all ( b"GIF89a" ) ?;
341
+ tmp. write_le ( self . width ) ?;
342
+ tmp. write_le ( self . height ) ?;
343
+ tmp. write_le ( flags) ?; // packed field
344
+ tmp. write_le ( 0u8 ) ?; // bg index
345
+ tmp. write_le ( 0u8 ) ?; // aspect ratio
346
+ tmp. finish ( self . writer ( ) ?)
339
347
}
340
348
341
349
/// Gets a reference to the writer instance used by this encoder.
@@ -353,12 +361,17 @@ impl<W: Write> Encoder<W> {
353
361
/// Finishes writing, and returns the `io::Write` instance used by this encoder
354
362
pub fn into_inner ( mut self ) -> io:: Result < W > {
355
363
self . write_trailer ( ) ?;
356
- Ok ( self . w . take ( ) . unwrap ( ) )
364
+ self . w . take ( ) . ok_or ( io :: Error :: from ( io :: ErrorKind :: Unsupported ) )
357
365
}
358
366
359
367
/// Write the final tailer.
360
368
fn write_trailer ( & mut self ) -> io:: Result < ( ) > {
361
- self . w . as_mut ( ) . unwrap ( ) . write_le ( Block :: Trailer as u8 )
369
+ self . writer ( ) ?. write_le ( Block :: Trailer as u8 )
370
+ }
371
+
372
+ #[ inline]
373
+ fn writer ( & mut self ) -> io:: Result < & mut W > {
374
+ self . w . as_mut ( ) . ok_or ( io:: Error :: from ( io:: ErrorKind :: Unsupported ) )
362
375
}
363
376
}
364
377
@@ -438,6 +451,35 @@ fn flag_size(size: usize) -> u8 {
438
451
}
439
452
}
440
453
454
+ struct Buf < const N : usize > {
455
+ buf : [ u8 ; N ] , pos : usize
456
+ }
457
+
458
+ impl < const N : usize > Write for Buf < N > {
459
+ #[ inline( always) ]
460
+ fn write ( & mut self , buf : & [ u8 ] ) -> io:: Result < usize > {
461
+ let len = buf. len ( ) ;
462
+ let pos = self . pos ;
463
+ self . buf [ pos.. pos + len] . copy_from_slice ( buf) ;
464
+ self . pos += len;
465
+ Ok ( len)
466
+ }
467
+
468
+ fn flush ( & mut self ) -> io:: Result < ( ) > { Ok ( ( ) ) }
469
+ }
470
+
471
+ fn tmp_buf < const N : usize > ( ) -> Buf < N > {
472
+ Buf { buf : [ 0 ; N ] , pos : 0 }
473
+ }
474
+
475
+ impl < const N : usize > Buf < N > {
476
+ #[ inline( always) ]
477
+ fn finish ( & mut self , mut w : impl Write ) -> io:: Result < ( ) > {
478
+ debug_assert_eq ! ( self . pos, N ) ;
479
+ w. write_all ( & self . buf )
480
+ }
481
+ }
482
+
441
483
#[ test]
442
484
fn error_cast ( ) {
443
485
let _ : Box < dyn error:: Error > = EncodingError :: from ( EncodingFormatError :: MissingColorPalette ) . into ( ) ;
0 commit comments