aseprite_loader/binary/chunks/
palette.rs1use std::ops::RangeInclusive;
2
3use bitflags::bitflags;
4use nom::{bytes::complete::take, combinator::cond, multi::count, Parser};
5
6use crate::binary::{
7 errors::{ParseError, ParseResult},
8 palette::PaletteError,
9 scalars::{
10 parse_color, parse_dword_as_u8, parse_dword_as_usize, parse_string, word, Color, Word,
11 },
12};
13
14#[derive(Debug)]
15pub struct PaletteChunk<'a> {
16 pub indices: RangeInclusive<u8>,
17 pub entries: Vec<PaletteEntry<'a>>,
18}
19
20#[derive(Debug)]
21pub struct PaletteEntry<'a> {
22 pub color: Color,
23 pub name: Option<&'a str>,
24}
25
26bitflags! {
27 pub struct PaletteEntryFlags: Word {
28 const HAS_NAME = 0x1;
29 }
30}
31
32pub fn parse_palette_chunk(input: &[u8]) -> ParseResult<'_, PaletteChunk<'_>> {
33 let (input, palette_size) = parse_dword_as_usize(input)?;
34 let (input, first_color_index) = parse_dword_as_u8(
35 input,
36 ParseError::PaletteError(PaletteError::FirstColorIndexOutOfBounds),
37 )?;
38 let (input, last_color_index) = parse_dword_as_u8(
39 input,
40 ParseError::PaletteError(PaletteError::LastColorIndexOutOfBounds),
41 )?;
42 if first_color_index > last_color_index {
43 return Err(nom::Err::Failure(ParseError::PaletteError(
44 PaletteError::FirstColorIndexGreaterThanLastColorIndex,
45 )));
46 }
47 let (input, _) = take(8usize)(input)?;
48 let (input, entries) = count(parse_palette_entry, palette_size).parse(input)?;
49 Ok((
50 input,
51 PaletteChunk {
52 indices: (first_color_index..=last_color_index),
53 entries,
54 },
55 ))
56}
57
58pub fn parse_palette_entry(input: &[u8]) -> ParseResult<'_, PaletteEntry<'_>> {
59 let (input, flags) = word(input)?;
60 let flags = PaletteEntryFlags::from_bits_truncate(flags);
61 let (input, color) = parse_color(input)?;
62 let (input, name) =
63 cond(flags.contains(PaletteEntryFlags::HAS_NAME), parse_string).parse(input)?;
64 Ok((input, PaletteEntry { color, name }))
65}