aseprite_loader/binary/
raw_frame.rs1use nom::{
2 bytes::complete::{tag, take},
3 combinator::{all_consuming, complete},
4 multi::many1,
5};
6
7use super::{
8 chunk::parse_chunks,
9 chunk::Chunk,
10 chunks::cel::CelChunk,
11 errors::{ParseError, ParseResult},
12 scalars::dword_size,
13 scalars::Word,
14 scalars::{parse_dword_as_usize, word},
15};
16
17#[derive(Debug)]
18pub struct RawFrame<'a> {
19 pub duration: Word,
20 pub chunks: Vec<Chunk<'a>>,
21}
22
23impl<'a> RawFrame<'a> {
24 pub fn cels(&self) -> impl Iterator<Item = &CelChunk<'_>> {
25 self.chunks.iter().filter_map(|chunk| {
26 if let Chunk::Cel(cel) = chunk {
27 Some(cel)
28 } else {
29 None
30 }
31 })
32 }
33}
34
35const FRAME_MAGIC_NUMBER: [u8; 2] = 0xF1FAu16.to_le_bytes();
36
37pub fn parse_frames(input: &[u8]) -> ParseResult<'_, Vec<RawFrame<'_>>> {
38 complete(all_consuming(many1(parse_rawframe)))(input)
39}
40
41pub fn parse_rawframe(input: &[u8]) -> ParseResult<'_, RawFrame<'_>> {
42 let (input, size) = dword_size(input, ParseError::InvalidFrameSize)?;
43 let (rest, input) = take(size - 4)(input)?;
45 let (input, _) = tag(FRAME_MAGIC_NUMBER)(input)?;
46 let (input, chunk_count) = word(input)?;
47 let (input, duration) = word(input)?;
48 let (input, _) = take(2usize)(input)?;
49 let (input, chunk_count) = match parse_dword_as_usize(input)? {
50 (input, 0) => (input, chunk_count.into()),
51 (input, chunk_count) => (input, chunk_count),
52 };
53 let (_, chunks) = parse_chunks(input, chunk_count)?;
54 Ok((rest, RawFrame { duration, chunks }))
55}