1use 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
108pub 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}