runefs/
parse.rs

1//! Faster parsers using [nom](https://crates.io/crates/nom).
2
3use nom::{
4    bytes::complete::{tag, take_while},
5    error::ParseError,
6    number::complete::{be_u16, be_u32, be_u8},
7    sequence::terminated,
8    IResult,
9};
10
11/// Reads a 0-terminated string from the given buffer. Uses `String::from_utf8_lossy()` for the conversion.
12///
13/// # Errors
14///
15/// Parser can reach EOF early if not enough bytes are supplied or no 0-termination character is present.
16///
17/// # Example
18///
19/// ```
20/// use runefs::parse::rs_string;
21///
22/// # fn main() -> Result<(), runefs::Error> {
23/// let buffer = &[82, 117, 110, 105, 116, 101, 32, 98, 97, 114, 0, 52, 14, 85, 65, 4, 56];
24///
25/// let (buffer, string) = rs_string(buffer)?;
26///
27/// assert_eq!(&string, "Runite bar");
28/// assert_eq!(buffer, &[52, 14, 85, 65, 4, 56]);
29/// # Ok(())
30/// # }
31/// ```
32pub fn rs_string<'a, E: ParseError<&'a [u8]>>(buffer: &'a [u8]) -> IResult<&'a [u8], String, E> {
33    let (buffer, string) = terminated(take_while(|byte| byte != 0), tag([0]))(buffer)?;
34
35    Ok((buffer, String::from_utf8_lossy(string).to_string()))
36}
37
38pub fn be_u32_smart_compat<'a, E: ParseError<&'a [u8]>>(
39    buffer: &'a [u8],
40) -> IResult<&'a [u8], u32, E> {
41    let mut var1 = 0_u32;
42
43    let (mut buffer, mut var2) = be_u16_smart(buffer)?;
44
45    loop {
46        if var2 != 32767 {
47            break;
48        }
49
50        var1 += 32767;
51        let (buf, value) = be_u16_smart(buffer)?;
52        buffer = buf;
53        var2 = value;
54    }
55
56    var1 += var2 as u32;
57
58    Ok((buffer, var1))
59}
60
61/// be_u16_smart but as i16.
62///
63/// For more details see [`be_u16_smart`](be_u16_smart)
64///
65/// # Errors
66///
67/// Parser can reach EOF early if not enough bytes are supplied.
68pub fn be_i16_smart<'a, E: ParseError<&'a [u8]>>(buffer: &'a [u8]) -> IResult<&'a [u8], u16, E> {
69    if buffer[0] < 128 {
70        let (buffer, value) = be_u8(buffer)?;
71        Ok((buffer, value.wrapping_sub(64) as u16))
72    } else {
73        let (buffer, value) = be_u16(buffer)?;
74        Ok((buffer, value.wrapping_sub(0xC000)))
75    }
76}
77
78/// Reads 1 byte if the first byte < 128, reads 2 bytes otherwise.
79///
80/// # Errors
81///
82/// Parser can reach EOF early if not enough bytes are supplied.
83///
84/// # Example
85///
86/// ```
87/// use runefs::parse::be_u16_smart;
88///
89/// # fn main() -> Result<(), runefs::Error> {
90/// let buffer = &[17, 142, 64, 4, 24, 254];
91///
92/// let (buffer, value1) = be_u16_smart(buffer)?;
93/// let (buffer, value2) = be_u16_smart(buffer)?;
94///
95/// assert_eq!(value1, 17);
96/// assert_eq!(value2, 3648);
97/// assert_eq!(buffer, &[4, 24, 254]);
98/// # Ok(())
99/// # }
100/// ```
101pub fn be_u16_smart<'a, E: ParseError<&'a [u8]>>(buffer: &'a [u8]) -> IResult<&'a [u8], u16, E> {
102    if buffer[0] < 128 {
103        let (buffer, value) = be_u8(buffer)?;
104        Ok((buffer, value as u16))
105    } else {
106        let (buffer, value) = be_u16(buffer)?;
107        Ok((buffer, value.wrapping_sub(0x8000)))
108    }
109}
110
111/// Reads 2 bytes if the first byte <= -1 after calculations, reads 4 bytes otherwise.
112///
113/// # Errors
114///
115/// Parser can reach EOF early if not enough bytes are supplied.
116///
117/// # Example
118///
119/// ```
120/// use runefs::parse::be_u32_smart;
121///
122/// # fn main() -> Result<(), runefs::Error> {
123/// let buffer = &[255, 54, 2, 0, 62, 1, 42, 233];
124///
125/// let (buffer, value1) = be_u32_smart(buffer)?;
126/// let (buffer, value2) = be_u32_smart(buffer)?;
127///
128/// assert_eq!(value1, 2134245888);
129/// assert_eq!(value2, 15873);
130/// assert_eq!(buffer, &[42, 233]);
131/// # Ok(())
132/// # }
133/// ```
134pub fn be_u32_smart<'a, E: ParseError<&'a [u8]>>(buffer: &'a [u8]) -> IResult<&'a [u8], u32, E> {
135    if (buffer[0] ^ 0xff) as i8 <= -1 {
136        let (buffer, value) = be_u16(buffer)?;
137        Ok((buffer, value as u32))
138    } else {
139        let (buffer, value) = be_u32(buffer)?;
140        Ok((buffer, value & 0x7fffffff))
141    }
142}
143
144#[test]
145fn rs_string_parser() -> crate::Result<()> {
146    let buffer = vec![
147        82, 117, 110, 105, 116, 101, 32, 98, 97, 114, 0, 52, 14, 85, 65, 4, 56,
148    ];
149
150    let (buffer, string) = rs_string(&buffer)?;
151
152    assert_eq!(&string, "Runite bar");
153    assert_eq!(&buffer, &[52, 14, 85, 65, 4, 56]);
154
155    Ok(())
156}
157
158#[test]
159fn be_u16_smart_parser() -> crate::Result<()> {
160    let buffer = &[17, 142, 64, 4, 24, 254];
161    let (buffer, value1) = be_u16_smart(buffer)?;
162    let (buffer, value2) = be_u16_smart(buffer)?;
163    assert_eq!(value1, 17);
164    assert_eq!(value2, 3648);
165    assert_eq!(buffer, &[4, 24, 254]);
166
167    Ok(())
168}
169
170#[test]
171fn be_u32_smart_parser() -> crate::Result<()> {
172    let buffer = &[255, 54, 2, 0, 62, 1, 42, 233];
173    let (buffer, value1) = be_u32_smart(buffer)?;
174    let (buffer, value2) = be_u32_smart(buffer)?;
175    assert_eq!(value1, 2134245888);
176    assert_eq!(value2, 15873);
177    assert_eq!(buffer, &[42, 233]);
178
179    Ok(())
180}