Skip to main content

write_fonts/generated/
generated_ift.rs

1// THIS FILE IS AUTOGENERATED.
2// Any changes to this file will be overwritten.
3// For more information about how codegen works, see font-codegen/README.md
4
5#[allow(unused_imports)]
6use crate::codegen_prelude::*;
7
8pub use read_fonts::tables::ift::{
9    EntryFormatFlags, GlyphKeyedFlags, PatchMapFieldPresenceFlags, TablePatchFlags,
10};
11
12#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
13#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
14pub enum Ift {
15    Format1(PatchMapFormat1),
16    Format2(PatchMapFormat2),
17}
18
19impl Ift {
20    /// Construct a new `PatchMapFormat1` subtable
21    #[allow(clippy::too_many_arguments)]
22    pub fn format_1(
23        field_flags: PatchMapFieldPresenceFlags,
24        compatibility_id: CompatibilityId,
25        max_entry_index: u16,
26        max_glyph_map_entry_index: u16,
27        glyph_count: Uint24,
28        glyph_map: GlyphMap,
29        feature_map: Option<FeatureMap>,
30        applied_entries_bitmap: Vec<u8>,
31        url_template_length: u16,
32        url_template: Vec<u8>,
33        patch_format: u8,
34    ) -> Self {
35        Self::Format1(PatchMapFormat1::new(
36            field_flags,
37            compatibility_id,
38            max_entry_index,
39            max_glyph_map_entry_index,
40            glyph_count,
41            glyph_map,
42            feature_map,
43            applied_entries_bitmap,
44            url_template_length,
45            url_template,
46            patch_format,
47        ))
48    }
49
50    /// Construct a new `PatchMapFormat2` subtable
51    #[allow(clippy::too_many_arguments)]
52    pub fn format_2(
53        field_flags: PatchMapFieldPresenceFlags,
54        compatibility_id: CompatibilityId,
55        default_patch_format: u8,
56        entry_count: Uint24,
57        entries: MappingEntries,
58        entry_id_string_data: Option<IdStringData>,
59        url_template_length: u16,
60        url_template: Vec<u8>,
61    ) -> Self {
62        Self::Format2(PatchMapFormat2::new(
63            field_flags,
64            compatibility_id,
65            default_patch_format,
66            entry_count,
67            entries,
68            entry_id_string_data,
69            url_template_length,
70            url_template,
71        ))
72    }
73}
74
75impl Default for Ift {
76    fn default() -> Self {
77        Self::Format1(Default::default())
78    }
79}
80
81impl FontWrite for Ift {
82    fn write_into(&self, writer: &mut TableWriter) {
83        match self {
84            Self::Format1(item) => item.write_into(writer),
85            Self::Format2(item) => item.write_into(writer),
86        }
87    }
88    fn table_type(&self) -> TableType {
89        match self {
90            Self::Format1(item) => item.table_type(),
91            Self::Format2(item) => item.table_type(),
92        }
93    }
94}
95
96impl Validate for Ift {
97    fn validate_impl(&self, ctx: &mut ValidationCtx) {
98        match self {
99            Self::Format1(item) => item.validate_impl(ctx),
100            Self::Format2(item) => item.validate_impl(ctx),
101        }
102    }
103}
104
105impl FromObjRef<read_fonts::tables::ift::Ift<'_>> for Ift {
106    fn from_obj_ref(obj: &read_fonts::tables::ift::Ift, _: FontData) -> Self {
107        use read_fonts::tables::ift::Ift as ObjRefType;
108        match obj {
109            ObjRefType::Format1(item) => Ift::Format1(item.to_owned_table()),
110            ObjRefType::Format2(item) => Ift::Format2(item.to_owned_table()),
111        }
112    }
113}
114
115impl FromTableRef<read_fonts::tables::ift::Ift<'_>> for Ift {}
116
117impl<'a> FontRead<'a> for Ift {
118    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
119        <read_fonts::tables::ift::Ift as FontRead>::read(data).map(|x| x.to_owned_table())
120    }
121}
122
123impl From<PatchMapFormat1> for Ift {
124    fn from(src: PatchMapFormat1) -> Ift {
125        Ift::Format1(src)
126    }
127}
128
129impl From<PatchMapFormat2> for Ift {
130    fn from(src: PatchMapFormat2) -> Ift {
131        Ift::Format2(src)
132    }
133}
134
135impl FontWrite for PatchMapFieldPresenceFlags {
136    fn write_into(&self, writer: &mut TableWriter) {
137        writer.write_slice(&self.bits().to_be_bytes())
138    }
139}
140
141/// [Patch Map Format Format 1](https://w3c.github.io/IFT/Overview.html#patch-map-format-1)
142#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
143#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
144pub struct PatchMapFormat1 {
145    pub field_flags: PatchMapFieldPresenceFlags,
146    /// Unique ID that identifies compatible patches.
147    pub compatibility_id: CompatibilityId,
148    /// Largest entry index which appears in either the glyph map or feature map.
149    pub max_entry_index: u16,
150    /// Largest entry index which appears in the glyph map.
151    pub max_glyph_map_entry_index: u16,
152    pub glyph_count: Uint24,
153    /// Sub table that maps glyph ids to entry indices.
154    pub glyph_map: OffsetMarker<GlyphMap, WIDTH_32>,
155    /// Sub table that maps feature and glyph ids to entry indices.
156    pub feature_map: NullableOffsetMarker<FeatureMap, WIDTH_32>,
157    pub applied_entries_bitmap: Vec<u8>,
158    pub url_template_length: u16,
159    pub url_template: Vec<u8>,
160    /// Patch format number for patches referenced by this mapping.
161    pub patch_format: u8,
162    pub cff_charstrings_offset: Option<u32>,
163    pub cff2_charstrings_offset: Option<u32>,
164}
165
166impl PatchMapFormat1 {
167    /// Construct a new `PatchMapFormat1`
168    #[allow(clippy::too_many_arguments)]
169    pub fn new(
170        field_flags: PatchMapFieldPresenceFlags,
171        compatibility_id: CompatibilityId,
172        max_entry_index: u16,
173        max_glyph_map_entry_index: u16,
174        glyph_count: Uint24,
175        glyph_map: GlyphMap,
176        feature_map: Option<FeatureMap>,
177        applied_entries_bitmap: Vec<u8>,
178        url_template_length: u16,
179        url_template: Vec<u8>,
180        patch_format: u8,
181    ) -> Self {
182        Self {
183            field_flags,
184            compatibility_id,
185            max_entry_index,
186            max_glyph_map_entry_index,
187            glyph_count,
188            glyph_map: glyph_map.into(),
189            feature_map: feature_map.into(),
190            applied_entries_bitmap,
191            url_template_length,
192            url_template,
193            patch_format,
194            ..Default::default()
195        }
196    }
197}
198
199impl FontWrite for PatchMapFormat1 {
200    #[allow(clippy::unnecessary_cast)]
201    fn write_into(&self, writer: &mut TableWriter) {
202        (1 as u8).write_into(writer);
203        (0 as u8).write_into(writer);
204        (0 as u8).write_into(writer);
205        (0 as u8).write_into(writer);
206        self.field_flags.write_into(writer);
207        self.compatibility_id.write_into(writer);
208        self.max_entry_index.write_into(writer);
209        self.max_glyph_map_entry_index.write_into(writer);
210        self.glyph_count.write_into(writer);
211        self.glyph_map.write_into(writer);
212        self.feature_map.write_into(writer);
213        self.applied_entries_bitmap.write_into(writer);
214        self.url_template_length.write_into(writer);
215        self.url_template.write_into(writer);
216        self.patch_format.write_into(writer);
217        self.field_flags
218            .contains(PatchMapFieldPresenceFlags::CFF_CHARSTRINGS_OFFSET)
219            .then(|| {
220                self.cff_charstrings_offset
221                    .as_ref()
222                    .expect("missing conditional field should have failed validation")
223                    .write_into(writer)
224            });
225        self.field_flags
226            .contains(PatchMapFieldPresenceFlags::CFF2_CHARSTRINGS_OFFSET)
227            .then(|| {
228                self.cff2_charstrings_offset
229                    .as_ref()
230                    .expect("missing conditional field should have failed validation")
231                    .write_into(writer)
232            });
233    }
234    fn table_type(&self) -> TableType {
235        TableType::Named("PatchMapFormat1")
236    }
237}
238
239impl Validate for PatchMapFormat1 {
240    fn validate_impl(&self, ctx: &mut ValidationCtx) {
241        ctx.in_table("PatchMapFormat1", |ctx| {
242            ctx.in_field("glyph_map", |ctx| {
243                self.glyph_map.validate_impl(ctx);
244            });
245            ctx.in_field("feature_map", |ctx| {
246                self.feature_map.validate_impl(ctx);
247            });
248            ctx.in_field("url_template", |ctx| {
249                if self.url_template.len() > (u16::MAX as usize) {
250                    ctx.report("array exceeds max length");
251                }
252            });
253            ctx.in_field("cff_charstrings_offset", |ctx| {
254                if !(self
255                    .field_flags
256                    .contains(PatchMapFieldPresenceFlags::CFF_CHARSTRINGS_OFFSET))
257                    && self.cff_charstrings_offset.is_some()
258                {
259                    ctx.report(
260                        "'cff_charstrings_offset' is present but CFF_CHARSTRINGS_OFFSET not set",
261                    )
262                }
263                if (self
264                    .field_flags
265                    .contains(PatchMapFieldPresenceFlags::CFF_CHARSTRINGS_OFFSET))
266                    && self.cff_charstrings_offset.is_none()
267                {
268                    ctx.report("CFF_CHARSTRINGS_OFFSET is set but 'cff_charstrings_offset' is None")
269                }
270            });
271            ctx.in_field("cff2_charstrings_offset", |ctx| {
272                if !(self
273                    .field_flags
274                    .contains(PatchMapFieldPresenceFlags::CFF2_CHARSTRINGS_OFFSET))
275                    && self.cff2_charstrings_offset.is_some()
276                {
277                    ctx.report(
278                        "'cff2_charstrings_offset' is present but CFF2_CHARSTRINGS_OFFSET not set",
279                    )
280                }
281                if (self
282                    .field_flags
283                    .contains(PatchMapFieldPresenceFlags::CFF2_CHARSTRINGS_OFFSET))
284                    && self.cff2_charstrings_offset.is_none()
285                {
286                    ctx.report(
287                        "CFF2_CHARSTRINGS_OFFSET is set but 'cff2_charstrings_offset' is None",
288                    )
289                }
290            });
291        })
292    }
293}
294
295impl<'a> FromObjRef<read_fonts::tables::ift::PatchMapFormat1<'a>> for PatchMapFormat1 {
296    fn from_obj_ref(obj: &read_fonts::tables::ift::PatchMapFormat1<'a>, _: FontData) -> Self {
297        let offset_data = obj.offset_data();
298        PatchMapFormat1 {
299            field_flags: obj.field_flags(),
300            compatibility_id: obj.compatibility_id(),
301            max_entry_index: obj.max_entry_index(),
302            max_glyph_map_entry_index: obj.max_glyph_map_entry_index(),
303            glyph_count: obj.glyph_count(),
304            glyph_map: obj.glyph_map().to_owned_table(),
305            feature_map: obj.feature_map().to_owned_table(),
306            applied_entries_bitmap: obj.applied_entries_bitmap().to_owned_obj(offset_data),
307            url_template_length: obj.url_template_length(),
308            url_template: obj.url_template().to_owned_obj(offset_data),
309            patch_format: obj.patch_format(),
310            cff_charstrings_offset: obj.cff_charstrings_offset(),
311            cff2_charstrings_offset: obj.cff2_charstrings_offset(),
312        }
313    }
314}
315
316#[allow(clippy::needless_lifetimes)]
317impl<'a> FromTableRef<read_fonts::tables::ift::PatchMapFormat1<'a>> for PatchMapFormat1 {}
318
319impl<'a> FontRead<'a> for PatchMapFormat1 {
320    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
321        <read_fonts::tables::ift::PatchMapFormat1 as FontRead>::read(data)
322            .map(|x| x.to_owned_table())
323    }
324}
325
326#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
327#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
328pub struct GlyphMap {
329    pub first_mapped_glyph: u16,
330}
331
332impl GlyphMap {
333    /// Construct a new `GlyphMap`
334    pub fn new(first_mapped_glyph: u16) -> Self {
335        Self { first_mapped_glyph }
336    }
337}
338
339impl FontWrite for GlyphMap {
340    #[allow(clippy::unnecessary_cast)]
341    fn write_into(&self, writer: &mut TableWriter) {
342        self.first_mapped_glyph.write_into(writer);
343    }
344    fn table_type(&self) -> TableType {
345        TableType::Named("GlyphMap")
346    }
347}
348
349impl Validate for GlyphMap {
350    fn validate_impl(&self, _ctx: &mut ValidationCtx) {}
351}
352
353impl<'a> FromObjRef<read_fonts::tables::ift::GlyphMap<'a>> for GlyphMap {
354    fn from_obj_ref(obj: &read_fonts::tables::ift::GlyphMap<'a>, _: FontData) -> Self {
355        let offset_data = obj.offset_data();
356        GlyphMap {
357            first_mapped_glyph: obj.first_mapped_glyph(),
358        }
359    }
360}
361
362#[allow(clippy::needless_lifetimes)]
363impl<'a> FromTableRef<read_fonts::tables::ift::GlyphMap<'a>> for GlyphMap {}
364
365#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
366#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
367pub struct FeatureMap {
368    pub feature_count: u16,
369    pub entry_map_data: Vec<u8>,
370}
371
372impl FeatureMap {
373    /// Construct a new `FeatureMap`
374    pub fn new(feature_count: u16, entry_map_data: Vec<u8>) -> Self {
375        Self {
376            feature_count,
377            entry_map_data,
378        }
379    }
380}
381
382impl FontWrite for FeatureMap {
383    #[allow(clippy::unnecessary_cast)]
384    fn write_into(&self, writer: &mut TableWriter) {
385        self.feature_count.write_into(writer);
386        self.entry_map_data.write_into(writer);
387    }
388    fn table_type(&self) -> TableType {
389        TableType::Named("FeatureMap")
390    }
391}
392
393impl Validate for FeatureMap {
394    fn validate_impl(&self, _ctx: &mut ValidationCtx) {}
395}
396
397impl<'a> FromObjRef<read_fonts::tables::ift::FeatureMap<'a>> for FeatureMap {
398    fn from_obj_ref(obj: &read_fonts::tables::ift::FeatureMap<'a>, _: FontData) -> Self {
399        let offset_data = obj.offset_data();
400        FeatureMap {
401            feature_count: obj.feature_count(),
402            entry_map_data: obj.entry_map_data().to_owned_obj(offset_data),
403        }
404    }
405}
406
407#[allow(clippy::needless_lifetimes)]
408impl<'a> FromTableRef<read_fonts::tables::ift::FeatureMap<'a>> for FeatureMap {}
409
410#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
411#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
412pub struct FeatureRecord {
413    pub feature_tag: Tag,
414}
415
416impl FeatureRecord {
417    /// Construct a new `FeatureRecord`
418    pub fn new(feature_tag: Tag) -> Self {
419        Self { feature_tag }
420    }
421}
422
423impl FontWrite for FeatureRecord {
424    #[allow(clippy::unnecessary_cast)]
425    fn write_into(&self, writer: &mut TableWriter) {
426        self.feature_tag.write_into(writer);
427    }
428    fn table_type(&self) -> TableType {
429        TableType::Named("FeatureRecord")
430    }
431}
432
433impl Validate for FeatureRecord {
434    fn validate_impl(&self, _ctx: &mut ValidationCtx) {}
435}
436
437impl FromObjRef<read_fonts::tables::ift::FeatureRecord> for FeatureRecord {
438    fn from_obj_ref(obj: &read_fonts::tables::ift::FeatureRecord, offset_data: FontData) -> Self {
439        FeatureRecord {
440            feature_tag: obj.feature_tag(),
441        }
442    }
443}
444
445#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
446#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
447pub struct EntryMapRecord {}
448
449impl EntryMapRecord {
450    /// Construct a new `EntryMapRecord`
451    pub fn new() -> Self {
452        Self {}
453    }
454}
455
456impl FontWrite for EntryMapRecord {
457    #[allow(clippy::unnecessary_cast)]
458    fn write_into(&self, writer: &mut TableWriter) {}
459    fn table_type(&self) -> TableType {
460        TableType::Named("EntryMapRecord")
461    }
462}
463
464impl Validate for EntryMapRecord {
465    fn validate_impl(&self, _ctx: &mut ValidationCtx) {}
466}
467
468impl FromObjRef<read_fonts::tables::ift::EntryMapRecord> for EntryMapRecord {
469    fn from_obj_ref(obj: &read_fonts::tables::ift::EntryMapRecord, offset_data: FontData) -> Self {
470        EntryMapRecord {}
471    }
472}
473
474/// [Patch Map Format Format 2](https://w3c.github.io/IFT/Overview.html#patch-map-format-2)
475#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
476#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
477pub struct PatchMapFormat2 {
478    pub field_flags: PatchMapFieldPresenceFlags,
479    /// Unique ID that identifies compatible patches.
480    pub compatibility_id: CompatibilityId,
481    /// Patch format number for patches referenced by this mapping.
482    pub default_patch_format: u8,
483    pub entry_count: Uint24,
484    pub entries: OffsetMarker<MappingEntries, WIDTH_32>,
485    pub entry_id_string_data: NullableOffsetMarker<IdStringData, WIDTH_32>,
486    pub url_template_length: u16,
487    pub url_template: Vec<u8>,
488    pub cff_charstrings_offset: Option<u32>,
489    pub cff2_charstrings_offset: Option<u32>,
490}
491
492impl PatchMapFormat2 {
493    /// Construct a new `PatchMapFormat2`
494    #[allow(clippy::too_many_arguments)]
495    pub fn new(
496        field_flags: PatchMapFieldPresenceFlags,
497        compatibility_id: CompatibilityId,
498        default_patch_format: u8,
499        entry_count: Uint24,
500        entries: MappingEntries,
501        entry_id_string_data: Option<IdStringData>,
502        url_template_length: u16,
503        url_template: Vec<u8>,
504    ) -> Self {
505        Self {
506            field_flags,
507            compatibility_id,
508            default_patch_format,
509            entry_count,
510            entries: entries.into(),
511            entry_id_string_data: entry_id_string_data.into(),
512            url_template_length,
513            url_template,
514            ..Default::default()
515        }
516    }
517}
518
519impl FontWrite for PatchMapFormat2 {
520    #[allow(clippy::unnecessary_cast)]
521    fn write_into(&self, writer: &mut TableWriter) {
522        (2 as u8).write_into(writer);
523        (0 as u8).write_into(writer);
524        (0 as u8).write_into(writer);
525        (0 as u8).write_into(writer);
526        self.field_flags.write_into(writer);
527        self.compatibility_id.write_into(writer);
528        self.default_patch_format.write_into(writer);
529        self.entry_count.write_into(writer);
530        self.entries.write_into(writer);
531        self.entry_id_string_data.write_into(writer);
532        self.url_template_length.write_into(writer);
533        self.url_template.write_into(writer);
534        self.field_flags
535            .contains(PatchMapFieldPresenceFlags::CFF_CHARSTRINGS_OFFSET)
536            .then(|| {
537                self.cff_charstrings_offset
538                    .as_ref()
539                    .expect("missing conditional field should have failed validation")
540                    .write_into(writer)
541            });
542        self.field_flags
543            .contains(PatchMapFieldPresenceFlags::CFF2_CHARSTRINGS_OFFSET)
544            .then(|| {
545                self.cff2_charstrings_offset
546                    .as_ref()
547                    .expect("missing conditional field should have failed validation")
548                    .write_into(writer)
549            });
550    }
551    fn table_type(&self) -> TableType {
552        TableType::Named("PatchMapFormat2")
553    }
554}
555
556impl Validate for PatchMapFormat2 {
557    fn validate_impl(&self, ctx: &mut ValidationCtx) {
558        ctx.in_table("PatchMapFormat2", |ctx| {
559            ctx.in_field("entries", |ctx| {
560                self.entries.validate_impl(ctx);
561            });
562            ctx.in_field("entry_id_string_data", |ctx| {
563                self.entry_id_string_data.validate_impl(ctx);
564            });
565            ctx.in_field("url_template", |ctx| {
566                if self.url_template.len() > (u16::MAX as usize) {
567                    ctx.report("array exceeds max length");
568                }
569            });
570            ctx.in_field("cff_charstrings_offset", |ctx| {
571                if !(self
572                    .field_flags
573                    .contains(PatchMapFieldPresenceFlags::CFF_CHARSTRINGS_OFFSET))
574                    && self.cff_charstrings_offset.is_some()
575                {
576                    ctx.report(
577                        "'cff_charstrings_offset' is present but CFF_CHARSTRINGS_OFFSET not set",
578                    )
579                }
580                if (self
581                    .field_flags
582                    .contains(PatchMapFieldPresenceFlags::CFF_CHARSTRINGS_OFFSET))
583                    && self.cff_charstrings_offset.is_none()
584                {
585                    ctx.report("CFF_CHARSTRINGS_OFFSET is set but 'cff_charstrings_offset' is None")
586                }
587            });
588            ctx.in_field("cff2_charstrings_offset", |ctx| {
589                if !(self
590                    .field_flags
591                    .contains(PatchMapFieldPresenceFlags::CFF2_CHARSTRINGS_OFFSET))
592                    && self.cff2_charstrings_offset.is_some()
593                {
594                    ctx.report(
595                        "'cff2_charstrings_offset' is present but CFF2_CHARSTRINGS_OFFSET not set",
596                    )
597                }
598                if (self
599                    .field_flags
600                    .contains(PatchMapFieldPresenceFlags::CFF2_CHARSTRINGS_OFFSET))
601                    && self.cff2_charstrings_offset.is_none()
602                {
603                    ctx.report(
604                        "CFF2_CHARSTRINGS_OFFSET is set but 'cff2_charstrings_offset' is None",
605                    )
606                }
607            });
608        })
609    }
610}
611
612impl<'a> FromObjRef<read_fonts::tables::ift::PatchMapFormat2<'a>> for PatchMapFormat2 {
613    fn from_obj_ref(obj: &read_fonts::tables::ift::PatchMapFormat2<'a>, _: FontData) -> Self {
614        let offset_data = obj.offset_data();
615        PatchMapFormat2 {
616            field_flags: obj.field_flags(),
617            compatibility_id: obj.compatibility_id(),
618            default_patch_format: obj.default_patch_format(),
619            entry_count: obj.entry_count(),
620            entries: obj.entries().to_owned_table(),
621            entry_id_string_data: obj.entry_id_string_data().to_owned_table(),
622            url_template_length: obj.url_template_length(),
623            url_template: obj.url_template().to_owned_obj(offset_data),
624            cff_charstrings_offset: obj.cff_charstrings_offset(),
625            cff2_charstrings_offset: obj.cff2_charstrings_offset(),
626        }
627    }
628}
629
630#[allow(clippy::needless_lifetimes)]
631impl<'a> FromTableRef<read_fonts::tables::ift::PatchMapFormat2<'a>> for PatchMapFormat2 {}
632
633impl<'a> FontRead<'a> for PatchMapFormat2 {
634    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
635        <read_fonts::tables::ift::PatchMapFormat2 as FontRead>::read(data)
636            .map(|x| x.to_owned_table())
637    }
638}
639
640#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
641#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
642pub struct MappingEntries {
643    pub entry_data: Vec<u8>,
644}
645
646impl MappingEntries {
647    /// Construct a new `MappingEntries`
648    pub fn new(entry_data: Vec<u8>) -> Self {
649        Self { entry_data }
650    }
651}
652
653impl FontWrite for MappingEntries {
654    fn write_into(&self, writer: &mut TableWriter) {
655        self.entry_data.write_into(writer);
656    }
657    fn table_type(&self) -> TableType {
658        TableType::Named("MappingEntries")
659    }
660}
661
662impl Validate for MappingEntries {
663    fn validate_impl(&self, _ctx: &mut ValidationCtx) {}
664}
665
666impl<'a> FromObjRef<read_fonts::tables::ift::MappingEntries<'a>> for MappingEntries {
667    fn from_obj_ref(obj: &read_fonts::tables::ift::MappingEntries<'a>, _: FontData) -> Self {
668        let offset_data = obj.offset_data();
669        MappingEntries {
670            entry_data: obj.entry_data().to_owned_obj(offset_data),
671        }
672    }
673}
674
675#[allow(clippy::needless_lifetimes)]
676impl<'a> FromTableRef<read_fonts::tables::ift::MappingEntries<'a>> for MappingEntries {}
677
678impl<'a> FontRead<'a> for MappingEntries {
679    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
680        <read_fonts::tables::ift::MappingEntries as FontRead>::read(data)
681            .map(|x| x.to_owned_table())
682    }
683}
684
685#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
686#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
687pub struct EntryData {
688    pub format_flags: EntryFormatFlags,
689    pub feature_count: Option<u8>,
690    pub feature_tags: Option<Vec<Tag>>,
691    pub design_space_count: Option<u16>,
692    pub design_space_segments: Option<Vec<DesignSpaceSegment>>,
693    pub child_indices: Option<Vec<Uint24>>,
694    pub trailing_data: Vec<u8>,
695}
696
697impl EntryData {
698    /// Construct a new `EntryData`
699    pub fn new(format_flags: EntryFormatFlags, trailing_data: Vec<u8>) -> Self {
700        Self {
701            format_flags,
702            trailing_data,
703            ..Default::default()
704        }
705    }
706}
707
708impl FontWrite for EntryData {
709    #[allow(clippy::unnecessary_cast)]
710    fn write_into(&self, writer: &mut TableWriter) {
711        self.format_flags.write_into(writer);
712        self.format_flags
713            .contains(EntryFormatFlags::FEATURES_AND_DESIGN_SPACE)
714            .then(|| {
715                self.feature_count
716                    .as_ref()
717                    .expect("missing conditional field should have failed validation")
718                    .write_into(writer)
719            });
720        self.format_flags
721            .contains(EntryFormatFlags::FEATURES_AND_DESIGN_SPACE)
722            .then(|| {
723                self.feature_tags
724                    .as_ref()
725                    .expect("missing conditional field should have failed validation")
726                    .write_into(writer)
727            });
728        self.format_flags
729            .contains(EntryFormatFlags::FEATURES_AND_DESIGN_SPACE)
730            .then(|| {
731                self.design_space_count
732                    .as_ref()
733                    .expect("missing conditional field should have failed validation")
734                    .write_into(writer)
735            });
736        self.format_flags
737            .contains(EntryFormatFlags::FEATURES_AND_DESIGN_SPACE)
738            .then(|| {
739                self.design_space_segments
740                    .as_ref()
741                    .expect("missing conditional field should have failed validation")
742                    .write_into(writer)
743            });
744        self.format_flags
745            .contains(EntryFormatFlags::CHILD_INDICES)
746            .then(|| {
747                self.child_indices
748                    .as_ref()
749                    .expect("missing conditional field should have failed validation")
750                    .write_into(writer)
751            });
752        self.trailing_data.write_into(writer);
753    }
754    fn table_type(&self) -> TableType {
755        TableType::Named("EntryData")
756    }
757}
758
759impl Validate for EntryData {
760    fn validate_impl(&self, ctx: &mut ValidationCtx) {
761        ctx.in_table("EntryData", |ctx| {
762            ctx.in_field("feature_count", |ctx| {
763                if !(self
764                    .format_flags
765                    .contains(EntryFormatFlags::FEATURES_AND_DESIGN_SPACE))
766                    && self.feature_count.is_some()
767                {
768                    ctx.report("'feature_count' is present but FEATURES_AND_DESIGN_SPACE not set")
769                }
770                if (self
771                    .format_flags
772                    .contains(EntryFormatFlags::FEATURES_AND_DESIGN_SPACE))
773                    && self.feature_count.is_none()
774                {
775                    ctx.report("FEATURES_AND_DESIGN_SPACE is set but 'feature_count' is None")
776                }
777            });
778            ctx.in_field("feature_tags", |ctx| {
779                if !(self
780                    .format_flags
781                    .contains(EntryFormatFlags::FEATURES_AND_DESIGN_SPACE))
782                    && self.feature_tags.is_some()
783                {
784                    ctx.report("'feature_tags' is present but FEATURES_AND_DESIGN_SPACE not set")
785                }
786                if (self
787                    .format_flags
788                    .contains(EntryFormatFlags::FEATURES_AND_DESIGN_SPACE))
789                    && self.feature_tags.is_none()
790                {
791                    ctx.report("FEATURES_AND_DESIGN_SPACE is set but 'feature_tags' is None")
792                }
793                if self.feature_tags.is_some()
794                    && self.feature_tags.as_ref().unwrap().len() > (u8::MAX as usize)
795                {
796                    ctx.report("array exceeds max length");
797                }
798            });
799            ctx.in_field("design_space_count", |ctx| {
800                if !(self
801                    .format_flags
802                    .contains(EntryFormatFlags::FEATURES_AND_DESIGN_SPACE))
803                    && self.design_space_count.is_some()
804                {
805                    ctx.report(
806                        "'design_space_count' is present but FEATURES_AND_DESIGN_SPACE not set",
807                    )
808                }
809                if (self
810                    .format_flags
811                    .contains(EntryFormatFlags::FEATURES_AND_DESIGN_SPACE))
812                    && self.design_space_count.is_none()
813                {
814                    ctx.report("FEATURES_AND_DESIGN_SPACE is set but 'design_space_count' is None")
815                }
816            });
817            ctx.in_field("design_space_segments", |ctx| {
818                if !(self
819                    .format_flags
820                    .contains(EntryFormatFlags::FEATURES_AND_DESIGN_SPACE))
821                    && self.design_space_segments.is_some()
822                {
823                    ctx.report(
824                        "'design_space_segments' is present but FEATURES_AND_DESIGN_SPACE not set",
825                    )
826                }
827                if (self
828                    .format_flags
829                    .contains(EntryFormatFlags::FEATURES_AND_DESIGN_SPACE))
830                    && self.design_space_segments.is_none()
831                {
832                    ctx.report(
833                        "FEATURES_AND_DESIGN_SPACE is set but 'design_space_segments' is None",
834                    )
835                }
836                if self.design_space_segments.is_some()
837                    && self.design_space_segments.as_ref().unwrap().len() > (u16::MAX as usize)
838                {
839                    ctx.report("array exceeds max length");
840                }
841                self.design_space_segments.validate_impl(ctx);
842            });
843            ctx.in_field("child_indices", |ctx| {
844                if !(self.format_flags.contains(EntryFormatFlags::CHILD_INDICES))
845                    && self.child_indices.is_some()
846                {
847                    ctx.report("'child_indices' is present but CHILD_INDICES not set")
848                }
849                if (self.format_flags.contains(EntryFormatFlags::CHILD_INDICES))
850                    && self.child_indices.is_none()
851                {
852                    ctx.report("CHILD_INDICES is set but 'child_indices' is None")
853                }
854            });
855        })
856    }
857}
858
859impl<'a> FromObjRef<read_fonts::tables::ift::EntryData<'a>> for EntryData {
860    fn from_obj_ref(obj: &read_fonts::tables::ift::EntryData<'a>, _: FontData) -> Self {
861        let offset_data = obj.offset_data();
862        EntryData {
863            format_flags: obj.format_flags(),
864            feature_count: obj.feature_count(),
865            feature_tags: obj.feature_tags().to_owned_obj(offset_data),
866            design_space_count: obj.design_space_count(),
867            design_space_segments: obj.design_space_segments().to_owned_obj(offset_data),
868            child_indices: obj.child_indices().to_owned_obj(offset_data),
869            trailing_data: obj.trailing_data().to_owned_obj(offset_data),
870        }
871    }
872}
873
874#[allow(clippy::needless_lifetimes)]
875impl<'a> FromTableRef<read_fonts::tables::ift::EntryData<'a>> for EntryData {}
876
877impl<'a> FontRead<'a> for EntryData {
878    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
879        <read_fonts::tables::ift::EntryData as FontRead>::read(data).map(|x| x.to_owned_table())
880    }
881}
882
883impl FontWrite for EntryFormatFlags {
884    fn write_into(&self, writer: &mut TableWriter) {
885        writer.write_slice(&self.bits().to_be_bytes())
886    }
887}
888
889#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
890#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
891pub struct DesignSpaceSegment {
892    pub axis_tag: Tag,
893    pub start: Fixed,
894    pub end: Fixed,
895}
896
897impl DesignSpaceSegment {
898    /// Construct a new `DesignSpaceSegment`
899    pub fn new(axis_tag: Tag, start: Fixed, end: Fixed) -> Self {
900        Self {
901            axis_tag,
902            start,
903            end,
904        }
905    }
906}
907
908impl FontWrite for DesignSpaceSegment {
909    fn write_into(&self, writer: &mut TableWriter) {
910        self.axis_tag.write_into(writer);
911        self.start.write_into(writer);
912        self.end.write_into(writer);
913    }
914    fn table_type(&self) -> TableType {
915        TableType::Named("DesignSpaceSegment")
916    }
917}
918
919impl Validate for DesignSpaceSegment {
920    fn validate_impl(&self, _ctx: &mut ValidationCtx) {}
921}
922
923impl FromObjRef<read_fonts::tables::ift::DesignSpaceSegment> for DesignSpaceSegment {
924    fn from_obj_ref(obj: &read_fonts::tables::ift::DesignSpaceSegment, _: FontData) -> Self {
925        DesignSpaceSegment {
926            axis_tag: obj.axis_tag(),
927            start: obj.start(),
928            end: obj.end(),
929        }
930    }
931}
932
933#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
934#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
935pub struct IdStringData {
936    pub id_data: Vec<u8>,
937}
938
939impl IdStringData {
940    /// Construct a new `IdStringData`
941    pub fn new(id_data: Vec<u8>) -> Self {
942        Self { id_data }
943    }
944}
945
946impl FontWrite for IdStringData {
947    fn write_into(&self, writer: &mut TableWriter) {
948        self.id_data.write_into(writer);
949    }
950    fn table_type(&self) -> TableType {
951        TableType::Named("IdStringData")
952    }
953}
954
955impl Validate for IdStringData {
956    fn validate_impl(&self, _ctx: &mut ValidationCtx) {}
957}
958
959impl<'a> FromObjRef<read_fonts::tables::ift::IdStringData<'a>> for IdStringData {
960    fn from_obj_ref(obj: &read_fonts::tables::ift::IdStringData<'a>, _: FontData) -> Self {
961        let offset_data = obj.offset_data();
962        IdStringData {
963            id_data: obj.id_data().to_owned_obj(offset_data),
964        }
965    }
966}
967
968#[allow(clippy::needless_lifetimes)]
969impl<'a> FromTableRef<read_fonts::tables::ift::IdStringData<'a>> for IdStringData {}
970
971impl<'a> FontRead<'a> for IdStringData {
972    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
973        <read_fonts::tables::ift::IdStringData as FontRead>::read(data).map(|x| x.to_owned_table())
974    }
975}
976
977/// [Table Keyed Patch](https://w3c.github.io/IFT/Overview.html#table-keyed)
978#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
979#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
980pub struct TableKeyedPatch {
981    pub format: Tag,
982    /// Unique ID that identifies compatible patches.
983    pub compatibility_id: CompatibilityId,
984    pub patches_count: u16,
985    pub patches: Vec<OffsetMarker<TablePatch, WIDTH_32>>,
986}
987
988impl TableKeyedPatch {
989    /// Construct a new `TableKeyedPatch`
990    pub fn new(
991        format: Tag,
992        compatibility_id: CompatibilityId,
993        patches_count: u16,
994        patches: Vec<TablePatch>,
995    ) -> Self {
996        Self {
997            format,
998            compatibility_id,
999            patches_count,
1000            patches: patches.into_iter().map(Into::into).collect(),
1001        }
1002    }
1003}
1004
1005impl FontWrite for TableKeyedPatch {
1006    #[allow(clippy::unnecessary_cast)]
1007    fn write_into(&self, writer: &mut TableWriter) {
1008        self.format.write_into(writer);
1009        (0 as u32).write_into(writer);
1010        self.compatibility_id.write_into(writer);
1011        self.patches_count.write_into(writer);
1012        self.patches.write_into(writer);
1013    }
1014    fn table_type(&self) -> TableType {
1015        TableType::Named("TableKeyedPatch")
1016    }
1017}
1018
1019impl Validate for TableKeyedPatch {
1020    fn validate_impl(&self, ctx: &mut ValidationCtx) {
1021        ctx.in_table("TableKeyedPatch", |ctx| {
1022            ctx.in_field("patches", |ctx| {
1023                self.patches.validate_impl(ctx);
1024            });
1025        })
1026    }
1027}
1028
1029impl<'a> FromObjRef<read_fonts::tables::ift::TableKeyedPatch<'a>> for TableKeyedPatch {
1030    fn from_obj_ref(obj: &read_fonts::tables::ift::TableKeyedPatch<'a>, _: FontData) -> Self {
1031        TableKeyedPatch {
1032            format: obj.format(),
1033            compatibility_id: obj.compatibility_id(),
1034            patches_count: obj.patches_count(),
1035            patches: obj.patches().to_owned_table(),
1036        }
1037    }
1038}
1039
1040#[allow(clippy::needless_lifetimes)]
1041impl<'a> FromTableRef<read_fonts::tables::ift::TableKeyedPatch<'a>> for TableKeyedPatch {}
1042
1043impl<'a> FontRead<'a> for TableKeyedPatch {
1044    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
1045        <read_fonts::tables::ift::TableKeyedPatch as FontRead>::read(data)
1046            .map(|x| x.to_owned_table())
1047    }
1048}
1049
1050/// [TablePatch](https://w3c.github.io/IFT/Overview.html#tablepatch)
1051#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
1052#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1053pub struct TablePatch {
1054    pub tag: Tag,
1055    pub flags: TablePatchFlags,
1056    pub max_uncompressed_length: u32,
1057    pub brotli_stream: Vec<u8>,
1058}
1059
1060impl TablePatch {
1061    /// Construct a new `TablePatch`
1062    pub fn new(
1063        tag: Tag,
1064        flags: TablePatchFlags,
1065        max_uncompressed_length: u32,
1066        brotli_stream: Vec<u8>,
1067    ) -> Self {
1068        Self {
1069            tag,
1070            flags,
1071            max_uncompressed_length,
1072            brotli_stream,
1073        }
1074    }
1075}
1076
1077impl FontWrite for TablePatch {
1078    fn write_into(&self, writer: &mut TableWriter) {
1079        self.tag.write_into(writer);
1080        self.flags.write_into(writer);
1081        self.max_uncompressed_length.write_into(writer);
1082        self.brotli_stream.write_into(writer);
1083    }
1084    fn table_type(&self) -> TableType {
1085        TableType::Named("TablePatch")
1086    }
1087}
1088
1089impl Validate for TablePatch {
1090    fn validate_impl(&self, _ctx: &mut ValidationCtx) {}
1091}
1092
1093impl<'a> FromObjRef<read_fonts::tables::ift::TablePatch<'a>> for TablePatch {
1094    fn from_obj_ref(obj: &read_fonts::tables::ift::TablePatch<'a>, _: FontData) -> Self {
1095        let offset_data = obj.offset_data();
1096        TablePatch {
1097            tag: obj.tag(),
1098            flags: obj.flags(),
1099            max_uncompressed_length: obj.max_uncompressed_length(),
1100            brotli_stream: obj.brotli_stream().to_owned_obj(offset_data),
1101        }
1102    }
1103}
1104
1105#[allow(clippy::needless_lifetimes)]
1106impl<'a> FromTableRef<read_fonts::tables::ift::TablePatch<'a>> for TablePatch {}
1107
1108impl<'a> FontRead<'a> for TablePatch {
1109    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
1110        <read_fonts::tables::ift::TablePatch as FontRead>::read(data).map(|x| x.to_owned_table())
1111    }
1112}
1113
1114impl FontWrite for TablePatchFlags {
1115    fn write_into(&self, writer: &mut TableWriter) {
1116        writer.write_slice(&self.bits().to_be_bytes())
1117    }
1118}
1119
1120/// [Glyph Keyed Patch](https://w3c.github.io/IFT/Overview.html#glyph-keyed)
1121#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
1122#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1123pub struct GlyphKeyedPatch {
1124    pub format: Tag,
1125    pub flags: GlyphKeyedFlags,
1126    pub compatibility_id: CompatibilityId,
1127    pub max_uncompressed_length: u32,
1128    pub brotli_stream: Vec<u8>,
1129}
1130
1131impl GlyphKeyedPatch {
1132    /// Construct a new `GlyphKeyedPatch`
1133    pub fn new(
1134        format: Tag,
1135        flags: GlyphKeyedFlags,
1136        compatibility_id: CompatibilityId,
1137        max_uncompressed_length: u32,
1138        brotli_stream: Vec<u8>,
1139    ) -> Self {
1140        Self {
1141            format,
1142            flags,
1143            compatibility_id,
1144            max_uncompressed_length,
1145            brotli_stream,
1146        }
1147    }
1148}
1149
1150impl FontWrite for GlyphKeyedPatch {
1151    #[allow(clippy::unnecessary_cast)]
1152    fn write_into(&self, writer: &mut TableWriter) {
1153        self.format.write_into(writer);
1154        (0 as u32).write_into(writer);
1155        self.flags.write_into(writer);
1156        self.compatibility_id.write_into(writer);
1157        self.max_uncompressed_length.write_into(writer);
1158        self.brotli_stream.write_into(writer);
1159    }
1160    fn table_type(&self) -> TableType {
1161        TableType::Named("GlyphKeyedPatch")
1162    }
1163}
1164
1165impl Validate for GlyphKeyedPatch {
1166    fn validate_impl(&self, _ctx: &mut ValidationCtx) {}
1167}
1168
1169impl<'a> FromObjRef<read_fonts::tables::ift::GlyphKeyedPatch<'a>> for GlyphKeyedPatch {
1170    fn from_obj_ref(obj: &read_fonts::tables::ift::GlyphKeyedPatch<'a>, _: FontData) -> Self {
1171        let offset_data = obj.offset_data();
1172        GlyphKeyedPatch {
1173            format: obj.format(),
1174            flags: obj.flags(),
1175            compatibility_id: obj.compatibility_id(),
1176            max_uncompressed_length: obj.max_uncompressed_length(),
1177            brotli_stream: obj.brotli_stream().to_owned_obj(offset_data),
1178        }
1179    }
1180}
1181
1182#[allow(clippy::needless_lifetimes)]
1183impl<'a> FromTableRef<read_fonts::tables::ift::GlyphKeyedPatch<'a>> for GlyphKeyedPatch {}
1184
1185impl<'a> FontRead<'a> for GlyphKeyedPatch {
1186    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
1187        <read_fonts::tables::ift::GlyphKeyedPatch as FontRead>::read(data)
1188            .map(|x| x.to_owned_table())
1189    }
1190}
1191
1192impl FontWrite for GlyphKeyedFlags {
1193    fn write_into(&self, writer: &mut TableWriter) {
1194        writer.write_slice(&self.bits().to_be_bytes())
1195    }
1196}
1197
1198/// [GlyphPatches](https://w3c.github.io/IFT/Overview.html#glyphpatches)
1199#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
1200#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1201pub struct GlyphPatches {
1202    pub glyph_count: u32,
1203    pub table_count: u8,
1204    pub tables: Vec<Tag>,
1205    pub glyph_data: Vec<OffsetMarker<GlyphData, WIDTH_32>>,
1206}
1207
1208impl GlyphPatches {
1209    /// Construct a new `GlyphPatches`
1210    pub fn new(
1211        glyph_count: u32,
1212        table_count: u8,
1213        tables: Vec<Tag>,
1214        glyph_data: Vec<GlyphData>,
1215    ) -> Self {
1216        Self {
1217            glyph_count,
1218            table_count,
1219            tables,
1220            glyph_data: glyph_data.into_iter().map(Into::into).collect(),
1221        }
1222    }
1223}
1224
1225impl FontWrite for GlyphPatches {
1226    #[allow(clippy::unnecessary_cast)]
1227    fn write_into(&self, writer: &mut TableWriter) {
1228        self.glyph_count.write_into(writer);
1229        self.table_count.write_into(writer);
1230        self.tables.write_into(writer);
1231        self.glyph_data.write_into(writer);
1232    }
1233    fn table_type(&self) -> TableType {
1234        TableType::Named("GlyphPatches")
1235    }
1236}
1237
1238impl Validate for GlyphPatches {
1239    fn validate_impl(&self, ctx: &mut ValidationCtx) {
1240        ctx.in_table("GlyphPatches", |ctx| {
1241            ctx.in_field("tables", |ctx| {
1242                if self.tables.len() > (u8::MAX as usize) {
1243                    ctx.report("array exceeds max length");
1244                }
1245            });
1246            ctx.in_field("glyph_data", |ctx| {
1247                self.glyph_data.validate_impl(ctx);
1248            });
1249        })
1250    }
1251}
1252
1253impl<'a> FromObjRef<read_fonts::tables::ift::GlyphPatches<'a>> for GlyphPatches {
1254    fn from_obj_ref(obj: &read_fonts::tables::ift::GlyphPatches<'a>, _: FontData) -> Self {
1255        let offset_data = obj.offset_data();
1256        GlyphPatches {
1257            glyph_count: obj.glyph_count(),
1258            table_count: obj.table_count(),
1259            tables: obj.tables().to_owned_obj(offset_data),
1260            glyph_data: obj.glyph_data().to_owned_table(),
1261        }
1262    }
1263}
1264
1265#[allow(clippy::needless_lifetimes)]
1266impl<'a> FromTableRef<read_fonts::tables::ift::GlyphPatches<'a>> for GlyphPatches {}
1267
1268#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
1269#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1270pub struct GlyphData {
1271    pub data: Vec<u8>,
1272}
1273
1274impl GlyphData {
1275    /// Construct a new `GlyphData`
1276    pub fn new(data: Vec<u8>) -> Self {
1277        Self { data }
1278    }
1279}
1280
1281impl FontWrite for GlyphData {
1282    fn write_into(&self, writer: &mut TableWriter) {
1283        self.data.write_into(writer);
1284    }
1285    fn table_type(&self) -> TableType {
1286        TableType::Named("GlyphData")
1287    }
1288}
1289
1290impl Validate for GlyphData {
1291    fn validate_impl(&self, _ctx: &mut ValidationCtx) {}
1292}
1293
1294impl<'a> FromObjRef<read_fonts::tables::ift::GlyphData<'a>> for GlyphData {
1295    fn from_obj_ref(obj: &read_fonts::tables::ift::GlyphData<'a>, _: FontData) -> Self {
1296        let offset_data = obj.offset_data();
1297        GlyphData {
1298            data: obj.data().to_owned_obj(offset_data),
1299        }
1300    }
1301}
1302
1303#[allow(clippy::needless_lifetimes)]
1304impl<'a> FromTableRef<read_fonts::tables::ift::GlyphData<'a>> for GlyphData {}
1305
1306impl<'a> FontRead<'a> for GlyphData {
1307    fn read(data: FontData<'a>) -> Result<Self, ReadError> {
1308        <read_fonts::tables::ift::GlyphData as FontRead>::read(data).map(|x| x.to_owned_table())
1309    }
1310}