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