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