aseprite_loader/binary/
scalars.rs

1//! This file contains all the scalars defined in the
2//! specification file.
3//!
4//! The specification uses names like `WORD`, `SHORT`, etc. which
5//! was resulted in some confusion while implementing this parser.
6//! Therefore the parser uses the same types making it easy to
7//! compare it to the specification.
8
9use nom::{
10    bytes::complete::take,
11    combinator::{flat_map, map_res},
12    number::complete::{le_i16, le_i32, le_u128, le_u16, le_u32, le_u8},
13};
14
15use super::errors::{ParseError, ParseResult};
16
17pub type Byte = u8;
18pub type Word = u16;
19pub type Short = i16;
20pub type Dword = u32;
21pub type Long = i32;
22pub type Float = f32;
23pub type Double = f64;
24pub type Qword = u64;
25pub type Long64 = i64;
26pub type Uuid = u128;
27
28#[derive(Debug, Copy, Clone, Default, PartialEq, Eq)]
29pub struct Point {
30    pub x: Long,
31    pub y: Long,
32}
33
34#[derive(Debug, Copy, Clone, Default, PartialEq, Eq)]
35pub struct Size {
36    pub width: Long,
37    pub height: Long,
38}
39
40#[derive(Debug, Copy, Clone, Default, PartialEq, Eq)]
41pub struct Rect {
42    pub point: Point,
43    pub size: Size,
44}
45
46#[derive(Debug, Copy, Clone)]
47pub struct Fixed(pub u16, pub u16);
48
49#[derive(Debug, Copy, Clone)]
50pub struct RGB {
51    pub red: u8,
52    pub green: u8,
53    pub blue: u8,
54}
55
56#[derive(Debug, Copy, Clone, Default, PartialEq, Eq)]
57pub struct Color {
58    pub red: u8,
59    pub green: u8,
60    pub blue: u8,
61    pub alpha: u8,
62}
63
64#[inline]
65pub fn byte(input: &[u8]) -> ParseResult<'_, Byte> {
66    le_u8(input)
67}
68
69#[inline]
70pub fn word(input: &[u8]) -> ParseResult<'_, Word> {
71    le_u16(input)
72}
73
74#[inline]
75pub fn short(input: &[u8]) -> ParseResult<'_, Short> {
76    le_i16(input)
77}
78
79#[inline]
80pub fn dword(input: &[u8]) -> ParseResult<'_, Dword> {
81    le_u32(input)
82}
83
84#[inline]
85pub fn long(input: &[u8]) -> ParseResult<'_, Long> {
86    le_i32(input)
87}
88
89pub fn parse_point(input: &[u8]) -> ParseResult<'_, Point> {
90    let (input, x) = long(input)?;
91    let (input, y) = long(input)?;
92    Ok((input, Point { x, y }))
93}
94
95pub fn parse_size(input: &[u8]) -> ParseResult<'_, Size> {
96    let (input, width) = long(input)?;
97    let (input, height) = long(input)?;
98    Ok((input, Size { width, height }))
99}
100
101pub fn parse_rect(input: &[u8]) -> ParseResult<'_, Rect> {
102    let (input, point) = parse_point(input)?;
103    let (input, size) = parse_size(input)?;
104    Ok((input, Rect { point, size }))
105}
106
107/// Parse a DWORD as size information and make sure the
108/// parsed size no less than 4. The latter is important as
109/// this function is used when parsing frames and chunks
110/// where the size includes itself.
111pub fn dword_size<'a>(input: &'a [u8], f: fn(Dword) -> ParseError<'a>) -> ParseResult<'a, Dword> {
112    let (input, size) = dword(input)?;
113    if size >= 4 {
114        Ok((input, size))
115    } else {
116        Err(nom::Err::Failure(f(size)))
117    }
118}
119
120pub fn parse_dword_as_usize(input: &[u8]) -> ParseResult<'_, usize> {
121    let (input, size) = dword(input)?;
122    let size = size
123        .try_into()
124        .map_err(|_| nom::Err::Failure(ParseError::DwordToUsize(size)))?;
125    Ok((input, size))
126}
127
128pub fn parse_dword_as_u8<'a>(input: &'a [u8], e: ParseError<'a>) -> ParseResult<'a, u8> {
129    let (input, size) = dword(input)?;
130    let size = size.try_into().map_err(|_| nom::Err::Failure(e))?;
131    Ok((input, size))
132}
133
134pub fn parse_string(input: &[u8]) -> ParseResult<'_, &str> {
135    map_res(flat_map(word, take), std::str::from_utf8)(input)
136}
137
138pub fn parse_uuid(input: &[u8]) -> ParseResult<'_, Uuid> {
139    le_u128(input)
140}
141
142pub fn fixed(input: &[u8]) -> ParseResult<'_, Fixed> {
143    let (input, low) = le_u16(input)?;
144    let (input, high) = le_u16(input)?;
145    Ok((input, Fixed(high, low)))
146}
147
148pub fn parse_color(input: &[u8]) -> ParseResult<'_, Color> {
149    let (input, red) = byte(input)?;
150    let (input, green) = byte(input)?;
151    let (input, blue) = byte(input)?;
152    let (input, alpha) = byte(input)?;
153    Ok((
154        input,
155        Color {
156            red,
157            green,
158            blue,
159            alpha,
160        },
161    ))
162}
163
164pub fn parse_rgb(input: &[u8]) -> ParseResult<'_, RGB> {
165    let (input, red) = byte(input)?;
166    let (input, green) = byte(input)?;
167    let (input, blue) = byte(input)?;
168    Ok((input, RGB { red, green, blue }))
169}