Skip to main content

figif_core/traits/
decoder.rs

1//! GIF decoder trait for loading GIF files.
2
3use crate::error::Result;
4use crate::types::{DecodedFrame, GifMetadata};
5use std::io::Read;
6use std::path::Path;
7
8/// Trait for decoding GIF files into frames.
9///
10/// Implementations can choose different strategies:
11/// - Buffered: Load all frames into memory at once
12/// - Streaming: Decode frames lazily on-demand
13///
14/// # Example
15///
16/// ```ignore
17/// use figif_core::traits::GifDecoder;
18/// use figif_core::decoders::BufferedDecoder;
19///
20/// let decoder = BufferedDecoder::new();
21/// let frames = decoder.decode_file("animation.gif")?;
22/// ```
23pub trait GifDecoder: Send + Sync {
24    /// The type of iterator returned by decode operations.
25    type FrameIter: Iterator<Item = Result<DecodedFrame>>;
26
27    /// Decode a GIF from a file path.
28    ///
29    /// Returns an iterator over decoded frames.
30    fn decode_file(&self, path: impl AsRef<Path>) -> Result<Self::FrameIter>;
31
32    /// Decode a GIF from a byte slice.
33    ///
34    /// Returns an iterator over decoded frames.
35    fn decode_bytes(&self, data: &[u8]) -> Result<Self::FrameIter>;
36
37    /// Decode a GIF from any reader.
38    ///
39    /// Returns an iterator over decoded frames.
40    fn decode_reader<R: Read + Send>(&self, reader: R) -> Result<Self::FrameIter>;
41
42    /// Extract metadata without fully decoding all frames.
43    ///
44    /// This is useful for getting dimensions, frame count, and duration
45    /// without the overhead of decoding all pixel data.
46    fn metadata_from_bytes(&self, data: &[u8]) -> Result<GifMetadata>;
47
48    /// Extract metadata from a file.
49    fn metadata_from_file(&self, path: impl AsRef<Path>) -> Result<GifMetadata>;
50
51    /// Get the name of this decoder for logging/debugging.
52    fn name(&self) -> &'static str;
53}
54
55/// A decoder that collects all frames into a vector.
56///
57/// This is useful when you need random access to frames
58/// or when the streaming approach is not suitable.
59pub trait BufferedGifDecoder: GifDecoder {
60    /// Decode all frames into a vector.
61    fn decode_all(&self, data: &[u8]) -> Result<Vec<DecodedFrame>> {
62        self.decode_bytes(data)?.collect()
63    }
64
65    /// Decode all frames from a file into a vector.
66    fn decode_all_from_file(&self, path: impl AsRef<Path>) -> Result<Vec<DecodedFrame>> {
67        self.decode_file(path)?.collect()
68    }
69}