1 | //! Binary parsing utils. |
2 | //! |
3 | //! This module should not be used directly, unless you're planning to parse |
4 | //! some tables manually. |
5 | |
6 | use core::convert::{TryFrom, TryInto}; |
7 | use core::ops::Range; |
8 | |
9 | /// A trait for parsing raw binary data of fixed size. |
10 | /// |
11 | /// This is a low-level, internal trait that should not be used directly. |
12 | pub trait FromData: Sized { |
13 | /// Object's raw data size. |
14 | /// |
15 | /// Not always the same as `mem::size_of`. |
16 | const SIZE: usize; |
17 | |
18 | /// Parses an object from a raw data. |
19 | fn parse(data: &[u8]) -> Option<Self>; |
20 | } |
21 | |
22 | /// A trait for parsing raw binary data of variable size. |
23 | /// |
24 | /// This is a low-level, internal trait that should not be used directly. |
25 | pub trait FromSlice<'a>: Sized { |
26 | /// Parses an object from a raw data. |
27 | fn parse(data: &'a [u8]) -> Option<Self>; |
28 | } |
29 | |
30 | impl FromData for () { |
31 | const SIZE: usize = 0; |
32 | |
33 | #[inline ] |
34 | fn parse(_: &[u8]) -> Option<Self> { |
35 | Some(()) |
36 | } |
37 | } |
38 | |
39 | impl FromData for u8 { |
40 | const SIZE: usize = 1; |
41 | |
42 | #[inline ] |
43 | fn parse(data: &[u8]) -> Option<Self> { |
44 | data.get(index:0).copied() |
45 | } |
46 | } |
47 | |
48 | impl FromData for i8 { |
49 | const SIZE: usize = 1; |
50 | |
51 | #[inline ] |
52 | fn parse(data: &[u8]) -> Option<Self> { |
53 | data.get(index:0).copied().map(|n: u8| n as i8) |
54 | } |
55 | } |
56 | |
57 | impl FromData for u16 { |
58 | const SIZE: usize = 2; |
59 | |
60 | #[inline ] |
61 | fn parse(data: &[u8]) -> Option<Self> { |
62 | data.try_into().ok().map(u16::from_be_bytes) |
63 | } |
64 | } |
65 | |
66 | impl FromData for i16 { |
67 | const SIZE: usize = 2; |
68 | |
69 | #[inline ] |
70 | fn parse(data: &[u8]) -> Option<Self> { |
71 | data.try_into().ok().map(i16::from_be_bytes) |
72 | } |
73 | } |
74 | |
75 | impl FromData for u32 { |
76 | const SIZE: usize = 4; |
77 | |
78 | #[inline ] |
79 | fn parse(data: &[u8]) -> Option<Self> { |
80 | data.try_into().ok().map(u32::from_be_bytes) |
81 | } |
82 | } |
83 | |
84 | impl FromData for i32 { |
85 | const SIZE: usize = 4; |
86 | |
87 | #[inline ] |
88 | fn parse(data: &[u8]) -> Option<Self> { |
89 | data.try_into().ok().map(i32::from_be_bytes) |
90 | } |
91 | } |
92 | |
93 | impl FromData for u64 { |
94 | const SIZE: usize = 8; |
95 | |
96 | #[inline ] |
97 | fn parse(data: &[u8]) -> Option<Self> { |
98 | data.try_into().ok().map(u64::from_be_bytes) |
99 | } |
100 | } |
101 | |
102 | /// A u24 number. |
103 | /// |
104 | /// Stored as u32, but encoded as 3 bytes in the font. |
105 | /// |
106 | /// <https://docs.microsoft.com/en-us/typography/opentype/spec/otff#data-types> |
107 | #[derive (Clone, Copy, Debug)] |
108 | pub struct U24(pub u32); |
109 | |
110 | impl FromData for U24 { |
111 | const SIZE: usize = 3; |
112 | |
113 | #[inline ] |
114 | fn parse(data: &[u8]) -> Option<Self> { |
115 | let data: [u8; 3] = data.try_into().ok()?; |
116 | Some(U24(u32::from_be_bytes([0, data[0], data[1], data[2]]))) |
117 | } |
118 | } |
119 | |
120 | /// A 16-bit signed fixed number with the low 14 bits of fraction (2.14). |
121 | #[derive (Clone, Copy, Debug)] |
122 | pub struct F2DOT14(pub i16); |
123 | |
124 | impl F2DOT14 { |
125 | /// Converts i16 to f32. |
126 | #[inline ] |
127 | pub fn to_f32(self) -> f32 { |
128 | f32::from(self.0) / 16384.0 |
129 | } |
130 | |
131 | #[cfg (feature = "variable-fonts" )] |
132 | #[inline ] |
133 | pub fn apply_float_delta(&self, delta: f32) -> f32 { |
134 | self.to_f32() + (delta as f64 * (1.0 / 16384.0)) as f32 |
135 | } |
136 | } |
137 | |
138 | impl FromData for F2DOT14 { |
139 | const SIZE: usize = 2; |
140 | |
141 | #[inline ] |
142 | fn parse(data: &[u8]) -> Option<Self> { |
143 | i16::parse(data).map(F2DOT14) |
144 | } |
145 | } |
146 | |
147 | /// A 32-bit signed fixed-point number (16.16). |
148 | #[derive (Clone, Copy, Debug)] |
149 | pub struct Fixed(pub f32); |
150 | |
151 | impl FromData for Fixed { |
152 | const SIZE: usize = 4; |
153 | |
154 | #[inline ] |
155 | fn parse(data: &[u8]) -> Option<Self> { |
156 | // TODO: is it safe to cast? |
157 | i32::parse(data).map(|n: i32| Fixed(n as f32 / 65536.0)) |
158 | } |
159 | } |
160 | |
161 | impl Fixed { |
162 | #[cfg (feature = "variable-fonts" )] |
163 | #[inline ] |
164 | pub(crate) fn apply_float_delta(&self, delta: f32) -> f32 { |
165 | self.0 + (delta as f64 * (1.0 / 65536.0)) as f32 |
166 | } |
167 | } |
168 | |
169 | /// A safe u32 to usize casting. |
170 | /// |
171 | /// Rust doesn't implement `From<u32> for usize`, |
172 | /// because it has to support 16 bit targets. |
173 | /// We don't, so we can allow this. |
174 | pub trait NumFrom<T>: Sized { |
175 | /// Converts u32 into usize. |
176 | fn num_from(_: T) -> Self; |
177 | } |
178 | |
179 | impl NumFrom<u32> for usize { |
180 | #[inline ] |
181 | fn num_from(v: u32) -> Self { |
182 | #[cfg (any(target_pointer_width = "32" , target_pointer_width = "64" ))] |
183 | { |
184 | v as usize |
185 | } |
186 | |
187 | // compilation error on 16 bit targets |
188 | } |
189 | } |
190 | |
191 | impl NumFrom<char> for usize { |
192 | #[inline ] |
193 | fn num_from(v: char) -> Self { |
194 | #[cfg (any(target_pointer_width = "32" , target_pointer_width = "64" ))] |
195 | { |
196 | v as usize |
197 | } |
198 | |
199 | // compilation error on 16 bit targets |
200 | } |
201 | } |
202 | |
203 | /// Just like TryFrom<N>, but for numeric types not supported by the Rust's std. |
204 | pub trait TryNumFrom<T>: Sized { |
205 | /// Casts between numeric types. |
206 | fn try_num_from(_: T) -> Option<Self>; |
207 | } |
208 | |
209 | impl TryNumFrom<f32> for u8 { |
210 | #[inline ] |
211 | fn try_num_from(v: f32) -> Option<Self> { |
212 | i32::try_num_from(v).and_then(|v: i32| u8::try_from(v).ok()) |
213 | } |
214 | } |
215 | |
216 | impl TryNumFrom<f32> for i16 { |
217 | #[inline ] |
218 | fn try_num_from(v: f32) -> Option<Self> { |
219 | i32::try_num_from(v).and_then(|v: i32| i16::try_from(v).ok()) |
220 | } |
221 | } |
222 | |
223 | impl TryNumFrom<f32> for u16 { |
224 | #[inline ] |
225 | fn try_num_from(v: f32) -> Option<Self> { |
226 | i32::try_num_from(v).and_then(|v: i32| u16::try_from(v).ok()) |
227 | } |
228 | } |
229 | |
230 | #[allow (clippy::manual_range_contains)] |
231 | impl TryNumFrom<f32> for i32 { |
232 | #[inline ] |
233 | fn try_num_from(v: f32) -> Option<Self> { |
234 | // Based on https://github.com/rust-num/num-traits/blob/master/src/cast.rs |
235 | |
236 | // Float as int truncates toward zero, so we want to allow values |
237 | // in the exclusive range `(MIN-1, MAX+1)`. |
238 | |
239 | // We can't represent `MIN-1` exactly, but there's no fractional part |
240 | // at this magnitude, so we can just use a `MIN` inclusive boundary. |
241 | const MIN: f32 = i32::MIN as f32; |
242 | // We can't represent `MAX` exactly, but it will round up to exactly |
243 | // `MAX+1` (a power of two) when we cast it. |
244 | const MAX_P1: f32 = i32::MAX as f32; |
245 | if v >= MIN && v < MAX_P1 { |
246 | Some(v as i32) |
247 | } else { |
248 | None |
249 | } |
250 | } |
251 | } |
252 | |
253 | /// A slice-like container that converts internal binary data only on access. |
254 | /// |
255 | /// Array values are stored in a continuous data chunk. |
256 | #[derive (Clone, Copy)] |
257 | pub struct LazyArray16<'a, T> { |
258 | data: &'a [u8], |
259 | data_type: core::marker::PhantomData<T>, |
260 | } |
261 | |
262 | impl<T> Default for LazyArray16<'_, T> { |
263 | #[inline ] |
264 | fn default() -> Self { |
265 | LazyArray16 { |
266 | data: &[], |
267 | data_type: core::marker::PhantomData, |
268 | } |
269 | } |
270 | } |
271 | |
272 | impl<'a, T: FromData> LazyArray16<'a, T> { |
273 | /// Creates a new `LazyArray`. |
274 | #[inline ] |
275 | pub fn new(data: &'a [u8]) -> Self { |
276 | LazyArray16 { |
277 | data, |
278 | data_type: core::marker::PhantomData, |
279 | } |
280 | } |
281 | |
282 | /// Returns a value at `index`. |
283 | #[inline ] |
284 | pub fn get(&self, index: u16) -> Option<T> { |
285 | if index < self.len() { |
286 | let start = usize::from(index) * T::SIZE; |
287 | let end = start + T::SIZE; |
288 | self.data.get(start..end).and_then(T::parse) |
289 | } else { |
290 | None |
291 | } |
292 | } |
293 | |
294 | /// Returns the last value. |
295 | #[inline ] |
296 | pub fn last(&self) -> Option<T> { |
297 | if !self.is_empty() { |
298 | self.get(self.len() - 1) |
299 | } else { |
300 | None |
301 | } |
302 | } |
303 | |
304 | /// Returns sub-array. |
305 | #[inline ] |
306 | pub fn slice(&self, range: Range<u16>) -> Option<Self> { |
307 | let start = usize::from(range.start) * T::SIZE; |
308 | let end = usize::from(range.end) * T::SIZE; |
309 | Some(LazyArray16 { |
310 | data: self.data.get(start..end)?, |
311 | ..LazyArray16::default() |
312 | }) |
313 | } |
314 | |
315 | /// Returns array's length. |
316 | #[inline ] |
317 | pub fn len(&self) -> u16 { |
318 | (self.data.len() / T::SIZE) as u16 |
319 | } |
320 | |
321 | /// Checks if array is empty. |
322 | #[inline ] |
323 | pub fn is_empty(&self) -> bool { |
324 | self.len() == 0 |
325 | } |
326 | |
327 | /// Performs a binary search by specified `key`. |
328 | #[inline ] |
329 | pub fn binary_search(&self, key: &T) -> Option<(u16, T)> |
330 | where |
331 | T: Ord, |
332 | { |
333 | self.binary_search_by(|p| p.cmp(key)) |
334 | } |
335 | |
336 | /// Performs a binary search using specified closure. |
337 | #[inline ] |
338 | pub fn binary_search_by<F>(&self, mut f: F) -> Option<(u16, T)> |
339 | where |
340 | F: FnMut(&T) -> core::cmp::Ordering, |
341 | { |
342 | // Based on Rust std implementation. |
343 | |
344 | use core::cmp::Ordering; |
345 | |
346 | let mut size = self.len(); |
347 | if size == 0 { |
348 | return None; |
349 | } |
350 | |
351 | let mut base = 0; |
352 | while size > 1 { |
353 | let half = size / 2; |
354 | let mid = base + half; |
355 | // mid is always in [0, size), that means mid is >= 0 and < size. |
356 | // mid >= 0: by definition |
357 | // mid < size: mid = size / 2 + size / 4 + size / 8 ... |
358 | let cmp = f(&self.get(mid)?); |
359 | base = if cmp == Ordering::Greater { base } else { mid }; |
360 | size -= half; |
361 | } |
362 | |
363 | // base is always in [0, size) because base <= mid. |
364 | let value = self.get(base)?; |
365 | if f(&value) == Ordering::Equal { |
366 | Some((base, value)) |
367 | } else { |
368 | None |
369 | } |
370 | } |
371 | } |
372 | |
373 | impl<'a, T: FromData + core::fmt::Debug + Copy> core::fmt::Debug for LazyArray16<'a, T> { |
374 | fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { |
375 | f.debug_list().entries(*self).finish() |
376 | } |
377 | } |
378 | |
379 | impl<'a, T: FromData> IntoIterator for LazyArray16<'a, T> { |
380 | type Item = T; |
381 | type IntoIter = LazyArrayIter16<'a, T>; |
382 | |
383 | #[inline ] |
384 | fn into_iter(self) -> Self::IntoIter { |
385 | LazyArrayIter16 { |
386 | data: self, |
387 | index: 0, |
388 | } |
389 | } |
390 | } |
391 | |
392 | /// An iterator over `LazyArray16`. |
393 | #[derive (Clone, Copy)] |
394 | #[allow (missing_debug_implementations)] |
395 | pub struct LazyArrayIter16<'a, T> { |
396 | data: LazyArray16<'a, T>, |
397 | index: u16, |
398 | } |
399 | |
400 | impl<T: FromData> Default for LazyArrayIter16<'_, T> { |
401 | #[inline ] |
402 | fn default() -> Self { |
403 | LazyArrayIter16 { |
404 | data: LazyArray16::new(&[]), |
405 | index: 0, |
406 | } |
407 | } |
408 | } |
409 | |
410 | impl<'a, T: FromData> Iterator for LazyArrayIter16<'a, T> { |
411 | type Item = T; |
412 | |
413 | #[inline ] |
414 | fn next(&mut self) -> Option<Self::Item> { |
415 | self.index += 1; // TODO: check |
416 | self.data.get(self.index - 1) |
417 | } |
418 | |
419 | #[inline ] |
420 | fn count(self) -> usize { |
421 | usize::from(self.data.len().saturating_sub(self.index)) |
422 | } |
423 | } |
424 | |
425 | /// A slice-like container that converts internal binary data only on access. |
426 | /// |
427 | /// This is a low-level, internal structure that should not be used directly. |
428 | #[derive (Clone, Copy)] |
429 | pub struct LazyArray32<'a, T> { |
430 | data: &'a [u8], |
431 | data_type: core::marker::PhantomData<T>, |
432 | } |
433 | |
434 | impl<T> Default for LazyArray32<'_, T> { |
435 | #[inline ] |
436 | fn default() -> Self { |
437 | LazyArray32 { |
438 | data: &[], |
439 | data_type: core::marker::PhantomData, |
440 | } |
441 | } |
442 | } |
443 | |
444 | impl<'a, T: FromData> LazyArray32<'a, T> { |
445 | /// Creates a new `LazyArray`. |
446 | #[inline ] |
447 | pub fn new(data: &'a [u8]) -> Self { |
448 | LazyArray32 { |
449 | data, |
450 | data_type: core::marker::PhantomData, |
451 | } |
452 | } |
453 | |
454 | /// Returns a value at `index`. |
455 | #[inline ] |
456 | pub fn get(&self, index: u32) -> Option<T> { |
457 | if index < self.len() { |
458 | let start = usize::num_from(index) * T::SIZE; |
459 | let end = start + T::SIZE; |
460 | self.data.get(start..end).and_then(T::parse) |
461 | } else { |
462 | None |
463 | } |
464 | } |
465 | |
466 | /// Returns array's length. |
467 | #[inline ] |
468 | pub fn len(&self) -> u32 { |
469 | (self.data.len() / T::SIZE) as u32 |
470 | } |
471 | |
472 | /// Checks if the array is empty. |
473 | pub fn is_empty(&self) -> bool { |
474 | self.len() == 0 |
475 | } |
476 | |
477 | /// Performs a binary search by specified `key`. |
478 | #[inline ] |
479 | pub fn binary_search(&self, key: &T) -> Option<(u32, T)> |
480 | where |
481 | T: Ord, |
482 | { |
483 | self.binary_search_by(|p| p.cmp(key)) |
484 | } |
485 | |
486 | /// Performs a binary search using specified closure. |
487 | #[inline ] |
488 | pub fn binary_search_by<F>(&self, mut f: F) -> Option<(u32, T)> |
489 | where |
490 | F: FnMut(&T) -> core::cmp::Ordering, |
491 | { |
492 | // Based on Rust std implementation. |
493 | |
494 | use core::cmp::Ordering; |
495 | |
496 | let mut size = self.len(); |
497 | if size == 0 { |
498 | return None; |
499 | } |
500 | |
501 | let mut base = 0; |
502 | while size > 1 { |
503 | let half = size / 2; |
504 | let mid = base + half; |
505 | // mid is always in [0, size), that means mid is >= 0 and < size. |
506 | // mid >= 0: by definition |
507 | // mid < size: mid = size / 2 + size / 4 + size / 8 ... |
508 | let cmp = f(&self.get(mid)?); |
509 | base = if cmp == Ordering::Greater { base } else { mid }; |
510 | size -= half; |
511 | } |
512 | |
513 | // base is always in [0, size) because base <= mid. |
514 | let value = self.get(base)?; |
515 | if f(&value) == Ordering::Equal { |
516 | Some((base, value)) |
517 | } else { |
518 | None |
519 | } |
520 | } |
521 | } |
522 | |
523 | impl<'a, T: FromData + core::fmt::Debug + Copy> core::fmt::Debug for LazyArray32<'a, T> { |
524 | fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { |
525 | f.debug_list().entries(*self).finish() |
526 | } |
527 | } |
528 | |
529 | impl<'a, T: FromData> IntoIterator for LazyArray32<'a, T> { |
530 | type Item = T; |
531 | type IntoIter = LazyArrayIter32<'a, T>; |
532 | |
533 | #[inline ] |
534 | fn into_iter(self) -> Self::IntoIter { |
535 | LazyArrayIter32 { |
536 | data: self, |
537 | index: 0, |
538 | } |
539 | } |
540 | } |
541 | |
542 | /// An iterator over `LazyArray32`. |
543 | #[derive (Clone, Copy)] |
544 | #[allow (missing_debug_implementations)] |
545 | pub struct LazyArrayIter32<'a, T> { |
546 | data: LazyArray32<'a, T>, |
547 | index: u32, |
548 | } |
549 | |
550 | impl<'a, T: FromData> Iterator for LazyArrayIter32<'a, T> { |
551 | type Item = T; |
552 | |
553 | #[inline ] |
554 | fn next(&mut self) -> Option<Self::Item> { |
555 | self.index += 1; // TODO: check |
556 | self.data.get(self.index - 1) |
557 | } |
558 | |
559 | #[inline ] |
560 | fn count(self) -> usize { |
561 | usize::num_from(self.data.len().saturating_sub(self.index)) |
562 | } |
563 | } |
564 | |
565 | /// A [`LazyArray16`]-like container, but data is accessed by offsets. |
566 | /// |
567 | /// Unlike [`LazyArray16`], internal storage is not continuous. |
568 | /// |
569 | /// Multiple offsets can point to the same data. |
570 | #[derive (Clone, Copy)] |
571 | pub struct LazyOffsetArray16<'a, T: FromSlice<'a>> { |
572 | data: &'a [u8], |
573 | // Zero offsets must be ignored, therefore we're using `Option<Offset16>`. |
574 | offsets: LazyArray16<'a, Option<Offset16>>, |
575 | data_type: core::marker::PhantomData<T>, |
576 | } |
577 | |
578 | impl<'a, T: FromSlice<'a>> LazyOffsetArray16<'a, T> { |
579 | /// Creates a new `LazyOffsetArray16`. |
580 | #[allow (dead_code)] |
581 | pub fn new(data: &'a [u8], offsets: LazyArray16<'a, Option<Offset16>>) -> Self { |
582 | Self { |
583 | data, |
584 | offsets, |
585 | data_type: core::marker::PhantomData, |
586 | } |
587 | } |
588 | |
589 | /// Parses `LazyOffsetArray16` from raw data. |
590 | #[allow (dead_code)] |
591 | pub fn parse(data: &'a [u8]) -> Option<Self> { |
592 | let mut s = Stream::new(data); |
593 | let count = s.read::<u16>()?; |
594 | let offsets = s.read_array16(count)?; |
595 | Some(Self { |
596 | data, |
597 | offsets, |
598 | data_type: core::marker::PhantomData, |
599 | }) |
600 | } |
601 | |
602 | /// Returns a value at `index`. |
603 | #[inline ] |
604 | pub fn get(&self, index: u16) -> Option<T> { |
605 | let offset = self.offsets.get(index)??.to_usize(); |
606 | self.data.get(offset..).and_then(T::parse) |
607 | } |
608 | |
609 | /// Returns array's length. |
610 | #[inline ] |
611 | pub fn len(&self) -> u16 { |
612 | self.offsets.len() |
613 | } |
614 | |
615 | /// Checks if array is empty. |
616 | #[inline ] |
617 | #[allow (dead_code)] |
618 | pub fn is_empty(&self) -> bool { |
619 | self.len() == 0 |
620 | } |
621 | } |
622 | |
623 | impl<'a, T: FromSlice<'a> + core::fmt::Debug + Copy> core::fmt::Debug for LazyOffsetArray16<'a, T> { |
624 | fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { |
625 | f.debug_list().entries(*self).finish() |
626 | } |
627 | } |
628 | |
629 | /// An iterator over [`LazyOffsetArray16`] values. |
630 | #[derive (Clone, Copy)] |
631 | #[allow (missing_debug_implementations)] |
632 | pub struct LazyOffsetArrayIter16<'a, T: FromSlice<'a>> { |
633 | array: LazyOffsetArray16<'a, T>, |
634 | index: u16, |
635 | } |
636 | |
637 | impl<'a, T: FromSlice<'a>> IntoIterator for LazyOffsetArray16<'a, T> { |
638 | type Item = T; |
639 | type IntoIter = LazyOffsetArrayIter16<'a, T>; |
640 | |
641 | #[inline ] |
642 | fn into_iter(self) -> Self::IntoIter { |
643 | LazyOffsetArrayIter16 { |
644 | array: self, |
645 | index: 0, |
646 | } |
647 | } |
648 | } |
649 | |
650 | impl<'a, T: FromSlice<'a>> Iterator for LazyOffsetArrayIter16<'a, T> { |
651 | type Item = T; |
652 | |
653 | fn next(&mut self) -> Option<Self::Item> { |
654 | if self.index < self.array.len() { |
655 | self.index += 1; |
656 | self.array.get(self.index - 1) |
657 | } else { |
658 | None |
659 | } |
660 | } |
661 | |
662 | #[inline ] |
663 | fn count(self) -> usize { |
664 | usize::from(self.array.len().saturating_sub(self.index)) |
665 | } |
666 | } |
667 | |
668 | /// A streaming binary parser. |
669 | #[derive (Clone, Default, Debug)] |
670 | pub struct Stream<'a> { |
671 | data: &'a [u8], |
672 | offset: usize, |
673 | } |
674 | |
675 | impl<'a> Stream<'a> { |
676 | /// Creates a new `Stream` parser. |
677 | #[inline ] |
678 | pub fn new(data: &'a [u8]) -> Self { |
679 | Stream { data, offset: 0 } |
680 | } |
681 | |
682 | /// Creates a new `Stream` parser at offset. |
683 | /// |
684 | /// Returns `None` when `offset` is out of bounds. |
685 | #[inline ] |
686 | pub fn new_at(data: &'a [u8], offset: usize) -> Option<Self> { |
687 | if offset <= data.len() { |
688 | Some(Stream { data, offset }) |
689 | } else { |
690 | None |
691 | } |
692 | } |
693 | |
694 | /// Checks that stream reached the end of the data. |
695 | #[inline ] |
696 | pub fn at_end(&self) -> bool { |
697 | self.offset >= self.data.len() |
698 | } |
699 | |
700 | /// Jumps to the end of the stream. |
701 | /// |
702 | /// Useful to indicate that we parsed all the data. |
703 | #[inline ] |
704 | pub fn jump_to_end(&mut self) { |
705 | self.offset = self.data.len(); |
706 | } |
707 | |
708 | /// Returns the current offset. |
709 | #[inline ] |
710 | pub fn offset(&self) -> usize { |
711 | self.offset |
712 | } |
713 | |
714 | /// Returns the trailing data. |
715 | /// |
716 | /// Returns `None` when `Stream` is reached the end. |
717 | #[inline ] |
718 | pub fn tail(&self) -> Option<&'a [u8]> { |
719 | self.data.get(self.offset..) |
720 | } |
721 | |
722 | /// Advances by `FromData::SIZE`. |
723 | /// |
724 | /// Doesn't check bounds. |
725 | #[inline ] |
726 | pub fn skip<T: FromData>(&mut self) { |
727 | self.advance(T::SIZE); |
728 | } |
729 | |
730 | /// Advances by the specified `len`. |
731 | /// |
732 | /// Doesn't check bounds. |
733 | #[inline ] |
734 | pub fn advance(&mut self, len: usize) { |
735 | self.offset += len; |
736 | } |
737 | |
738 | /// Advances by the specified `len` and checks for bounds. |
739 | #[inline ] |
740 | pub fn advance_checked(&mut self, len: usize) -> Option<()> { |
741 | if self.offset + len <= self.data.len() { |
742 | self.advance(len); |
743 | Some(()) |
744 | } else { |
745 | None |
746 | } |
747 | } |
748 | |
749 | /// Parses the type from the steam. |
750 | /// |
751 | /// Returns `None` when there is not enough data left in the stream |
752 | /// or the type parsing failed. |
753 | #[inline ] |
754 | pub fn read<T: FromData>(&mut self) -> Option<T> { |
755 | self.read_bytes(T::SIZE).and_then(T::parse) |
756 | } |
757 | |
758 | /// Parses the type from the steam at offset. |
759 | #[inline ] |
760 | pub fn read_at<T: FromData>(data: &[u8], offset: usize) -> Option<T> { |
761 | data.get(offset..offset + T::SIZE).and_then(T::parse) |
762 | } |
763 | |
764 | /// Reads N bytes from the stream. |
765 | #[inline ] |
766 | pub fn read_bytes(&mut self, len: usize) -> Option<&'a [u8]> { |
767 | // An integer overflow here on 32bit systems is almost guarantee to be caused |
768 | // by an incorrect parsing logic from the caller side. |
769 | // Simply using `checked_add` here would silently swallow errors, which is not what we want. |
770 | debug_assert!(self.offset as u64 + len as u64 <= u32::MAX as u64); |
771 | |
772 | let v = self.data.get(self.offset..self.offset + len)?; |
773 | self.advance(len); |
774 | Some(v) |
775 | } |
776 | |
777 | /// Reads the next `count` types as a slice. |
778 | #[inline ] |
779 | pub fn read_array16<T: FromData>(&mut self, count: u16) -> Option<LazyArray16<'a, T>> { |
780 | let len = usize::from(count) * T::SIZE; |
781 | self.read_bytes(len).map(LazyArray16::new) |
782 | } |
783 | |
784 | /// Reads the next `count` types as a slice. |
785 | #[inline ] |
786 | pub fn read_array32<T: FromData>(&mut self, count: u32) -> Option<LazyArray32<'a, T>> { |
787 | let len = usize::num_from(count) * T::SIZE; |
788 | self.read_bytes(len).map(LazyArray32::new) |
789 | } |
790 | |
791 | #[allow (dead_code)] |
792 | #[inline ] |
793 | pub fn read_at_offset16(&mut self, data: &'a [u8]) -> Option<&'a [u8]> { |
794 | let offset = self.read::<Offset16>()?.to_usize(); |
795 | data.get(offset..) |
796 | } |
797 | } |
798 | |
799 | /// A common offset methods. |
800 | pub trait Offset { |
801 | /// Converts the offset to `usize`. |
802 | fn to_usize(&self) -> usize; |
803 | } |
804 | |
805 | /// A type-safe u16 offset. |
806 | #[derive (Clone, Copy, Debug)] |
807 | pub struct Offset16(pub u16); |
808 | |
809 | impl Offset for Offset16 { |
810 | #[inline ] |
811 | fn to_usize(&self) -> usize { |
812 | usize::from(self.0) |
813 | } |
814 | } |
815 | |
816 | impl FromData for Offset16 { |
817 | const SIZE: usize = 2; |
818 | |
819 | #[inline ] |
820 | fn parse(data: &[u8]) -> Option<Self> { |
821 | u16::parse(data).map(Offset16) |
822 | } |
823 | } |
824 | |
825 | impl FromData for Option<Offset16> { |
826 | const SIZE: usize = Offset16::SIZE; |
827 | |
828 | #[inline ] |
829 | fn parse(data: &[u8]) -> Option<Self> { |
830 | let offset: Offset16 = Offset16::parse(data)?; |
831 | if offset.0 != 0 { |
832 | Some(Some(offset)) |
833 | } else { |
834 | Some(None) |
835 | } |
836 | } |
837 | } |
838 | |
839 | /// A type-safe u24 offset. |
840 | #[derive (Clone, Copy, Debug)] |
841 | pub struct Offset24(pub u32); |
842 | |
843 | impl Offset for Offset24 { |
844 | #[inline ] |
845 | fn to_usize(&self) -> usize { |
846 | usize::num_from(self.0) |
847 | } |
848 | } |
849 | |
850 | impl FromData for Offset24 { |
851 | const SIZE: usize = 3; |
852 | |
853 | #[inline ] |
854 | fn parse(data: &[u8]) -> Option<Self> { |
855 | U24::parse(data).map(|n: U24| Offset24(n.0)) |
856 | } |
857 | } |
858 | |
859 | impl FromData for Option<Offset24> { |
860 | const SIZE: usize = Offset24::SIZE; |
861 | |
862 | #[inline ] |
863 | fn parse(data: &[u8]) -> Option<Self> { |
864 | let offset: Offset24 = Offset24::parse(data)?; |
865 | if offset.0 != 0 { |
866 | Some(Some(offset)) |
867 | } else { |
868 | Some(None) |
869 | } |
870 | } |
871 | } |
872 | |
873 | /// A type-safe u32 offset. |
874 | #[derive (Clone, Copy, Debug)] |
875 | pub struct Offset32(pub u32); |
876 | |
877 | impl Offset for Offset32 { |
878 | #[inline ] |
879 | fn to_usize(&self) -> usize { |
880 | usize::num_from(self.0) |
881 | } |
882 | } |
883 | |
884 | impl FromData for Offset32 { |
885 | const SIZE: usize = 4; |
886 | |
887 | #[inline ] |
888 | fn parse(data: &[u8]) -> Option<Self> { |
889 | u32::parse(data).map(Offset32) |
890 | } |
891 | } |
892 | |
893 | impl FromData for Option<Offset32> { |
894 | const SIZE: usize = Offset32::SIZE; |
895 | |
896 | #[inline ] |
897 | fn parse(data: &[u8]) -> Option<Self> { |
898 | let offset: Offset32 = Offset32::parse(data)?; |
899 | if offset.0 != 0 { |
900 | Some(Some(offset)) |
901 | } else { |
902 | Some(None) |
903 | } |
904 | } |
905 | } |
906 | |
907 | #[inline ] |
908 | pub fn i16_bound(min: i16, val: i16, max: i16) -> i16 { |
909 | use core::cmp; |
910 | cmp::max(v1:min, v2:cmp::min(v1:max, v2:val)) |
911 | } |
912 | |
913 | #[inline ] |
914 | pub fn f32_bound(min: f32, val: f32, max: f32) -> f32 { |
915 | debug_assert!(min.is_finite()); |
916 | debug_assert!(val.is_finite()); |
917 | debug_assert!(max.is_finite()); |
918 | |
919 | if val > max { |
920 | return max; |
921 | } else if val < min { |
922 | return min; |
923 | } |
924 | |
925 | val |
926 | } |
927 | |