Skip to main content

fontdb/ttf_parser/
parser.rs

1//! Binary parsing utils.
2
3use core::convert::TryInto;
4
5/// A trait for parsing raw binary data of fixed size.
6///
7/// This is a low-level, internal trait that should not be used directly.
8pub trait FromData: Sized {
9    /// Object's raw data size.
10    ///
11    /// Not always the same as `mem::size_of`.
12    const SIZE: usize;
13
14    /// Parses an object from a raw data.
15    fn parse(data: &[u8]) -> Option<Self>;
16}
17
18impl FromData for u16 {
19    const SIZE: usize = 2;
20
21    #[inline]
22    fn parse(data: &[u8]) -> Option<Self> {
23        data.try_into().ok().map(u16::from_be_bytes)
24    }
25}
26
27impl FromData for u32 {
28    const SIZE: usize = 4;
29
30    #[inline]
31    fn parse(data: &[u8]) -> Option<Self> {
32        data.try_into().ok().map(u32::from_be_bytes)
33    }
34}
35
36/// A safe u32 to usize casting.
37///
38/// Rust doesn't implement `From<u32> for usize`,
39/// because it has to support 16 bit targets.
40/// We don't, so we can allow this.
41pub trait NumFrom<T>: Sized {
42    /// Converts u32 into usize.
43    fn num_from(_: T) -> Self;
44}
45
46impl NumFrom<u32> for usize {
47    #[inline]
48    fn num_from(v: u32) -> Self {
49        #[cfg(any(target_pointer_width = "32", target_pointer_width = "64"))]
50        {
51            v as usize
52        }
53
54        // compilation error on 16 bit targets
55    }
56}
57
58/// A slice-like container that converts internal binary data only on access.
59///
60/// Array values are stored in a continuous data chunk.
61#[derive(Clone, Copy)]
62pub struct LazyArray16<'a, T> {
63    data: &'a [u8],
64    data_type: core::marker::PhantomData<T>,
65}
66
67impl<T> Default for LazyArray16<'_, T> {
68    #[inline]
69    fn default() -> Self {
70        LazyArray16 {
71            data: &[],
72            data_type: core::marker::PhantomData,
73        }
74    }
75}
76
77impl<'a, T: FromData> LazyArray16<'a, T> {
78    /// Creates a new `LazyArray`.
79    #[inline]
80    pub fn new(data: &'a [u8]) -> Self {
81        LazyArray16 {
82            data,
83            data_type: core::marker::PhantomData,
84        }
85    }
86
87    /// Returns a value at `index`.
88    #[inline]
89    pub fn get(&self, index: u16) -> Option<T> {
90        if index < self.len() {
91            let start = usize::from(index) * T::SIZE;
92            let end = start + T::SIZE;
93            self.data.get(start..end).and_then(T::parse)
94        } else {
95            None
96        }
97    }
98
99    /// Returns array's length.
100    #[inline]
101    pub fn len(&self) -> u16 {
102        (self.data.len() / T::SIZE) as u16
103    }
104
105    /// Performs a binary search using specified closure.
106    #[inline]
107    pub fn binary_search_by<F>(&self, mut f: F) -> Option<(u16, T)>
108    where
109        F: FnMut(&T) -> core::cmp::Ordering,
110    {
111        // Based on Rust std implementation.
112
113        use core::cmp::Ordering;
114
115        let mut size = self.len();
116        if size == 0 {
117            return None;
118        }
119
120        let mut base = 0;
121        while size > 1 {
122            let half = size / 2;
123            let mid = base + half;
124            // mid is always in [0, size), that means mid is >= 0 and < size.
125            // mid >= 0: by definition
126            // mid < size: mid = size / 2 + size / 4 + size / 8 ...
127            let cmp = f(&self.get(mid)?);
128            base = if cmp == Ordering::Greater { base } else { mid };
129            size -= half;
130        }
131
132        // base is always in [0, size) because base <= mid.
133        let value = self.get(base)?;
134        if f(&value) == Ordering::Equal {
135            Some((base, value))
136        } else {
137            None
138        }
139    }
140}
141
142impl<'a, T: FromData> IntoIterator for LazyArray16<'a, T> {
143    type Item = T;
144    type IntoIter = LazyArrayIter16<'a, T>;
145
146    #[inline]
147    fn into_iter(self) -> Self::IntoIter {
148        LazyArrayIter16 {
149            data: self,
150            index: 0,
151        }
152    }
153}
154
155/// An iterator over `LazyArray16`.
156#[derive(Clone, Copy)]
157pub struct LazyArrayIter16<'a, T> {
158    data: LazyArray16<'a, T>,
159    index: u16,
160}
161
162impl<'a, T: FromData> Iterator for LazyArrayIter16<'a, T> {
163    type Item = T;
164
165    #[inline]
166    fn next(&mut self) -> Option<Self::Item> {
167        self.index += 1; // TODO: check
168        self.data.get(self.index - 1)
169    }
170
171    #[inline]
172    fn count(self) -> usize {
173        usize::from(self.data.len().saturating_sub(self.index))
174    }
175}
176
177/// A slice-like container that converts internal binary data only on access.
178///
179/// This is a low-level, internal structure that should not be used directly.
180#[derive(Clone, Copy)]
181pub struct LazyArray32<'a, T> {
182    data: &'a [u8],
183    data_type: core::marker::PhantomData<T>,
184}
185
186impl<'a, T: FromData> LazyArray32<'a, T> {
187    /// Creates a new `LazyArray`.
188    #[inline]
189    pub fn new(data: &'a [u8]) -> Self {
190        LazyArray32 {
191            data,
192            data_type: core::marker::PhantomData,
193        }
194    }
195
196    /// Returns a value at `index`.
197    #[inline]
198    pub fn get(&self, index: u32) -> Option<T> {
199        if index < self.len() {
200            let start = usize::num_from(index) * T::SIZE;
201            let end = start + T::SIZE;
202            self.data.get(start..end).and_then(T::parse)
203        } else {
204            None
205        }
206    }
207
208    /// Returns array's length.
209    #[inline]
210    pub fn len(&self) -> u32 {
211        (self.data.len() / T::SIZE) as u32
212    }
213}
214
215/// A streaming binary parser.
216#[derive(Clone, Default, Debug)]
217pub struct Stream<'a> {
218    data: &'a [u8],
219    offset: usize,
220}
221
222impl<'a> Stream<'a> {
223    /// Creates a new `Stream` parser.
224    #[inline]
225    pub fn new(data: &'a [u8]) -> Self {
226        Stream { data, offset: 0 }
227    }
228
229    /// Returns the current offset.
230    #[inline]
231    pub fn offset(&self) -> usize {
232        self.offset
233    }
234
235    /// Returns the trailing data.
236    ///
237    /// Returns `None` when `Stream` is reached the end.
238    #[inline]
239    pub fn tail(&self) -> Option<&'a [u8]> {
240        self.data.get(self.offset..)
241    }
242
243    /// Advances by `FromData::SIZE`.
244    ///
245    /// Doesn't check bounds.
246    #[inline]
247    pub fn skip<T: FromData>(&mut self) {
248        self.advance(T::SIZE);
249    }
250
251    /// Advances by the specified `len`.
252    ///
253    /// Doesn't check bounds.
254    #[inline]
255    pub fn advance(&mut self, len: usize) {
256        self.offset += len;
257    }
258
259    /// Advances by the specified `len` and checks for bounds.
260    #[inline]
261    pub fn advance_checked(&mut self, len: usize) -> Option<()> {
262        if self.offset + len <= self.data.len() {
263            self.advance(len);
264            Some(())
265        } else {
266            None
267        }
268    }
269
270    /// Parses the type from the steam.
271    ///
272    /// Returns `None` when there is not enough data left in the stream
273    /// or the type parsing failed.
274    #[inline]
275    pub fn read<T: FromData>(&mut self) -> Option<T> {
276        self.read_bytes(T::SIZE).and_then(T::parse)
277    }
278
279    /// Parses the type from the steam at offset.
280    #[inline]
281    pub fn read_at<T: FromData>(data: &[u8], offset: usize) -> Option<T> {
282        data.get(offset..offset + T::SIZE).and_then(T::parse)
283    }
284
285    /// Reads N bytes from the stream.
286    #[inline]
287    pub fn read_bytes(&mut self, len: usize) -> Option<&'a [u8]> {
288        // An integer overflow here on 32bit systems is almost guarantee to be caused
289        // by an incorrect parsing logic from the caller side.
290        // Simply using `checked_add` here would silently swallow errors, which is not what we want.
291        debug_assert!(self.offset as u64 + len as u64 <= u32::MAX as u64);
292
293        let v = self.data.get(self.offset..self.offset + len)?;
294        self.advance(len);
295        Some(v)
296    }
297
298    /// Reads the next `count` types as a slice.
299    #[inline]
300    pub fn read_array16<T: FromData>(&mut self, count: u16) -> Option<LazyArray16<'a, T>> {
301        let len = usize::from(count) * T::SIZE;
302        self.read_bytes(len).map(LazyArray16::new)
303    }
304
305    /// Reads the next `count` types as a slice.
306    #[inline]
307    pub fn read_array32<T: FromData>(&mut self, count: u32) -> Option<LazyArray32<'a, T>> {
308        let len = usize::num_from(count) * T::SIZE;
309        self.read_bytes(len).map(LazyArray32::new)
310    }
311}
312
313/// A common offset methods.
314pub trait Offset {
315    /// Converts the offset to `usize`.
316    fn to_usize(&self) -> usize;
317}
318
319/// A type-safe u16 offset.
320#[derive(Clone, Copy, Debug)]
321pub struct Offset16(pub u16);
322
323impl Offset for Offset16 {
324    #[inline]
325    fn to_usize(&self) -> usize {
326        usize::from(self.0)
327    }
328}
329
330impl FromData for Offset16 {
331    const SIZE: usize = 2;
332
333    #[inline]
334    fn parse(data: &[u8]) -> Option<Self> {
335        u16::parse(data).map(Offset16)
336    }
337}
338
339/// A type-safe u32 offset.
340#[derive(Clone, Copy, Debug)]
341pub struct Offset32(pub u32);
342
343impl Offset for Offset32 {
344    #[inline]
345    fn to_usize(&self) -> usize {
346        usize::num_from(self.0)
347    }
348}
349
350impl FromData for Offset32 {
351    const SIZE: usize = 4;
352
353    #[inline]
354    fn parse(data: &[u8]) -> Option<Self> {
355        u32::parse(data).map(Offset32)
356    }
357}