1use crate::tag::Tag;
10use core::convert::TryInto;
11use core::ops::Range;
12
13pub trait TryFromBeBytes: Sized {
17 const SIZE: usize;
21
22 fn try_parse_from_be_bytes(data: &[u8]) -> Option<Self>;
24}
25
26pub trait FromSlice<'a>: Sized {
30 fn parse(data: &'a [u8]) -> Option<Self>;
32}
33
34impl TryFromBeBytes for () {
35 const SIZE: usize = 0;
36
37 #[inline]
38 fn try_parse_from_be_bytes(_: &[u8]) -> Option<Self> {
39 Some(())
40 }
41}
42
43impl TryFromBeBytes for u8 {
44 const SIZE: usize = 1;
45
46 #[inline]
47 fn try_parse_from_be_bytes(data: &[u8]) -> Option<Self> {
48 data.first().copied()
49 }
50}
51
52impl TryFromBeBytes for i8 {
53 const SIZE: usize = 1;
54
55 #[inline]
56 fn try_parse_from_be_bytes(data: &[u8]) -> Option<Self> {
57 data.first().copied().map(|n| n as i8)
58 }
59}
60
61impl TryFromBeBytes for u16 {
62 const SIZE: usize = 2;
63
64 #[inline]
65 fn try_parse_from_be_bytes(data: &[u8]) -> Option<Self> {
66 data.try_into().ok().map(u16::from_be_bytes)
67 }
68}
69
70impl TryFromBeBytes for i16 {
71 const SIZE: usize = 2;
72
73 #[inline]
74 fn try_parse_from_be_bytes(data: &[u8]) -> Option<Self> {
75 data.try_into().ok().map(i16::from_be_bytes)
76 }
77}
78
79impl TryFromBeBytes for u32 {
80 const SIZE: usize = 4;
81
82 #[inline]
83 fn try_parse_from_be_bytes(data: &[u8]) -> Option<Self> {
84 data.try_into().ok().map(u32::from_be_bytes)
85 }
86}
87
88impl TryFromBeBytes for i32 {
89 const SIZE: usize = 4;
90
91 #[inline]
92 fn try_parse_from_be_bytes(data: &[u8]) -> Option<Self> {
93 data.try_into().ok().map(i32::from_be_bytes)
94 }
95}
96
97impl TryFromBeBytes for u64 {
98 const SIZE: usize = 8;
99
100 #[inline]
101 fn try_parse_from_be_bytes(data: &[u8]) -> Option<Self> {
102 data.try_into().ok().map(u64::from_be_bytes)
103 }
104}
105
106impl TryFromBeBytes for i64 {
107 const SIZE: usize = 8;
108
109 #[inline]
110 fn try_parse_from_be_bytes(data: &[u8]) -> Option<Self> {
111 data.try_into().ok().map(i64::from_be_bytes)
112 }
113}
114
115impl TryFromBeBytes for Tag {
116 const SIZE: usize = 4;
117
118 #[inline]
119 fn try_parse_from_be_bytes(data: &[u8]) -> Option<Self> {
120 data.try_into().ok().map(Tag::from_be_bytes)
121 }
122}
123
124pub struct LazyArray16<'a, T> {
128 data: &'a [u8],
129 data_type: core::marker::PhantomData<T>,
130}
131
132impl<T> Clone for LazyArray16<'_, T> {
133 fn clone(&self) -> Self {
134 *self
135 }
136}
137impl<T> Copy for LazyArray16<'_, T> {}
138
139impl<T> Default for LazyArray16<'_, T> {
140 #[inline]
141 fn default() -> Self {
142 LazyArray16 {
143 data: &[],
144 data_type: core::marker::PhantomData,
145 }
146 }
147}
148
149impl<'a, T: TryFromBeBytes> LazyArray16<'a, T> {
150 #[inline]
152 pub fn new(data: &'a [u8]) -> Self {
153 LazyArray16 {
154 data,
155 data_type: core::marker::PhantomData,
156 }
157 }
158
159 pub(crate) fn bytes(&self) -> &[u8] {
160 self.data
161 }
162
163 #[inline]
165 pub fn get(&self, index: u16) -> Option<T> {
166 if index < self.len() {
167 let start = usize::from(index) * T::SIZE;
168 let end = start + T::SIZE;
169 self.data
170 .get(start..end)
171 .and_then(T::try_parse_from_be_bytes)
172 } else {
173 None
174 }
175 }
176
177 #[inline]
179 pub fn last(&self) -> Option<T> {
180 if !self.is_empty() {
181 self.get(self.len() - 1)
182 } else {
183 None
184 }
185 }
186
187 #[inline]
189 pub fn slice(&self, range: Range<u16>) -> Option<Self> {
190 let start = usize::from(range.start) * T::SIZE;
191 let end = usize::from(range.end) * T::SIZE;
192 Some(LazyArray16 {
193 data: self.data.get(start..end)?,
194 ..LazyArray16::default()
195 })
196 }
197
198 #[inline]
200 pub fn len(&self) -> u16 {
201 (self.data.len() / T::SIZE) as u16
202 }
203
204 #[inline]
206 pub fn is_empty(&self) -> bool {
207 self.len() == 0
208 }
209
210 #[inline]
212 pub fn binary_search(&self, key: &T) -> Option<(u16, T)>
213 where
214 T: Ord,
215 {
216 self.binary_search_by(|p| p.cmp(key))
217 }
218
219 #[inline]
221 pub fn binary_search_by<F>(&self, mut f: F) -> Option<(u16, T)>
222 where
223 F: FnMut(&T) -> core::cmp::Ordering,
224 {
225 use core::cmp::Ordering;
228
229 let mut size = self.len();
230 if size == 0 {
231 return None;
232 }
233
234 let mut base = 0;
235 while size > 1 {
236 let half = size / 2;
237 let mid = base + half;
238 let cmp = f(&self.get(mid)?);
242 base = if cmp == Ordering::Greater { base } else { mid };
243 size -= half;
244 }
245
246 let value = self.get(base)?;
248 if f(&value) == Ordering::Equal {
249 Some((base, value))
250 } else {
251 None
252 }
253 }
254}
255
256impl<'a, T: TryFromBeBytes + core::fmt::Debug + Copy> core::fmt::Debug for LazyArray16<'a, T> {
257 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
258 f.debug_list().entries(*self).finish()
259 }
260}
261
262impl<'a, T: TryFromBeBytes> IntoIterator for LazyArray16<'a, T> {
263 type Item = T;
264 type IntoIter = LazyArrayIter16<'a, T>;
265
266 #[inline]
267 fn into_iter(self) -> Self::IntoIter {
268 LazyArrayIter16 {
269 data: self,
270 index: 0,
271 }
272 }
273}
274
275#[derive(Clone, Copy)]
277#[allow(missing_debug_implementations)]
278pub struct LazyArrayIter16<'a, T> {
279 data: LazyArray16<'a, T>,
280 index: u16,
281}
282
283impl<T: TryFromBeBytes> Default for LazyArrayIter16<'_, T> {
284 #[inline]
285 fn default() -> Self {
286 LazyArrayIter16 {
287 data: LazyArray16::new(&[]),
288 index: 0,
289 }
290 }
291}
292
293impl<'a, T: TryFromBeBytes> Iterator for LazyArrayIter16<'a, T> {
294 type Item = T;
295
296 #[inline]
297 fn next(&mut self) -> Option<Self::Item> {
298 self.index += 1; self.data.get(self.index - 1)
300 }
301
302 #[inline]
303 fn count(self) -> usize {
304 usize::from(self.data.len().saturating_sub(self.index))
305 }
306}
307
308#[derive(Clone, Copy)]
312pub struct LazyArray32<'a, T> {
313 data: &'a [u8],
314 data_type: core::marker::PhantomData<T>,
315}
316
317impl<T> Default for LazyArray32<'_, T> {
318 #[inline]
319 fn default() -> Self {
320 LazyArray32 {
321 data: &[],
322 data_type: core::marker::PhantomData,
323 }
324 }
325}
326
327impl<'a, T: TryFromBeBytes> LazyArray32<'a, T> {
328 #[inline]
330 pub fn new(data: &'a [u8]) -> Self {
331 LazyArray32 {
332 data,
333 data_type: core::marker::PhantomData,
334 }
335 }
336
337 #[inline]
339 pub fn get(&self, index: u32) -> Option<T> {
340 if index < self.len() {
341 let start = (index as usize) * T::SIZE;
342 let end = start + T::SIZE;
343 self.data
344 .get(start..end)
345 .and_then(T::try_parse_from_be_bytes)
346 } else {
347 None
348 }
349 }
350
351 #[inline]
353 pub fn len(&self) -> u32 {
354 (self.data.len() / T::SIZE) as u32
355 }
356
357 pub fn is_empty(&self) -> bool {
359 self.len() == 0
360 }
361
362 #[inline]
364 pub fn binary_search(&self, key: &T) -> Option<(u32, T)>
365 where
366 T: Ord,
367 {
368 self.binary_search_by(|p| p.cmp(key))
369 }
370
371 #[inline]
373 pub fn binary_search_by<F>(&self, mut f: F) -> Option<(u32, T)>
374 where
375 F: FnMut(&T) -> core::cmp::Ordering,
376 {
377 use core::cmp::Ordering;
380
381 let mut size = self.len();
382 if size == 0 {
383 return None;
384 }
385
386 let mut base = 0;
387 while size > 1 {
388 let half = size / 2;
389 let mid = base + half;
390 let cmp = f(&self.get(mid)?);
394 base = if cmp == Ordering::Greater { base } else { mid };
395 size -= half;
396 }
397
398 let value = self.get(base)?;
400 if f(&value) == Ordering::Equal {
401 Some((base, value))
402 } else {
403 None
404 }
405 }
406}
407
408impl<'a, T: TryFromBeBytes + core::fmt::Debug + Copy> core::fmt::Debug for LazyArray32<'a, T> {
409 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
410 f.debug_list().entries(*self).finish()
411 }
412}
413
414impl<'a, T: TryFromBeBytes> IntoIterator for LazyArray32<'a, T> {
415 type Item = T;
416 type IntoIter = LazyArrayIter32<'a, T>;
417
418 #[inline]
419 fn into_iter(self) -> Self::IntoIter {
420 LazyArrayIter32 {
421 data: self,
422 index: 0,
423 }
424 }
425}
426
427#[derive(Clone, Copy)]
429#[allow(missing_debug_implementations)]
430pub struct LazyArrayIter32<'a, T> {
431 data: LazyArray32<'a, T>,
432 index: u32,
433}
434
435impl<'a, T: TryFromBeBytes> Iterator for LazyArrayIter32<'a, T> {
436 type Item = T;
437
438 #[inline]
439 fn next(&mut self) -> Option<Self::Item> {
440 self.index += 1; self.data.get(self.index - 1)
442 }
443
444 #[inline]
445 fn count(self) -> usize {
446 self.data.len().saturating_sub(self.index) as usize
447 }
448}
449
450#[derive(Clone, Copy)]
456pub struct LazyOffsetArray16<'a, T: FromSlice<'a>> {
457 data: &'a [u8],
458 offsets: LazyArray16<'a, u16>,
460 data_type: core::marker::PhantomData<T>,
461}
462
463impl<'a, T: FromSlice<'a>> LazyOffsetArray16<'a, T> {
464 #[allow(dead_code)]
466 pub fn new(data: &'a [u8], offsets: LazyArray16<'a, u16>) -> Self {
467 Self {
468 data,
469 offsets,
470 data_type: core::marker::PhantomData,
471 }
472 }
473
474 #[allow(dead_code)]
476 pub fn parse(data: &'a [u8]) -> Option<Self> {
477 let mut s = Stream::new(data);
478 let count = s.read::<u16>()?;
479 let offsets = s.read_array16(count)?;
480 Some(Self {
481 data,
482 offsets,
483 data_type: core::marker::PhantomData,
484 })
485 }
486
487 #[inline]
489 pub fn get(&self, index: u16) -> Option<T> {
490 let offset = usize::from(self.offsets.get(index).filter(|offset| *offset != 0)?);
491 self.data.get(offset..).and_then(T::parse)
492 }
493
494 #[inline]
496 pub fn len(&self) -> u16 {
497 self.offsets.len()
498 }
499
500 #[inline]
502 #[allow(dead_code)]
503 pub fn is_empty(&self) -> bool {
504 self.len() == 0
505 }
506}
507
508impl<'a, T: FromSlice<'a> + core::fmt::Debug + Copy> core::fmt::Debug for LazyOffsetArray16<'a, T> {
509 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
510 f.debug_list().entries(*self).finish()
511 }
512}
513
514#[derive(Clone, Copy)]
516#[allow(missing_debug_implementations)]
517pub struct LazyOffsetArrayIter16<'a, T: FromSlice<'a>> {
518 array: LazyOffsetArray16<'a, T>,
519 index: u16,
520}
521
522impl<'a, T: FromSlice<'a>> IntoIterator for LazyOffsetArray16<'a, T> {
523 type Item = T;
524 type IntoIter = LazyOffsetArrayIter16<'a, T>;
525
526 #[inline]
527 fn into_iter(self) -> Self::IntoIter {
528 LazyOffsetArrayIter16 {
529 array: self,
530 index: 0,
531 }
532 }
533}
534
535impl<'a, T: FromSlice<'a>> Iterator for LazyOffsetArrayIter16<'a, T> {
536 type Item = T;
537
538 fn next(&mut self) -> Option<Self::Item> {
539 if self.index < self.array.len() {
540 self.index += 1;
541 self.array.get(self.index - 1)
542 } else {
543 None
544 }
545 }
546
547 #[inline]
548 fn count(self) -> usize {
549 usize::from(self.array.len().saturating_sub(self.index))
550 }
551}
552
553#[derive(Clone, Default, Debug)]
555pub struct Stream<'a> {
556 data: &'a [u8],
557 offset: usize,
558}
559
560impl<'a> Stream<'a> {
561 #[inline]
563 pub fn new(data: &'a [u8]) -> Self {
564 Stream { data, offset: 0 }
565 }
566
567 #[inline]
571 pub fn new_at(data: &'a [u8], offset: usize) -> Option<Self> {
572 if offset <= data.len() {
573 Some(Stream { data, offset })
574 } else {
575 None
576 }
577 }
578
579 #[inline]
581 pub fn at_end(&self) -> bool {
582 self.offset >= self.data.len()
583 }
584
585 #[inline]
589 pub fn jump_to_end(&mut self) {
590 self.offset = self.data.len();
591 }
592
593 #[inline]
595 pub fn offset(&self) -> usize {
596 self.offset
597 }
598
599 #[inline]
603 pub fn tail(&self) -> Option<&'a [u8]> {
604 self.data.get(self.offset..)
605 }
606
607 #[inline]
611 pub fn skip<T: TryFromBeBytes>(&mut self) {
612 self.advance(T::SIZE);
613 }
614
615 #[inline]
619 pub fn advance(&mut self, len: usize) {
620 self.offset += len;
621 }
622
623 #[inline]
625 pub fn advance_checked(&mut self, len: usize) -> Option<()> {
626 if self.offset + len <= self.data.len() {
627 self.advance(len);
628 Some(())
629 } else {
630 None
631 }
632 }
633
634 #[inline]
639 pub fn read<T: TryFromBeBytes>(&mut self) -> Option<T> {
640 self.read_bytes(T::SIZE)
641 .and_then(T::try_parse_from_be_bytes)
642 }
643
644 #[inline]
646 pub fn read_at<T: TryFromBeBytes>(data: &[u8], offset: usize) -> Option<T> {
647 data.get(offset..offset + T::SIZE)
648 .and_then(T::try_parse_from_be_bytes)
649 }
650
651 #[inline]
653 pub fn read_bytes(&mut self, len: usize) -> Option<&'a [u8]> {
654 debug_assert!(self.offset as u64 + len as u64 <= u32::MAX as u64);
658
659 let v = self.data.get(self.offset..self.offset + len)?;
660 self.advance(len);
661 Some(v)
662 }
663
664 #[inline]
666 pub fn read_array16<T: TryFromBeBytes>(&mut self, count: u16) -> Option<LazyArray16<'a, T>> {
667 let len = usize::from(count) * T::SIZE;
668 self.read_bytes(len).map(LazyArray16::new)
669 }
670
671 #[inline]
673 pub fn read_array32<T: TryFromBeBytes>(&mut self, count: u32) -> Option<LazyArray32<'a, T>> {
674 let len = count as usize * T::SIZE;
675 self.read_bytes(len).map(LazyArray32::new)
676 }
677
678 #[allow(dead_code)]
679 #[inline]
680 pub fn read_at_offset16(&mut self, data: &'a [u8]) -> Option<&'a [u8]> {
681 let offset = usize::from(self.read::<u16>()?);
682 data.get(offset..)
683 }
684}
685
686#[inline]
687pub fn i16_bound(min: i16, val: i16, max: i16) -> i16 {
688 use core::cmp;
689 cmp::max(min, cmp::min(max, val))
690}
691
692#[inline]
693pub fn f32_bound(min: f32, val: f32, max: f32) -> f32 {
694 debug_assert!(min.is_finite());
695 debug_assert!(val.is_finite());
696 debug_assert!(max.is_finite());
697
698 if val > max {
699 return max;
700 } else if val < min {
701 return min;
702 }
703
704 val
705}
706
707pub fn round4(value: usize) -> usize {
708 match value.checked_add(3) {
709 Some(value_plus_3) => value_plus_3 & !3,
710 None => value,
711 }
712}