1use super::Leaf;
4use crate::parser::{Parse, Parser, ParserError};
5use bstr::BStr;
6use pretty_hex::PrettyHex;
7use std::fmt::{Debug, Display};
8use std::num::TryFromIntError;
9use tracing::warn;
10
11#[derive(Copy, Clone)]
16#[repr(transparent)]
17pub struct Number<'a> {
18 bytes: &'a [u8],
19}
20
21impl<'a> Number<'a> {
22 pub fn as_bytes(&self) -> &'a [u8] {
24 self.bytes
25 }
26
27 pub fn kind(&self) -> Leaf {
30 let mut p = Parser::new(self.bytes);
31 Leaf(p.u16().unwrap())
32 }
33}
34
35impl<'a> Parse<'a> for Number<'a> {
36 fn from_parser(p: &mut Parser<'a>) -> Result<Self, ParserError> {
37 let start = p.peek_rest();
38
39 let more_len = match Leaf(p.u16()?) {
40 lf if lf.is_immediate_numeric() => 0,
41 Leaf::LF_CHAR => 1,
42 Leaf::LF_SHORT => 2,
43 Leaf::LF_USHORT => 2,
44 Leaf::LF_LONG => 4,
45 Leaf::LF_ULONG => 4,
46 Leaf::LF_REAL32 => 4,
47 Leaf::LF_REAL64 => 8,
48 Leaf::LF_REAL80 => 10,
49 Leaf::LF_REAL128 => 16,
50 Leaf::LF_QUADWORD => 8,
51 Leaf::LF_UQUADWORD => 8,
52 Leaf::LF_REAL48 => 6,
53 Leaf::LF_COMPLEX32 => 8,
54 Leaf::LF_COMPLEX64 => 16,
55 Leaf::LF_COMPLEX80 => 20,
56 Leaf::LF_COMPLEX128 => 32,
57 Leaf::LF_VARSTRING => p.u16()? as usize,
58 Leaf::LF_OCTWORD => 16,
59 Leaf::LF_UOCTWORD => 16,
60 Leaf::LF_DECIMAL => 16,
61 Leaf::LF_DATE => 8,
62 Leaf::LF_UTF8STRING => {
63 p.skip_strz()?;
64 0
65 }
66 Leaf::LF_REAL16 => 2,
67 lf => {
68 warn!(leaf = ?lf, "unrecognized numeric leaf");
69 return Err(ParserError::new());
71 }
72 };
73
74 p.skip(more_len)?;
75 Ok(Self {
76 bytes: &start[..start.len() - p.len()],
77 })
78 }
79}
80
81impl<'a> Number<'a> {}
82
83macro_rules! try_from_number {
84 (
85 $t:ty
86 ) => {
87 impl<'a> TryFrom<Number<'a>> for $t {
88 type Error = TryFromIntError;
89
90 #[inline(never)]
91 fn try_from(value: Number<'a>) -> Result<Self, Self::Error> {
92 use map_parser_error_to_int_error as e;
93
94 let mut p = Parser::new(value.bytes);
95 Ok(match Leaf(e(p.u16())?) {
96 lf if lf.is_immediate_numeric() => Self::try_from(lf.0)?,
97 Leaf::LF_USHORT => Self::try_from(e(p.u16())?)?,
98 Leaf::LF_ULONG => Self::try_from(e(p.u32())?)?,
99 Leaf::LF_UQUADWORD => Self::try_from(e(p.u64())?)?,
100 Leaf::LF_CHAR => Self::try_from(e(p.i8())?)?,
101 Leaf::LF_SHORT => Self::try_from(e(p.i16())?)?,
102 Leaf::LF_LONG => Self::try_from(e(p.i32())?)?,
103 Leaf::LF_QUADWORD => Self::try_from(e(p.i64())?)?,
104 Leaf::LF_OCTWORD => Self::try_from(e(p.i128())?)?,
105 Leaf::LF_UOCTWORD => Self::try_from(e(p.u128())?)?,
106 _ => return Err(try_from_int_error()),
107 })
108 }
109 }
110 };
111}
112
113try_from_number!(i8);
114try_from_number!(i16);
115try_from_number!(i32);
116try_from_number!(i64);
117try_from_number!(i128);
118
119try_from_number!(u8);
120try_from_number!(u16);
121try_from_number!(u32);
122try_from_number!(u64);
123try_from_number!(u128);
124
125fn map_parser_error_to_int_error<T>(r: Result<T, ParserError>) -> Result<T, TryFromIntError> {
126 match r {
127 Ok(x) => Ok(x),
128 Err(ParserError) => Err(try_from_int_error()),
129 }
130}
131
132#[derive(Copy, Clone, Eq, PartialEq, Debug)]
134pub struct TryFromFloatError;
135
136impl From<ParserError> for TryFromFloatError {
137 fn from(_: ParserError) -> Self {
138 Self
139 }
140}
141
142impl<'a> TryFrom<Number<'a>> for f32 {
143 type Error = TryFromFloatError;
144
145 fn try_from(value: Number<'a>) -> Result<Self, Self::Error> {
146 let mut p = Parser::new(value.bytes);
147 Ok(match Leaf(p.u16()?) {
148 Leaf::LF_REAL32 => f32::from_le_bytes(p.array()?),
149 _ => return Err(TryFromFloatError),
150 })
151 }
152}
153
154impl<'a> TryFrom<Number<'a>> for f64 {
155 type Error = TryFromFloatError;
156
157 fn try_from(value: Number<'a>) -> Result<Self, Self::Error> {
158 let mut p = Parser::new(value.bytes);
159 Ok(match Leaf(p.u16()?) {
160 Leaf::LF_REAL32 => f32::from_le_bytes(p.array::<4>()?) as f64,
161 Leaf::LF_REAL64 => f64::from_le_bytes(p.array::<8>()?),
162 _ => return Err(TryFromFloatError),
163 })
164 }
165}
166
167#[derive(Copy, Clone, Eq, PartialEq, Debug)]
169pub struct TryFromStrError;
170
171impl From<ParserError> for TryFromStrError {
172 fn from(_: ParserError) -> Self {
173 Self
174 }
175}
176impl<'a> TryFrom<Number<'a>> for &'a BStr {
177 type Error = TryFromStrError;
178
179 fn try_from(value: Number<'a>) -> Result<Self, Self::Error> {
180 let mut p = Parser::new(value.bytes);
181 Ok(match Leaf(p.u16()?) {
182 Leaf::LF_UTF8STRING => p.strz()?,
183 Leaf::LF_VARSTRING => {
184 let len = p.u16()?;
185 let bytes = p.bytes(len as usize)?;
186 BStr::new(bytes)
187 }
188 _ => return Err(TryFromStrError),
189 })
190 }
191}
192
193impl<'a> Debug for Number<'a> {
194 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
195 Display::fmt(self, f)
196 }
197}
198
199impl<'a> Display for Number<'a> {
200 #[inline(never)]
201 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
202 fn e<T>(
203 f: &mut std::fmt::Formatter<'_>,
204 r: Result<T, ParserError>,
205 ) -> Result<T, std::fmt::Error> {
206 match r {
207 Ok(x) => Ok(x),
208 Err(ParserError) => {
209 f.write_str("??(parser error)")?;
210 Err(std::fmt::Error)
211 }
212 }
213 }
214
215 let mut p = Parser::new(self.bytes);
216
217 match Leaf(p.u16().unwrap()) {
218 lf if lf.is_immediate_numeric() => Display::fmt(&lf.0, f),
219 Leaf::LF_CHAR => Display::fmt(&e(f, p.i8())?, f),
220 Leaf::LF_SHORT => Display::fmt(&e(f, p.i16())?, f),
221 Leaf::LF_USHORT => Display::fmt(&e(f, p.u16())?, f),
222 Leaf::LF_LONG => Display::fmt(&e(f, p.i32())?, f),
223 Leaf::LF_ULONG => Display::fmt(&e(f, p.u32())?, f),
224 Leaf::LF_REAL32 => Display::fmt(&e(f, p.f32())?, f),
225 Leaf::LF_REAL64 => Display::fmt(&e(f, p.f64())?, f),
226 Leaf::LF_QUADWORD => Display::fmt(&e(f, p.i64())?, f),
227 Leaf::LF_UQUADWORD => Display::fmt(&e(f, p.u64())?, f),
228 Leaf::LF_VARSTRING => {
229 let len = p.u16().unwrap();
231 let s = BStr::new(p.bytes(len as usize).unwrap());
232 <BStr as Display>::fmt(s, f)
233 }
234 Leaf::LF_OCTWORD => Display::fmt(&e(f, p.i128())?, f),
235 Leaf::LF_UOCTWORD => Display::fmt(&e(f, p.u128())?, f),
236 Leaf::LF_UTF8STRING => {
237 let s = p.strz().unwrap();
238 <BStr as Display>::fmt(s, f)
239 }
240
241 lf => {
242 write!(f, "?? {lf:?} {:?}", self.bytes.hex_dump())
243 }
244 }
245 }
246}
247
248fn try_from_int_error() -> TryFromIntError {
249 u32::try_from(-1i8).unwrap_err()
250}
251
252#[cfg(test)]
253fn parse_number(bytes: &[u8]) -> Number {
254 let mut p = Parser::new(bytes);
255 let n = p.number().unwrap();
256 assert!(p.is_empty());
257 n
258}
259
260#[test]
261fn number_error() {
262 assert!(Number::parse(&[]).is_err()); assert!(Number::parse(&[0]).is_err()); assert!(Number::parse(&[0xff, 0xff]).is_err()); }
266
267#[test]
268fn number_immediate() {
269 let n = parse_number(&[0xaa, 0x70]);
271 assert_eq!(n.as_bytes(), &[0xaa, 0x70]);
272 assert_eq!(u32::try_from(n).unwrap(), 0x70aa);
273}
274
275#[test]
276fn number_char() {
277 let n = parse_number(&[0x00, 0x80, (-33i8) as u8]);
279 assert_eq!(i32::try_from(n).unwrap(), -33);
280
281 assert!(f32::try_from(n).is_err());
282 assert!(f64::try_from(n).is_err());
283 assert!(<&BStr>::try_from(n).is_err());
284}
285
286#[test]
287fn number_short() {
288 let n = parse_number(&[0x01, 0x80, 0xaa, 0x55]);
290 assert_eq!(i32::try_from(n).unwrap(), 0x55aa_i32);
291 assert_eq!(u32::try_from(n).unwrap(), 0x55aa_u32);
292
293 let n = parse_number(&[0x01, 0x80, 0x55, 0xaa]);
294 assert_eq!(i32::try_from(n).unwrap(), -21931_i32);
295 assert!(u32::try_from(n).is_err());
296
297 assert!(f32::try_from(n).is_err());
298 assert!(f64::try_from(n).is_err());
299 assert!(<&BStr>::try_from(n).is_err());
300}
301
302#[test]
303fn number_long() {
304 let n = parse_number(&[0x03, 0x80, 1, 2, 3, 4]);
306 assert_eq!(u32::try_from(n).unwrap(), 0x04030201_u32);
307 assert_eq!(i32::try_from(n).unwrap(), 0x04030201_i32);
308 assert!(u16::try_from(n).is_err());
309 assert!(i16::try_from(n).is_err());
310 assert!(u8::try_from(n).is_err());
311 assert!(i8::try_from(n).is_err());
312
313 let n = parse_number(&[0x03, 0x80, 0xfe, 0xff, 0xff, 0xff]);
315 assert!(u8::try_from(n).is_err());
316 assert!(u16::try_from(n).is_err());
317 assert!(u32::try_from(n).is_err());
318 assert!(u64::try_from(n).is_err());
319 assert!(u128::try_from(n).is_err());
320 assert_eq!(i8::try_from(n).unwrap(), -2);
321 assert_eq!(i16::try_from(n).unwrap(), -2);
322 assert_eq!(i32::try_from(n).unwrap(), -2);
323 assert_eq!(i64::try_from(n).unwrap(), -2);
324 assert_eq!(i128::try_from(n).unwrap(), -2);
325
326 assert!(f32::try_from(n).is_err());
327 assert!(f64::try_from(n).is_err());
328 assert!(<&BStr>::try_from(n).is_err());
329}
330
331#[test]
332fn number_real32() {
333 use std::f32::consts::PI;
334
335 let b: [u8; 4] = PI.to_le_bytes();
336 assert_eq!(b, [0xdb, 0x0f, 0x49, 0x40]); println!("f32 PI bytes: {:#x?}", b);
338
339 let n = parse_number(&[0x05, 0x80, 0xdb, 0x0f, 0x49, 0x40]);
341
342 assert!(u8::try_from(n).is_err());
344 assert!(u16::try_from(n).is_err());
345 assert!(u32::try_from(n).is_err());
346 assert!(u64::try_from(n).is_err());
347 assert!(u128::try_from(n).is_err());
348
349 assert!(i8::try_from(n).is_err());
350 assert!(i16::try_from(n).is_err());
351 assert!(i32::try_from(n).is_err());
352 assert!(i64::try_from(n).is_err());
353 assert!(i128::try_from(n).is_err());
354
355 assert_eq!(f32::try_from(n).unwrap(), PI);
357
358 let _ = f64::try_from(n).unwrap();
360}
361
362#[test]
363fn number_real64() {
364 use std::f64::consts::PI;
365
366 let b: [u8; 8] = PI.to_le_bytes();
367 assert_eq!(b, [0x18, 0x2d, 0x44, 0x54, 0xfb, 0x21, 0x9, 0x40]);
368 println!("f64 PI bytes: {:#x?}", b);
370
371 let n = parse_number(&[0x06, 0x80, 0x18, 0x2d, 0x44, 0x54, 0xfb, 0x21, 0x9, 0x40]);
373
374 assert!(u8::try_from(n).is_err());
376 assert!(u16::try_from(n).is_err());
377 assert!(u32::try_from(n).is_err());
378 assert!(u64::try_from(n).is_err());
379 assert!(u128::try_from(n).is_err());
380
381 assert!(i8::try_from(n).is_err());
382 assert!(i16::try_from(n).is_err());
383 assert!(i32::try_from(n).is_err());
384 assert!(i64::try_from(n).is_err());
385 assert!(i128::try_from(n).is_err());
386
387 assert_eq!(f64::try_from(n).unwrap(), PI);
389}
390
391#[test]
392fn number_strz() {
393 let n = parse_number(b"\x1b\x80Hello, world\0");
394 assert_eq!(n.kind(), Leaf::LF_UTF8STRING);
395 assert_eq!(<&BStr>::try_from(n).unwrap(), "Hello, world");
396
397 let n = parse_number(&[0x00, 0x80, (-33i8) as u8]);
398 assert!(<&BStr>::try_from(n).is_err());
399}
400
401#[test]
402fn number_varstring() {
403 let s = parse_number(b"\x10\x80\x0c\x00Hello, world");
404 assert_eq!(s.kind(), Leaf::LF_VARSTRING);
405 assert_eq!(<&BStr>::try_from(s).unwrap(), "Hello, world");
406}
407
408#[test]
409fn number_unsupported_types() {
410 let cases: &[(Leaf, usize)] = &[
413 (Leaf::LF_REAL80, 10),
414 (Leaf::LF_REAL128, 16),
415 (Leaf::LF_REAL48, 6),
416 (Leaf::LF_COMPLEX32, 8),
417 (Leaf::LF_COMPLEX64, 16),
418 (Leaf::LF_COMPLEX80, 20),
419 (Leaf::LF_COMPLEX128, 32),
420 (Leaf::LF_DECIMAL, 16),
421 (Leaf::LF_DATE, 8),
422 (Leaf::LF_REAL16, 2),
423 ];
424
425 for &(kind, num_zeroes) in cases.iter() {
426 let mut input = vec![0; 2 + num_zeroes];
427 input[0] = kind.0 as u8;
428 input[1] = (kind.0 >> 8) as u8;
429 let n = parse_number(&input);
430 assert_eq!(kind, n.kind());
431 }
432}
433
434#[test]
435fn display() {
436 let cases: &[(&[u8], &str)] = &[
437 (&[0x01, 0x04], "immediate 1025"),
438 (&[0x00, 0x80, 0xff], "LF_CHAR -1"),
439 (&[0x01, 0x80, 0xfe, 0xff], "LF_SHORT -2"),
440 (&[0x02, 0x80, 0xfd, 0xff], "LF_USHORT 65533"),
441 (&[0x03, 0x80, 0xfc, 0xff, 0xff, 0xff], "LF_LONG -4"),
442 (&[0x04, 0x80, 0x00, 0x00, 0x02, 0x00], "LF_ULONG 131072"),
443 (&[0x05, 0x80, 0xdb, 0x0f, 0x49, 0x40], "LF_REAL32 3.1415927"),
444 (
445 &[0x06, 0x80, 0x18, 0x2d, 0x44, 0x54, 0xfb, 0x21, 0x9, 0x40],
446 "LF_REAL64 3.141592653589793",
447 ),
448 (
449 &[0x09, 0x80, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff],
450 "LF_QUADWORD -5",
451 ),
452 (
453 &[0x0a, 0x80, 0x00, 0xe4, 0x0b, 0x54, 0x02, 0x00, 0x00, 0x00],
454 "LF_UQUADWORD 10000000000",
455 ),
456 (
457 &[
458 0x17, 0x80, 0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
459 0xff, 0xff, 0xff, 0xff,
460 ],
461 "LF_OCTWORD -6",
462 ),
463 (
464 &[
465 0x18, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
466 0x00, 0x00, 0x00, 0x00,
467 ],
468 "LF_UOCTWORD 1",
469 ),
470 ];
471
472 for &(input, expected_output) in cases.iter() {
473 let mut p = Parser::new(input);
474 let leaf = Leaf(p.u16().unwrap());
475
476 let n = parse_number(input);
477
478 let actual_output = if leaf.is_immediate_numeric() {
479 format!("immediate {n}")
480 } else {
481 format!("{leaf:?} {n}")
482 };
483
484 assert_eq!(actual_output, expected_output, "bytes: {:#x?}", input);
485
486 let _ = format!("{:?}", n);
488 }
489}
490
491#[test]
492fn display_bogus() {
493 let bogus_num = Number {
498 bytes: &[0xff, 0xff, 0xaa, 0xaa, 0xaa],
499 };
500 println!("bogus_num = {bogus_num}");
501}