1 //! Generic traversal of font tables.
2 //!
3 //! This module defines functionality that allows untyped access to font table
4 //! data. This is used as the basis for things like debug printing.
5 //!
6 //! The basis of traversal is the [`SomeTable`] trait, which is implemented for
7 //! all font tables. This trait provides the table's name, as well as ordered access
8 //! to the table's fields. Using this, it is possible to iterate through a table
9 //! and its subtables, records, and values.
10 
11 use std::{fmt::Debug, ops::Deref};
12 
13 use types::{
14     BigEndian, F2Dot14, FWord, Fixed, GlyphId, LongDateTime, MajorMinor, NameId, Nullable,
15     Offset16, Offset24, Offset32, Scalar, Tag, UfWord, Uint24, Version16Dot16,
16 };
17 
18 use crate::{
19     array::{ComputedArray, VarLenArray},
20     read::{ComputeSize, ReadArgs},
21     FontData, FontRead, FontReadWithArgs, ReadError, VarSize,
22 };
23 
24 /// Types of fields in font tables.
25 ///
26 /// Fields can either be scalars, offsets to tables, or arrays.
27 pub enum FieldType<'a> {
28     I8(i8),
29     U8(u8),
30     I16(i16),
31     U16(u16),
32     I32(i32),
33     U32(u32),
34     U24(Uint24),
35     Tag(Tag),
36     FWord(FWord),
37     UfWord(UfWord),
38     MajorMinor(MajorMinor),
39     Version16Dot16(Version16Dot16),
40     F2Dot14(F2Dot14),
41     Fixed(Fixed),
42     LongDateTime(LongDateTime),
43     GlyphId(GlyphId),
44     NameId(NameId),
45     BareOffset(OffsetType),
46     ResolvedOffset(ResolvedOffset<'a>),
47     /// Used in tables like name/post so we can actually print the strings
48     StringOffset(StringOffset<'a>),
49     /// Used in COLR/CPAL
50     ArrayOffset(ArrayOffset<'a>),
51     Record(RecordResolver<'a>),
52     Array(Box<dyn SomeArray<'a> + 'a>),
53     Unknown,
54 }
55 
56 /// Any offset type.
57 #[derive(Clone, Copy)]
58 pub enum OffsetType {
59     Offset16(u16),
60     Offset24(Uint24),
61     Offset32(u32),
62 }
63 
64 impl OffsetType {
65     /// Return this offset as a u32.
to_u32(self) -> u3266     pub fn to_u32(self) -> u32 {
67         match self {
68             Self::Offset16(val) => val.into(),
69             Self::Offset24(val) => val.into(),
70             Self::Offset32(val) => val,
71         }
72     }
73 }
74 
75 /// An offset, as well as the table it references.
76 pub struct ResolvedOffset<'a> {
77     /// The raw offset
78     pub offset: OffsetType,
79     /// The parsed table pointed to by this offset, or an error if parsing fails.
80     pub target: Result<Box<dyn SomeTable<'a> + 'a>, ReadError>,
81 }
82 
83 /// An offset to string data.
84 ///
85 /// This is a special case for the name table (and maybe elsewhere?)
86 pub struct StringOffset<'a> {
87     pub offset: OffsetType,
88     pub target: Result<Box<dyn SomeString<'a> + 'a>, ReadError>,
89 }
90 
91 /// An offset to an array.
92 pub struct ArrayOffset<'a> {
93     pub offset: OffsetType,
94     pub target: Result<Box<dyn SomeArray<'a> + 'a>, ReadError>,
95 }
96 
97 pub(crate) struct ArrayOfOffsets<'a, O> {
98     type_name: &'static str,
99     offsets: &'a [O],
100     resolver: Box<dyn Fn(&O) -> FieldType<'a> + 'a>,
101 }
102 
103 impl<'a, O> SomeArray<'a> for ArrayOfOffsets<'a, O> {
type_name(&self) -> &str104     fn type_name(&self) -> &str {
105         self.type_name
106     }
107 
len(&self) -> usize108     fn len(&self) -> usize {
109         self.offsets.len()
110     }
111 
get(&self, idx: usize) -> Option<FieldType<'a>>112     fn get(&self, idx: usize) -> Option<FieldType<'a>> {
113         let off = self.offsets.get(idx)?;
114         let target = (self.resolver)(off);
115         Some(target)
116     }
117 }
118 
119 impl<'a> FieldType<'a> {
120     /// makes a field, handling the case where this array may not be present in
121     /// all versions
array_of_records<T>( type_name: &'static str, records: &'a [T], data: FontData<'a>, ) -> FieldType<'a> where T: Clone + SomeRecord<'a> + 'a,122     pub fn array_of_records<T>(
123         type_name: &'static str,
124         records: &'a [T],
125         data: FontData<'a>,
126     ) -> FieldType<'a>
127     where
128         T: Clone + SomeRecord<'a> + 'a,
129     {
130         ArrayOfRecords {
131             type_name,
132             data,
133             records,
134         }
135         .into()
136     }
137 
138     // Convenience method for handling computed arrays
computed_array<T>( type_name: &'static str, array: ComputedArray<'a, T>, data: FontData<'a>, ) -> FieldType<'a> where T: FontReadWithArgs<'a> + ComputeSize + SomeRecord<'a> + 'a, T::Args: Copy + 'static,139     pub fn computed_array<T>(
140         type_name: &'static str,
141         array: ComputedArray<'a, T>,
142         data: FontData<'a>,
143     ) -> FieldType<'a>
144     where
145         T: FontReadWithArgs<'a> + ComputeSize + SomeRecord<'a> + 'a,
146         T::Args: Copy + 'static,
147     {
148         ComputedArrayOfRecords {
149             type_name,
150             data,
151             array,
152         }
153         .into()
154     }
155 
156     // Convenience method for handling VarLenArrays
var_array<T>( type_name: &'static str, array: VarLenArray<'a, T>, data: FontData<'a>, ) -> FieldType<'a> where T: FontRead<'a> + VarSize + SomeRecord<'a> + 'a,157     pub fn var_array<T>(
158         type_name: &'static str,
159         array: VarLenArray<'a, T>,
160         data: FontData<'a>,
161     ) -> FieldType<'a>
162     where
163         T: FontRead<'a> + VarSize + SomeRecord<'a> + 'a,
164     {
165         VarLenArrayOfRecords {
166             type_name,
167             data,
168             array,
169         }
170         .into()
171     }
172 
173     /// Convenience method for creating a `FieldType` from an array of offsets.
174     ///
175     /// The `resolver` argument is a function that takes an offset and resolves
176     /// it.
array_of_offsets<O>( type_name: &'static str, offsets: &'a [O], resolver: impl Fn(&O) -> FieldType<'a> + 'a, ) -> Self where177     pub fn array_of_offsets<O>(
178         type_name: &'static str,
179         offsets: &'a [O],
180         resolver: impl Fn(&O) -> FieldType<'a> + 'a,
181     ) -> Self
182 where {
183         FieldType::Array(Box::new(ArrayOfOffsets {
184             type_name,
185             offsets,
186             resolver: Box::new(resolver),
187         }))
188     }
189 
190     /// Convenience method for creating a `FieldType` from an offset to an array.
offset_to_array_of_scalars<T: SomeArray<'a> + 'a>( offset: impl Into<OffsetType>, result: impl Into<Option<Result<T, ReadError>>>, ) -> Self191     pub fn offset_to_array_of_scalars<T: SomeArray<'a> + 'a>(
192         offset: impl Into<OffsetType>,
193         result: impl Into<Option<Result<T, ReadError>>>,
194     ) -> Self {
195         let offset = offset.into();
196         match result.into() {
197             Some(target) => FieldType::ArrayOffset(ArrayOffset {
198                 offset,
199                 target: target.map(|x| Box::new(x) as Box<dyn SomeArray>),
200             }),
201             None => FieldType::BareOffset(offset),
202         }
203     }
204 
205     /// Convenience method for creating a `FieldType` from an offset to an array.
offset_to_array_of_records<T: Clone + SomeRecord<'a> + 'a>( offset: impl Into<OffsetType>, result: impl Into<Option<Result<&'a [T], ReadError>>>, type_name: &'static str, data: FontData<'a>, ) -> Self206     pub fn offset_to_array_of_records<T: Clone + SomeRecord<'a> + 'a>(
207         offset: impl Into<OffsetType>,
208         result: impl Into<Option<Result<&'a [T], ReadError>>>,
209         type_name: &'static str,
210         data: FontData<'a>,
211     ) -> Self {
212         let offset = offset.into();
213         match result.into() {
214             Some(target) => {
215                 let target = target.map(|records| {
216                     Box::new(ArrayOfRecords {
217                         type_name,
218                         data,
219                         records,
220                     }) as Box<dyn SomeArray>
221                 });
222                 FieldType::ArrayOffset(ArrayOffset { offset, target })
223             }
224             None => FieldType::BareOffset(offset),
225         }
226     }
227 
228     //FIXME: I bet this is generating a *lot* of code
229     /// Convenience method for creating a `FieldType` for a resolved offset.
230     ///
231     /// This handles cases where offsets are nullable, in which case the `result`
232     /// argument may be `None`.
offset<T: SomeTable<'a> + 'a>( offset: impl Into<OffsetType>, result: impl Into<Option<Result<T, ReadError>>>, ) -> Self233     pub fn offset<T: SomeTable<'a> + 'a>(
234         offset: impl Into<OffsetType>,
235         result: impl Into<Option<Result<T, ReadError>>>,
236     ) -> Self {
237         let offset = offset.into();
238         match result.into() {
239             Some(target) => FieldType::ResolvedOffset(ResolvedOffset {
240                 offset,
241                 target: target.map(|x| Box::new(x) as Box<dyn SomeTable>),
242             }),
243             None => FieldType::BareOffset(offset),
244         }
245     }
246 
247     /// Convenience method for creating a `FieldType` from an unknown offset.
unknown_offset(offset: impl Into<OffsetType>) -> Self248     pub fn unknown_offset(offset: impl Into<OffsetType>) -> Self {
249         Self::BareOffset(offset.into())
250     }
251 }
252 
253 /// A generic field in a font table.
254 pub struct Field<'a> {
255     /// The field's name.
256     pub name: &'static str,
257     /// The field's value.
258     pub value: FieldType<'a>,
259 }
260 
261 /// A generic table type.
262 ///
263 /// This is intended to be used as a trait object, and is a way of generically
264 /// representing any table, providing ordered access to that table's fields.
265 pub trait SomeTable<'a> {
266     /// The name of this table
type_name(&self) -> &str267     fn type_name(&self) -> &str;
268     /// Access this table's fields, in declaration order.
get_field(&self, idx: usize) -> Option<Field<'a>>269     fn get_field(&self, idx: usize) -> Option<Field<'a>>;
270 }
271 
272 impl<'a> dyn SomeTable<'a> + 'a {
273     /// Returns an iterator over this table's fields.
iter(&self) -> impl Iterator<Item = Field<'a>> + '_274     pub fn iter(&self) -> impl Iterator<Item = Field<'a>> + '_ {
275         FieldIter {
276             table: self,
277             idx: 0,
278         }
279     }
280 }
281 
282 struct FieldIter<'a, 'b> {
283     table: &'b dyn SomeTable<'a>,
284     idx: usize,
285 }
286 
287 impl<'a, 'b> Iterator for FieldIter<'a, 'b> {
288     type Item = Field<'a>;
289 
next(&mut self) -> Option<Self::Item>290     fn next(&mut self) -> Option<Self::Item> {
291         let this = self.idx;
292         self.idx += 1;
293         self.table.get_field(this)
294     }
295 }
296 
297 impl<'a> SomeTable<'a> for Box<dyn SomeTable<'a> + 'a> {
type_name(&self) -> &str298     fn type_name(&self) -> &str {
299         self.deref().type_name()
300     }
301 
get_field(&self, idx: usize) -> Option<Field<'a>>302     fn get_field(&self, idx: usize) -> Option<Field<'a>> {
303         self.deref().get_field(idx)
304     }
305 }
306 
307 /// A generic trait for records, which need to be passed in data
308 /// in order to fully resolve themselves.
309 pub trait SomeRecord<'a> {
traverse(self, data: FontData<'a>) -> RecordResolver<'a>310     fn traverse(self, data: FontData<'a>) -> RecordResolver<'a>;
311 }
312 
313 /// A struct created from a record and the data it needs to resolve any
314 /// contained offsets.
315 pub struct RecordResolver<'a> {
316     pub(crate) name: &'static str,
317     pub(crate) get_field: Box<dyn Fn(usize, FontData<'a>) -> Option<Field<'a>> + 'a>,
318     pub(crate) data: FontData<'a>,
319 }
320 
321 /// A generic trait for arrays.
322 pub trait SomeArray<'a> {
323     /// The name of this type. For an array of u16s, this is `[u16]`.
type_name(&self) -> &str324     fn type_name(&self) -> &str;
325 
326     /// The length of the array.
len(&self) -> usize327     fn len(&self) -> usize;
328 
329     /// Returns `true` if this array is empty.
is_empty(&self) -> bool330     fn is_empty(&self) -> bool {
331         self.len() == 0
332     }
333 
334     /// Return the item at `idx`, or `None` if `idx` is out of bounds.
get(&self, idx: usize) -> Option<FieldType<'a>>335     fn get(&self, idx: usize) -> Option<FieldType<'a>>;
336 }
337 
338 impl<'a> dyn SomeArray<'a> + 'a {
339     /// Return an iterator over the contents of this array.
iter(&self) -> impl Iterator<Item = FieldType<'a>> + '_340     pub fn iter(&self) -> impl Iterator<Item = FieldType<'a>> + '_ {
341         ArrayIter {
342             array: self,
343             idx: 0,
344         }
345     }
346 }
347 
348 struct ArrayIter<'a, 'b> {
349     array: &'b dyn SomeArray<'a>,
350     idx: usize,
351 }
352 
353 impl<'a, 'b> Iterator for ArrayIter<'a, 'b> {
354     type Item = FieldType<'a>;
355 
next(&mut self) -> Option<Self::Item>356     fn next(&mut self) -> Option<Self::Item> {
357         let this = self.idx;
358         self.idx += 1;
359         self.array.get(this)
360     }
361 }
362 
363 impl<'a, T: Scalar + Into<FieldType<'a>>> SomeArray<'a> for &'a [BigEndian<T>]
364 where
365     BigEndian<T>: Copy, // i don't know why i need this??
366 {
len(&self) -> usize367     fn len(&self) -> usize {
368         (*self).len()
369     }
370 
get(&self, idx: usize) -> Option<FieldType<'a>>371     fn get(&self, idx: usize) -> Option<FieldType<'a>> {
372         (*self).get(idx).map(|val| val.get().into())
373     }
374 
type_name(&self) -> &str375     fn type_name(&self) -> &str {
376         let full_name = std::any::type_name::<T>();
377         full_name.split("::").last().unwrap_or(full_name)
378     }
379 }
380 
381 impl<'a> SomeArray<'a> for &'a [u8] {
type_name(&self) -> &str382     fn type_name(&self) -> &str {
383         "u8"
384     }
385 
len(&self) -> usize386     fn len(&self) -> usize {
387         (*self).len()
388     }
389 
get(&self, idx: usize) -> Option<FieldType<'a>>390     fn get(&self, idx: usize) -> Option<FieldType<'a>> {
391         (*self).get(idx).copied().map(Into::into)
392     }
393 }
394 
395 impl<'a> SomeArray<'a> for Box<dyn SomeArray<'a> + 'a> {
type_name(&self) -> &str396     fn type_name(&self) -> &str {
397         self.deref().type_name()
398     }
399 
len(&self) -> usize400     fn len(&self) -> usize {
401         self.deref().len()
402     }
403 
get(&self, idx: usize) -> Option<FieldType<'a>>404     fn get(&self, idx: usize) -> Option<FieldType<'a>> {
405         self.deref().get(idx)
406     }
407 }
408 
409 pub trait SomeString<'a> {
iter_chars(&self) -> Box<dyn Iterator<Item = char> + 'a>410     fn iter_chars(&self) -> Box<dyn Iterator<Item = char> + 'a>;
411 }
412 
413 impl<'a> SomeString<'a> for Box<dyn SomeString<'a> + 'a> {
iter_chars(&self) -> Box<dyn Iterator<Item = char> + 'a>414     fn iter_chars(&self) -> Box<dyn Iterator<Item = char> + 'a> {
415         self.deref().iter_chars()
416     }
417 }
418 
419 // only used as Box<dyn SomeArray<'a>>
420 struct ArrayOfRecords<'a, T> {
421     pub(crate) type_name: &'static str,
422     pub(crate) data: FontData<'a>,
423     pub(crate) records: &'a [T],
424 }
425 
426 // only used as Box<dyn SomeArray<'a>>
427 struct ComputedArrayOfRecords<'a, T: ReadArgs> {
428     pub(crate) type_name: &'static str,
429     pub(crate) data: FontData<'a>,
430     pub(crate) array: ComputedArray<'a, T>,
431 }
432 
433 struct VarLenArrayOfRecords<'a, T> {
434     pub(crate) type_name: &'static str,
435     pub(crate) data: FontData<'a>,
436     pub(crate) array: VarLenArray<'a, T>,
437 }
438 
439 impl<'a, T> SomeArray<'a> for ComputedArrayOfRecords<'a, T>
440 where
441     T: FontReadWithArgs<'a> + ComputeSize + SomeRecord<'a> + 'a,
442     T::Args: Copy + 'static,
443     Self: 'a,
444 {
len(&self) -> usize445     fn len(&self) -> usize {
446         self.array.len()
447     }
448 
get(&self, idx: usize) -> Option<FieldType<'a>>449     fn get(&self, idx: usize) -> Option<FieldType<'a>> {
450         self.array
451             .get(idx)
452             .ok()
453             .map(|record| record.traverse(self.data).into())
454     }
455 
type_name(&self) -> &str456     fn type_name(&self) -> &str {
457         self.type_name
458     }
459 }
460 
461 impl<'a, T: SomeRecord<'a> + Clone> SomeArray<'a> for ArrayOfRecords<'a, T> {
type_name(&self) -> &str462     fn type_name(&self) -> &str {
463         self.type_name
464     }
465 
len(&self) -> usize466     fn len(&self) -> usize {
467         self.records.len()
468     }
469 
get(&self, idx: usize) -> Option<FieldType<'a>>470     fn get(&self, idx: usize) -> Option<FieldType<'a>> {
471         self.records
472             .get(idx)
473             .map(|record| record.clone().traverse(self.data).into())
474     }
475 }
476 
477 impl<'a, T> SomeArray<'a> for VarLenArrayOfRecords<'a, T>
478 where
479     T: FontRead<'a> + VarSize + SomeRecord<'a> + 'a,
480     Self: 'a,
481 {
len(&self) -> usize482     fn len(&self) -> usize {
483         self.array.iter().count()
484     }
485 
get(&self, idx: usize) -> Option<FieldType<'a>>486     fn get(&self, idx: usize) -> Option<FieldType<'a>> {
487         self.array
488             .get(idx)?
489             .ok()
490             .map(|record| record.traverse(self.data).into())
491     }
492 
type_name(&self) -> &str493     fn type_name(&self) -> &str {
494         self.type_name
495     }
496 }
497 
498 impl<'a> Field<'a> {
499     /// Create a new field with the given name and value.
new(name: &'static str, value: impl Into<FieldType<'a>>) -> Self500     pub fn new(name: &'static str, value: impl Into<FieldType<'a>>) -> Self {
501         Field {
502             name,
503             value: value.into(),
504         }
505     }
506 }
507 
508 /// A wrapper type that implements `Debug` for any table.
509 struct DebugPrintTable<'a, 'b>(pub &'b (dyn SomeTable<'a> + 'a));
510 
511 /// A wrapper type that implements `Debug` for any array.
512 struct DebugPrintArray<'a, 'b>(pub &'b (dyn SomeArray<'a> + 'a));
513 
514 impl<'a> Debug for FieldType<'a> {
fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result515     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
516         match self {
517             Self::I8(arg0) => arg0.fmt(f),
518             Self::U8(arg0) => arg0.fmt(f),
519             Self::I16(arg0) => arg0.fmt(f),
520             Self::U16(arg0) => arg0.fmt(f),
521             Self::I32(arg0) => arg0.fmt(f),
522             Self::U32(arg0) => arg0.fmt(f),
523             Self::U24(arg0) => arg0.fmt(f),
524             Self::Tag(arg0) => arg0.fmt(f),
525             Self::FWord(arg0) => arg0.to_i16().fmt(f),
526             Self::UfWord(arg0) => arg0.to_u16().fmt(f),
527             Self::MajorMinor(arg0) => write!(f, "{}.{}", arg0.major, arg0.minor),
528             Self::Version16Dot16(arg0) => arg0.fmt(f),
529             Self::F2Dot14(arg0) => arg0.fmt(f),
530             Self::Fixed(arg0) => arg0.fmt(f),
531             Self::LongDateTime(arg0) => arg0.as_secs().fmt(f),
532             Self::GlyphId(arg0) => {
533                 write!(f, "g")?;
534                 arg0.to_u16().fmt(f)
535             }
536             Self::NameId(arg0) => arg0.fmt(f),
537             Self::StringOffset(string) => match &string.target {
538                 Ok(arg0) => arg0.as_ref().fmt(f),
539                 Err(_) => string.target.fmt(f),
540             },
541             Self::ArrayOffset(array) => match &array.target {
542                 Ok(arg0) => arg0.as_ref().fmt(f),
543                 Err(_) => array.target.fmt(f),
544             },
545             Self::BareOffset(arg0) => write!(f, "0x{:04X}", arg0.to_u32()),
546             Self::ResolvedOffset(ResolvedOffset {
547                 target: Ok(arg0), ..
548             }) => arg0.fmt(f),
549             Self::ResolvedOffset(arg0) => arg0.target.fmt(f),
550             Self::Record(arg0) => (arg0 as &(dyn SomeTable<'a> + 'a)).fmt(f),
551             Self::Array(arg0) => arg0.fmt(f),
552             Self::Unknown => write!(f, "no repr available"),
553         }
554     }
555 }
556 
557 impl<'a, 'b> std::fmt::Debug for DebugPrintTable<'a, 'b> {
fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result558     fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
559         let mut debug_struct = f.debug_struct(self.0.type_name());
560         for field in self.0.iter() {
561             debug_struct.field(field.name, &field.value);
562         }
563         debug_struct.finish()
564     }
565 }
566 
567 impl<'a> Debug for dyn SomeTable<'a> + 'a {
fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result568     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
569         DebugPrintTable(self).fmt(f)
570     }
571 }
572 
573 impl<'a> Debug for dyn SomeString<'a> + 'a {
fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result574     fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
575         write!(f, "\"")?;
576         for c in self.iter_chars() {
577             write!(f, "{c}")?
578         }
579         write!(f, "\"")
580     }
581 }
582 
583 impl<'a, 'b> std::fmt::Debug for DebugPrintArray<'a, 'b> {
fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result584     fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
585         let mut debug_list = f.debug_list();
586         let mut idx = 0;
587         while let Some(item) = self.0.get(idx) {
588             idx += 1;
589             debug_list.entry(&item);
590         }
591         debug_list.finish()
592     }
593 }
594 
595 impl<'a> Debug for dyn SomeArray<'a> + 'a {
fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result596     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
597         DebugPrintArray(self).fmt(f)
598     }
599 }
600 
601 impl std::fmt::Display for OffsetType {
fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result602     fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
603         write!(f, "{:+}", self.to_u32())
604     }
605 }
606 
607 // used to give us an auto-impl of Debug
608 impl<'a> SomeTable<'a> for RecordResolver<'a> {
type_name(&self) -> &str609     fn type_name(&self) -> &str {
610         self.name
611     }
612 
get_field(&self, idx: usize) -> Option<Field<'a>>613     fn get_field(&self, idx: usize) -> Option<Field<'a>> {
614         (self.get_field)(idx, self.data)
615     }
616 }
617 
618 impl<'a> From<u8> for FieldType<'a> {
from(src: u8) -> FieldType<'a>619     fn from(src: u8) -> FieldType<'a> {
620         FieldType::U8(src)
621     }
622 }
623 
624 impl<'a> From<i8> for FieldType<'a> {
from(src: i8) -> FieldType<'a>625     fn from(src: i8) -> FieldType<'a> {
626         FieldType::I8(src)
627     }
628 }
629 
630 impl<'a> From<u16> for FieldType<'a> {
from(src: u16) -> FieldType<'a>631     fn from(src: u16) -> FieldType<'a> {
632         FieldType::U16(src)
633     }
634 }
635 
636 impl<'a> From<i16> for FieldType<'a> {
from(src: i16) -> FieldType<'a>637     fn from(src: i16) -> FieldType<'a> {
638         FieldType::I16(src)
639     }
640 }
641 
642 impl<'a> From<u32> for FieldType<'a> {
from(src: u32) -> FieldType<'a>643     fn from(src: u32) -> FieldType<'a> {
644         FieldType::U32(src)
645     }
646 }
647 
648 impl<'a> From<i32> for FieldType<'a> {
from(src: i32) -> FieldType<'a>649     fn from(src: i32) -> FieldType<'a> {
650         FieldType::I32(src)
651     }
652 }
653 
654 impl<'a> From<Uint24> for FieldType<'a> {
from(src: Uint24) -> FieldType<'a>655     fn from(src: Uint24) -> FieldType<'a> {
656         FieldType::U24(src)
657     }
658 }
659 
660 impl<'a> From<Tag> for FieldType<'a> {
from(src: Tag) -> FieldType<'a>661     fn from(src: Tag) -> FieldType<'a> {
662         FieldType::Tag(src)
663     }
664 }
665 
666 impl<'a> From<FWord> for FieldType<'a> {
from(src: FWord) -> FieldType<'a>667     fn from(src: FWord) -> FieldType<'a> {
668         FieldType::FWord(src)
669     }
670 }
671 
672 impl<'a> From<UfWord> for FieldType<'a> {
from(src: UfWord) -> FieldType<'a>673     fn from(src: UfWord) -> FieldType<'a> {
674         FieldType::UfWord(src)
675     }
676 }
677 
678 impl<'a> From<Fixed> for FieldType<'a> {
from(src: Fixed) -> FieldType<'a>679     fn from(src: Fixed) -> FieldType<'a> {
680         FieldType::Fixed(src)
681     }
682 }
683 
684 impl<'a> From<F2Dot14> for FieldType<'a> {
from(src: F2Dot14) -> FieldType<'a>685     fn from(src: F2Dot14) -> FieldType<'a> {
686         FieldType::F2Dot14(src)
687     }
688 }
689 
690 impl<'a> From<LongDateTime> for FieldType<'a> {
from(src: LongDateTime) -> FieldType<'a>691     fn from(src: LongDateTime) -> FieldType<'a> {
692         FieldType::LongDateTime(src)
693     }
694 }
695 
696 impl<'a> From<MajorMinor> for FieldType<'a> {
from(src: MajorMinor) -> FieldType<'a>697     fn from(src: MajorMinor) -> FieldType<'a> {
698         FieldType::MajorMinor(src)
699     }
700 }
701 
702 impl<'a> From<Version16Dot16> for FieldType<'a> {
from(src: Version16Dot16) -> FieldType<'a>703     fn from(src: Version16Dot16) -> FieldType<'a> {
704         FieldType::Version16Dot16(src)
705     }
706 }
707 
708 impl<'a> From<GlyphId> for FieldType<'a> {
from(src: GlyphId) -> FieldType<'a>709     fn from(src: GlyphId) -> FieldType<'a> {
710         FieldType::GlyphId(src)
711     }
712 }
713 
714 impl<'a> From<NameId> for FieldType<'a> {
from(src: NameId) -> FieldType<'a>715     fn from(src: NameId) -> FieldType<'a> {
716         FieldType::NameId(src)
717     }
718 }
719 
720 impl<'a> From<RecordResolver<'a>> for FieldType<'a> {
from(src: RecordResolver<'a>) -> Self721     fn from(src: RecordResolver<'a>) -> Self {
722         FieldType::Record(src)
723     }
724 }
725 
726 impl<'a, T: SomeArray<'a> + 'a> From<T> for FieldType<'a> {
from(src: T) -> Self727     fn from(src: T) -> Self {
728         FieldType::Array(Box::new(src))
729     }
730 }
731 
732 impl From<Offset16> for OffsetType {
from(src: Offset16) -> OffsetType733     fn from(src: Offset16) -> OffsetType {
734         OffsetType::Offset16(src.to_u32() as u16)
735     }
736 }
737 
738 impl From<Offset24> for OffsetType {
from(src: Offset24) -> OffsetType739     fn from(src: Offset24) -> OffsetType {
740         OffsetType::Offset24(Uint24::new(src.to_u32()))
741     }
742 }
743 
744 impl From<Offset32> for OffsetType {
from(src: Offset32) -> OffsetType745     fn from(src: Offset32) -> OffsetType {
746         OffsetType::Offset32(src.to_u32())
747     }
748 }
749 
750 impl<'a> From<Offset16> for FieldType<'a> {
from(src: Offset16) -> FieldType<'a>751     fn from(src: Offset16) -> FieldType<'a> {
752         FieldType::BareOffset(src.into())
753     }
754 }
755 
756 impl<'a> From<Offset24> for FieldType<'a> {
from(src: Offset24) -> FieldType<'a>757     fn from(src: Offset24) -> FieldType<'a> {
758         FieldType::BareOffset(src.into())
759     }
760 }
761 
762 impl<'a> From<Offset32> for FieldType<'a> {
from(src: Offset32) -> FieldType<'a>763     fn from(src: Offset32) -> FieldType<'a> {
764         FieldType::BareOffset(src.into())
765     }
766 }
767 
768 impl<T: Into<OffsetType> + Clone> From<Nullable<T>> for OffsetType {
from(src: Nullable<T>) -> Self769     fn from(src: Nullable<T>) -> Self {
770         src.offset().clone().into()
771     }
772 }
773