ttf_parser/
parser.rs

1//! Binary parsing utils.
2//!
3//! This module should not be used directly, unless you're planning to parse
4//! some tables manually.
5
6use core::ops::Range;
7use core::convert::{TryFrom, TryInto};
8
9/// A trait for parsing raw binary data.
10///
11/// This is a low-level, internal trait that should not be used directly.
12pub 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
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/// A u24 number.
86///
87/// Stored as u32, but encoded as 3 bytes in the font.
88///
89/// https://docs.microsoft.com/en-us/typography/opentype/spec/otff#data-types
90#[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/// A 16-bit signed fixed number with the low 14 bits of fraction (2.14).
105#[derive(Clone, Copy, Debug)]
106pub struct F2DOT14(pub i16);
107
108impl F2DOT14 {
109    /// Converts i16 to f32.
110    #[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/// A 32-bit signed fixed-point number (16.16).
127#[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        // TODO: is it safe to cast?
136        i32::parse(data).map(|n| Fixed(n as f32 / 65536.0))
137    }
138}
139
140
141/// A safe u32 to usize casting.
142///
143/// Rust doesn't implement `From<u32> for usize`,
144/// because it has to support 16 bit targets.
145/// We don't, so we can allow this.
146pub trait NumFrom<T>: Sized {
147    /// Converts u32 into usize.
148    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        // compilation error on 16 bit targets
160    }
161}
162
163
164/// Just like TryFrom<N>, but for numeric types not supported by the Rust's std.
165pub trait TryNumFrom<T>: Sized {
166    /// Casts between numeric types.
167    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        // Based on https://github.com/rust-num/num-traits/blob/master/src/cast.rs
195
196        // Float as int truncates toward zero, so we want to allow values
197        // in the exclusive range `(MIN-1, MAX+1)`.
198
199        // We can't represent `MIN-1` exactly, but there's no fractional part
200        // at this magnitude, so we can just use a `MIN` inclusive boundary.
201        const MIN: f32 = core::i32::MIN as f32;
202        // We can't represent `MAX` exactly, but it will round up to exactly
203        // `MAX+1` (a power of two) when we cast it.
204        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/// A slice-like container that converts internal binary data only on access.
215///
216/// This is a low-level, internal structure that should not be used directly.
217#[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    /// Creates a new `LazyArray`.
235    #[inline]
236    pub fn new(data: &'a [u8]) -> Self {
237        LazyArray16 {
238            data,
239            data_type: core::marker::PhantomData,
240        }
241    }
242
243    /// Returns a value at `index`.
244    #[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    /// Returns the last value.
256    #[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    /// Returns array's length.
266    #[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    /// Returns array's length.
277    #[inline]
278    pub fn len(&self) -> u16 {
279        (self.data.len() / T::SIZE) as u16
280    }
281
282    /// Checks if array is empty.
283    #[inline]
284    pub fn is_empty(&self) -> bool {
285        self.len() == 0
286    }
287
288    /// Performs a binary search by specified `key`.
289    #[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    /// Performs a binary search using specified closure.
297    #[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        // Based on Rust std implementation.
302
303        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            // mid is always in [0, size), that means mid is >= 0 and < size.
315            // mid >= 0: by definition
316            // mid < size: mid = size / 2 + size / 4 + size / 8 ...
317            let cmp = f(&self.get(mid)?);
318            base = if cmp == Ordering::Greater { base } else { mid };
319            size -= half;
320        }
321
322        // base is always in [0, size) because base <= mid.
323        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/// An iterator over `LazyArray16`.
349#[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; // TODO: check
372        self.data.get(self.index - 1)
373    }
374}
375
376
377/// A slice-like container that converts internal binary data only on access.
378///
379/// This is a low-level, internal structure that should not be used directly.
380#[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    /// Creates a new `LazyArray`.
398    #[inline]
399    pub fn new(data: &'a [u8]) -> Self {
400        LazyArray32 {
401            data,
402            data_type: core::marker::PhantomData,
403        }
404    }
405
406    /// Returns a value at `index`.
407    #[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    /// Returns array's length.
419    #[inline]
420    pub fn len(&self) -> u32 {
421        (self.data.len() / T::SIZE) as u32
422    }
423
424    /// Performs a binary search by specified `key`.
425    #[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    /// Performs a binary search using specified closure.
433    #[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        // Based on Rust std implementation.
438
439        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            // mid is always in [0, size), that means mid is >= 0 and < size.
451            // mid >= 0: by definition
452            // mid < size: mid = size / 2 + size / 4 + size / 8 ...
453            let cmp = f(&self.get(mid)?);
454            base = if cmp == Ordering::Greater { base } else { mid };
455            size -= half;
456        }
457
458        // base is always in [0, size) because base <= mid.
459        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/// An iterator over `LazyArray32`.
485#[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; // TODO: check
498        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/// A streaming binary parser.
509#[derive(Clone, Copy, Default, Debug)]
510pub struct Stream<'a> {
511    data: &'a [u8],
512    offset: usize,
513}
514
515impl<'a> Stream<'a> {
516    /// Creates a new `Stream` parser.
517    #[inline]
518    pub fn new(data: &'a [u8]) -> Self {
519        Stream { data, offset: 0 }
520    }
521
522    /// Creates a new `Stream` parser at offset.
523    ///
524    /// Returns `None` when `offset` is out of bounds.
525    #[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    /// Checks that stream reached the end of the data.
535    #[inline]
536    pub fn at_end(&self) -> bool {
537        self.offset >= self.data.len()
538    }
539
540    /// Jumps to the end of the stream.
541    ///
542    /// Useful to indicate that we parsed all the data.
543    #[inline]
544    pub fn jump_to_end(&mut self) {
545        self.offset = self.data.len();
546    }
547
548    /// Returns the current offset.
549    #[inline]
550    pub fn offset(&self) -> usize {
551        self.offset
552    }
553
554    /// Returns the trailing data.
555    ///
556    /// Returns `None` when `Stream` is reached the end.
557    #[inline]
558    pub fn tail(&self) -> Option<&'a [u8]> {
559        self.data.get(self.offset..)
560    }
561
562    /// Advances by `FromData::SIZE`.
563    ///
564    /// Doesn't check bounds.
565    #[inline]
566    pub fn skip<T: FromData>(&mut self) {
567        self.advance(T::SIZE);
568    }
569
570    /// Advances by the specified `len`.
571    ///
572    /// Doesn't check bounds.
573    #[inline]
574    pub fn advance(&mut self, len: usize) {
575        self.offset += len;
576    }
577
578    /// Advances by the specified `len` and checks for bounds.
579    #[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    /// Parses the type from the steam.
590    ///
591    /// Returns `None` when there is not enough data left in the stream
592    /// or the type parsing failed.
593    #[inline]
594    pub fn read<T: FromData>(&mut self) -> Option<T> {
595        self.read_bytes(T::SIZE).and_then(T::parse)
596    }
597
598    /// Parses the type from the steam at offset.
599    #[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    /// Reads N bytes from the stream.
605    #[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    /// Reads the next `count` types as a slice.
613    #[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    /// Reads the next `count` types as a slice.
620    #[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
628/// A common offset methods.
629pub trait Offset {
630    /// Converts the offset to `usize`.
631    fn to_usize(&self) -> usize;
632
633    /// Checks that offset is null.
634    fn is_null(&self) -> bool { self.to_usize() == 0 }
635}
636
637
638/// A type-safe u16 offset.
639#[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/// A type-safe u32 offset.
670#[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}