1use core::ops::Range;
7use core::convert::{TryFrom, TryInto};
8
9pub trait FromData: Sized {
13 const SIZE: usize;
17
18 fn parse(data: &[u8]) -> Option<Self>;
20}
21
22impl FromData for () {
23 const SIZE: usize = 0;
24
25 #[inline]
26 fn parse(_: &[u8]) -> Option<Self> {
27 Some(())
28 }
29}
30
31impl FromData for u8 {
32 const SIZE: usize = 1;
33
34 #[inline]
35 fn parse(data: &[u8]) -> Option<Self> {
36 data.get(0).copied()
37 }
38}
39
40impl FromData for i8 {
41 const SIZE: usize = 1;
42
43 #[inline]
44 fn parse(data: &[u8]) -> Option<Self> {
45 data.get(0).copied().map(|n| n as i8)
46 }
47}
48
49impl FromData for u16 {
50 const SIZE: usize = 2;
51
52 #[inline]
53 fn parse(data: &[u8]) -> Option<Self> {
54 data.try_into().ok().map(u16::from_be_bytes)
55 }
56}
57
58impl FromData for i16 {
59 const SIZE: usize = 2;
60
61 #[inline]
62 fn parse(data: &[u8]) -> Option<Self> {
63 data.try_into().ok().map(i16::from_be_bytes)
64 }
65}
66
67impl FromData for u32 {
68 const SIZE: usize = 4;
69
70 #[inline]
71 fn parse(data: &[u8]) -> Option<Self> {
72 data.try_into().ok().map(u32::from_be_bytes)
73 }
74}
75
76impl FromData for i32 {
77 const SIZE: usize = 4;
78
79 #[inline]
80 fn parse(data: &[u8]) -> Option<Self> {
81 data.try_into().ok().map(i32::from_be_bytes)
82 }
83}
84
85#[derive(Clone, Copy, Debug)]
91pub struct U24(pub u32);
92
93impl FromData for U24 {
94 const SIZE: usize = 3;
95
96 #[inline]
97 fn parse(data: &[u8]) -> Option<Self> {
98 let data: [u8; 3] = data.try_into().ok()?;
99 Some(U24(u32::from_be_bytes([0, data[0], data[1], data[2]])))
100 }
101}
102
103
104#[derive(Clone, Copy, Debug)]
106pub struct F2DOT14(pub i16);
107
108impl F2DOT14 {
109 #[inline]
111 pub fn to_f32(&self) -> f32 {
112 f32::from(self.0) / 16384.0
113 }
114}
115
116impl FromData for F2DOT14 {
117 const SIZE: usize = 2;
118
119 #[inline]
120 fn parse(data: &[u8]) -> Option<Self> {
121 i16::parse(data).map(F2DOT14)
122 }
123}
124
125
126#[derive(Clone, Copy, Debug)]
128pub struct Fixed(pub f32);
129
130impl FromData for Fixed {
131 const SIZE: usize = 4;
132
133 #[inline]
134 fn parse(data: &[u8]) -> Option<Self> {
135 i32::parse(data).map(|n| Fixed(n as f32 / 65536.0))
137 }
138}
139
140
141pub trait NumFrom<T>: Sized {
147 fn num_from(_: T) -> Self;
149}
150
151impl NumFrom<u32> for usize {
152 #[inline]
153 fn num_from(v: u32) -> Self {
154 #[cfg(any(target_pointer_width = "32", target_pointer_width = "64"))]
155 {
156 v as usize
157 }
158
159 }
161}
162
163
164pub trait TryNumFrom<T>: Sized {
166 fn try_num_from(_: T) -> Option<Self>;
168}
169
170impl TryNumFrom<f32> for u8 {
171 #[inline]
172 fn try_num_from(v: f32) -> Option<Self> {
173 i32::try_num_from(v).and_then(|v| u8::try_from(v).ok())
174 }
175}
176
177impl TryNumFrom<f32> for i16 {
178 #[inline]
179 fn try_num_from(v: f32) -> Option<Self> {
180 i32::try_num_from(v).and_then(|v| i16::try_from(v).ok())
181 }
182}
183
184impl TryNumFrom<f32> for u16 {
185 #[inline]
186 fn try_num_from(v: f32) -> Option<Self> {
187 i32::try_num_from(v).and_then(|v| u16::try_from(v).ok())
188 }
189}
190
191impl TryNumFrom<f32> for i32 {
192 #[inline]
193 fn try_num_from(v: f32) -> Option<Self> {
194 const MIN: f32 = core::i32::MIN as f32;
202 const MAX_P1: f32 = core::i32::MAX as f32;
205 if v >= MIN && v < MAX_P1 {
206 Some(v as i32)
207 } else {
208 None
209 }
210 }
211}
212
213
214#[derive(Clone, Copy)]
218pub struct LazyArray16<'a, T> {
219 data: &'a [u8],
220 data_type: core::marker::PhantomData<T>,
221}
222
223impl<T> Default for LazyArray16<'_, T> {
224 #[inline]
225 fn default() -> Self {
226 LazyArray16 {
227 data: &[],
228 data_type: core::marker::PhantomData,
229 }
230 }
231}
232
233impl<'a, T: FromData> LazyArray16<'a, T> {
234 #[inline]
236 pub fn new(data: &'a [u8]) -> Self {
237 LazyArray16 {
238 data,
239 data_type: core::marker::PhantomData,
240 }
241 }
242
243 #[inline]
245 pub fn get(&self, index: u16) -> Option<T> {
246 if index < self.len() {
247 let start = usize::from(index) * T::SIZE;
248 let end = start + T::SIZE;
249 self.data.get(start..end).and_then(T::parse)
250 } else {
251 None
252 }
253 }
254
255 #[inline]
257 pub fn last(&self) -> Option<T> {
258 if !self.is_empty() {
259 self.get(self.len() - 1)
260 } else {
261 None
262 }
263 }
264
265 #[inline]
267 pub fn slice(&self, range: Range<u16>) -> Option<Self> {
268 let start = usize::from(range.start) * T::SIZE;
269 let end = usize::from(range.end) * T::SIZE;
270 Some(LazyArray16 {
271 data: self.data.get(start..end)?,
272 ..LazyArray16::default()
273 })
274 }
275
276 #[inline]
278 pub fn len(&self) -> u16 {
279 (self.data.len() / T::SIZE) as u16
280 }
281
282 #[inline]
284 pub fn is_empty(&self) -> bool {
285 self.len() == 0
286 }
287
288 #[inline]
290 pub fn binary_search(&self, key: &T) -> Option<(u16, T)>
291 where T: Ord
292 {
293 self.binary_search_by(|p| p.cmp(key))
294 }
295
296 #[inline]
298 pub fn binary_search_by<F>(&self, mut f: F) -> Option<(u16, T)>
299 where F: FnMut(&T) -> core::cmp::Ordering
300 {
301 use core::cmp::Ordering;
304
305 let mut size = self.len();
306 if size == 0 {
307 return None;
308 }
309
310 let mut base = 0;
311 while size > 1 {
312 let half = size / 2;
313 let mid = base + half;
314 let cmp = f(&self.get(mid)?);
318 base = if cmp == Ordering::Greater { base } else { mid };
319 size -= half;
320 }
321
322 let value = self.get(base)?;
324 if f(&value) == Ordering::Equal { Some((base, value)) } else { None }
325 }
326}
327
328impl<'a, T: FromData + core::fmt::Debug + Copy> core::fmt::Debug for LazyArray16<'a, T> {
329 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
330 f.debug_list().entries(self.into_iter()).finish()
331 }
332}
333
334impl<'a, T: FromData> IntoIterator for LazyArray16<'a, T> {
335 type Item = T;
336 type IntoIter = LazyArrayIter16<'a, T>;
337
338 #[inline]
339 fn into_iter(self) -> Self::IntoIter {
340 LazyArrayIter16 {
341 data: self,
342 index: 0,
343 }
344 }
345}
346
347
348#[derive(Clone, Copy)]
350#[allow(missing_debug_implementations)]
351pub struct LazyArrayIter16<'a, T> {
352 data: LazyArray16<'a, T>,
353 index: u16,
354}
355
356impl<T: FromData> Default for LazyArrayIter16<'_, T> {
357 #[inline]
358 fn default() -> Self {
359 LazyArrayIter16 {
360 data: LazyArray16::new(&[]),
361 index: 0,
362 }
363 }
364}
365
366impl<'a, T: FromData> Iterator for LazyArrayIter16<'a, T> {
367 type Item = T;
368
369 #[inline]
370 fn next(&mut self) -> Option<Self::Item> {
371 self.index += 1; self.data.get(self.index - 1)
373 }
374}
375
376
377#[derive(Clone, Copy)]
381pub struct LazyArray32<'a, T> {
382 data: &'a [u8],
383 data_type: core::marker::PhantomData<T>,
384}
385
386impl<T> Default for LazyArray32<'_, T> {
387 #[inline]
388 fn default() -> Self {
389 LazyArray32 {
390 data: &[],
391 data_type: core::marker::PhantomData,
392 }
393 }
394}
395
396impl<'a, T: FromData> LazyArray32<'a, T> {
397 #[inline]
399 pub fn new(data: &'a [u8]) -> Self {
400 LazyArray32 {
401 data,
402 data_type: core::marker::PhantomData,
403 }
404 }
405
406 #[inline]
408 pub fn get(&self, index: u32) -> Option<T> {
409 if index < self.len() {
410 let start = usize::num_from(index) * T::SIZE;
411 let end = start + T::SIZE;
412 self.data.get(start..end).and_then(T::parse)
413 } else {
414 None
415 }
416 }
417
418 #[inline]
420 pub fn len(&self) -> u32 {
421 (self.data.len() / T::SIZE) as u32
422 }
423
424 #[inline]
426 pub fn binary_search(&self, key: &T) -> Option<(u32, T)>
427 where T: Ord
428 {
429 self.binary_search_by(|p| p.cmp(key))
430 }
431
432 #[inline]
434 pub fn binary_search_by<F>(&self, mut f: F) -> Option<(u32, T)>
435 where F: FnMut(&T) -> core::cmp::Ordering
436 {
437 use core::cmp::Ordering;
440
441 let mut size = self.len();
442 if size == 0 {
443 return None;
444 }
445
446 let mut base = 0;
447 while size > 1 {
448 let half = size / 2;
449 let mid = base + half;
450 let cmp = f(&self.get(mid)?);
454 base = if cmp == Ordering::Greater { base } else { mid };
455 size -= half;
456 }
457
458 let value = self.get(base)?;
460 if f(&value) == Ordering::Equal { Some((base, value)) } else { None }
461 }
462}
463
464impl<'a, T: FromData + core::fmt::Debug + Copy> core::fmt::Debug for LazyArray32<'a, T> {
465 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
466 f.debug_list().entries(self.into_iter()).finish()
467 }
468}
469
470impl<'a, T: FromData> IntoIterator for LazyArray32<'a, T> {
471 type Item = T;
472 type IntoIter = LazyArrayIter32<'a, T>;
473
474 #[inline]
475 fn into_iter(self) -> Self::IntoIter {
476 LazyArrayIter32 {
477 data: self,
478 index: 0,
479 }
480 }
481}
482
483
484#[derive(Clone, Copy)]
486#[allow(missing_debug_implementations)]
487pub struct LazyArrayIter32<'a, T> {
488 data: LazyArray32<'a, T>,
489 index: u32,
490}
491
492impl<'a, T: FromData> Iterator for LazyArrayIter32<'a, T> {
493 type Item = T;
494
495 #[inline]
496 fn next(&mut self) -> Option<Self::Item> {
497 self.index += 1; self.data.get(self.index - 1)
499 }
500
501 #[inline]
502 fn count(self) -> usize {
503 usize::num_from(self.data.len())
504 }
505}
506
507
508#[derive(Clone, Copy, Default, Debug)]
510pub struct Stream<'a> {
511 data: &'a [u8],
512 offset: usize,
513}
514
515impl<'a> Stream<'a> {
516 #[inline]
518 pub fn new(data: &'a [u8]) -> Self {
519 Stream { data, offset: 0 }
520 }
521
522 #[inline]
526 pub fn new_at(data: &'a [u8], offset: usize) -> Option<Self> {
527 if offset <= data.len() {
528 Some(Stream { data, offset })
529 } else {
530 None
531 }
532 }
533
534 #[inline]
536 pub fn at_end(&self) -> bool {
537 self.offset >= self.data.len()
538 }
539
540 #[inline]
544 pub fn jump_to_end(&mut self) {
545 self.offset = self.data.len();
546 }
547
548 #[inline]
550 pub fn offset(&self) -> usize {
551 self.offset
552 }
553
554 #[inline]
558 pub fn tail(&self) -> Option<&'a [u8]> {
559 self.data.get(self.offset..)
560 }
561
562 #[inline]
566 pub fn skip<T: FromData>(&mut self) {
567 self.advance(T::SIZE);
568 }
569
570 #[inline]
574 pub fn advance(&mut self, len: usize) {
575 self.offset += len;
576 }
577
578 #[inline]
580 pub fn advance_checked(&mut self, len: usize) -> Option<()> {
581 if self.offset + len <= self.data.len() {
582 self.advance(len);
583 Some(())
584 } else {
585 None
586 }
587 }
588
589 #[inline]
594 pub fn read<T: FromData>(&mut self) -> Option<T> {
595 self.read_bytes(T::SIZE).and_then(T::parse)
596 }
597
598 #[inline]
600 pub fn read_at<T: FromData>(data: &[u8], offset: usize) -> Option<T> {
601 data.get(offset..offset + T::SIZE).and_then(T::parse)
602 }
603
604 #[inline]
606 pub fn read_bytes(&mut self, len: usize) -> Option<&'a [u8]> {
607 let v = self.data.get(self.offset..self.offset + len)?;
608 self.advance(len);
609 Some(v)
610 }
611
612 #[inline]
614 pub fn read_array16<T: FromData>(&mut self, count: u16) -> Option<LazyArray16<'a, T>> {
615 let len = usize::from(count) * T::SIZE;
616 self.read_bytes(len).map(LazyArray16::new)
617 }
618
619 #[inline]
621 pub fn read_array32<T: FromData>(&mut self, count: u32) -> Option<LazyArray32<'a, T>> {
622 let len = usize::num_from(count) * T::SIZE;
623 self.read_bytes(len).map(LazyArray32::new)
624 }
625}
626
627
628pub trait Offset {
630 fn to_usize(&self) -> usize;
632
633 fn is_null(&self) -> bool { self.to_usize() == 0 }
635}
636
637
638#[derive(Clone, Copy, Debug)]
640pub struct Offset16(pub u16);
641
642impl Offset for Offset16 {
643 #[inline]
644 fn to_usize(&self) -> usize {
645 usize::from(self.0)
646 }
647}
648
649impl FromData for Offset16 {
650 const SIZE: usize = 2;
651
652 #[inline]
653 fn parse(data: &[u8]) -> Option<Self> {
654 u16::parse(data).map(Offset16)
655 }
656}
657
658impl FromData for Option<Offset16> {
659 const SIZE: usize = Offset16::SIZE;
660
661 #[inline]
662 fn parse(data: &[u8]) -> Option<Self> {
663 let offset = Offset16::parse(data)?;
664 if offset.0 != 0 { Some(Some(offset)) } else { Some(None) }
665 }
666}
667
668
669#[derive(Clone, Copy, Debug)]
671pub struct Offset32(pub u32);
672
673impl Offset for Offset32 {
674 #[inline]
675 fn to_usize(&self) -> usize {
676 usize::num_from(self.0)
677 }
678}
679
680impl FromData for Offset32 {
681 const SIZE: usize = 4;
682
683 #[inline]
684 fn parse(data: &[u8]) -> Option<Self> {
685 u32::parse(data).map(Offset32)
686 }
687}
688
689
690impl FromData for Option<Offset32> {
691 const SIZE: usize = Offset32::SIZE;
692
693 #[inline]
694 fn parse(data: &[u8]) -> Option<Self> {
695 let offset = Offset32::parse(data)?;
696 if offset.0 != 0 { Some(Some(offset)) } else { Some(None) }
697 }
698}
699
700
701#[inline]
702pub(crate) fn i16_bound(min: i16, val: i16, max: i16) -> i16 {
703 use core::cmp;
704 cmp::max(min, cmp::min(max, val))
705}
706
707#[inline]
708pub(crate) fn f32_bound(min: f32, val: f32, max: f32) -> f32 {
709 debug_assert!(min.is_finite());
710 debug_assert!(val.is_finite());
711 debug_assert!(max.is_finite());
712
713 if val > max {
714 return max;
715 } else if val < min {
716 return min;
717 }
718
719 val
720}