aseprite_loader/binary/chunks/
tileset.rs1use bitflags::bitflags;
2use nom::{
3 bytes::complete::take,
4 combinator::{cond, flat_map},
5 Parser,
6};
7
8use crate::binary::{
9 errors::ParseResult,
10 scalars::{dword, parse_string, short, word, Dword, Short, Word},
11};
12
13#[derive(Debug)]
14pub struct TilesetChunk<'a> {
15 pub id: Dword,
17 pub flags: TilesetFlags,
19 pub number_of_tiles: Dword,
21 pub width: Word,
23 pub height: Word,
25 pub base_index: Short,
32 pub name: &'a str,
34 pub external_file: Option<TilesetExternalFile>,
36 pub tiles: Option<TilesetTiles<'a>>,
38}
39
40#[derive(Debug, Copy, Clone)]
41pub struct TilesetExternalFile {
42 pub external_file_id: Dword,
45 pub tileset_id: Dword,
47}
48
49#[derive(Debug)]
50pub struct TilesetTiles<'a> {
51 pub data: &'a [u8],
54}
55
56bitflags! {
57 #[derive(Debug)]
58 pub struct TilesetFlags: Dword {
59 const EXTERNAL_FILE = 1;
61 const TILES = 2;
63 const TILE_0_EMPTY = 4;
68 const XFLIP = 8;
72 const YFLIP = 16;
74 const DFLIP = 32;
76 }
77}
78
79pub fn parse_tileset_chunk(input: &[u8]) -> ParseResult<'_, TilesetChunk<'_>> {
80 let (input, id) = dword(input)?;
81 let (input, flags) = dword(input)?;
82 let flags = TilesetFlags::from_bits_truncate(flags);
83 let (input, number_of_tiles) = dword(input)?;
84 let (input, width) = word(input)?;
85 let (input, height) = word(input)?;
86 let (input, base_index) = short(input)?;
87 let (input, _) = take(14usize)(input)?;
88 let (input, name) = parse_string(input)?;
89 let (input, external_file) = cond(
90 flags.contains(TilesetFlags::EXTERNAL_FILE),
91 parse_external_file,
92 )
93 .parse(input)?;
94 let (input, tiles) = cond(flags.contains(TilesetFlags::TILES), parse_tiles).parse(input)?;
95 Ok((
96 input,
97 TilesetChunk {
98 id,
99 flags,
100 number_of_tiles,
101 width,
102 height,
103 base_index,
104 name,
105 external_file,
106 tiles,
107 },
108 ))
109}
110
111pub fn parse_external_file(input: &[u8]) -> ParseResult<'_, TilesetExternalFile> {
112 let (input, external_file_id) = dword(input)?;
113 let (input, tileset_id) = dword(input)?;
114 Ok((
115 input,
116 TilesetExternalFile {
117 external_file_id,
118 tileset_id,
119 },
120 ))
121}
122
123use nom::combinator::map;
124
125pub fn parse_tiles(input: &[u8]) -> ParseResult<'_, TilesetTiles<'_>> {
126 map(flat_map(dword, take), |data| TilesetTiles { data }).parse(input)
127}