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