Coverage Report

Created: 2026-07-25 07:50

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/fontations/read-fonts/generated/generated_ift.rs
Line
Count
Source
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)]
6
use crate::codegen_prelude::*;
7
8
#[derive(Clone)]
9
pub enum Ift<'a> {
10
    Format1(PatchMapFormat1<'a>),
11
    Format2(PatchMapFormat2<'a>),
12
}
13
14
impl Default for Ift<'_> {
15
    fn default() -> Self {
16
        Self::Format1(Default::default())
17
    }
18
}
19
20
impl<'a> Ift<'a> {
21
    ///Return the `FontData` used to resolve offsets for this table.
22
    pub fn offset_data(&self) -> FontData<'a> {
23
        match self {
24
            Self::Format1(item) => item.offset_data(),
25
            Self::Format2(item) => item.offset_data(),
26
        }
27
    }
28
29
    /// Format identifier: format = 1
30
    pub fn format(&self) -> u8 {
31
        match self {
32
            Self::Format1(item) => item.format(),
33
            Self::Format2(item) => item.format(),
34
        }
35
    }
36
37
    pub fn field_flags(&self) -> PatchMapFieldPresenceFlags {
38
        match self {
39
            Self::Format1(item) => item.field_flags(),
40
            Self::Format2(item) => item.field_flags(),
41
        }
42
    }
43
44
    /// Unique ID that identifies compatible patches.
45
    pub fn compatibility_id(&self) -> CompatibilityId {
46
        match self {
47
            Self::Format1(item) => item.compatibility_id(),
48
            Self::Format2(item) => item.compatibility_id(),
49
        }
50
    }
51
52
    pub fn url_template_length(&self) -> u16 {
53
        match self {
54
            Self::Format1(item) => item.url_template_length(),
55
            Self::Format2(item) => item.url_template_length(),
56
        }
57
    }
58
59
    pub fn url_template(&self) -> &'a [u8] {
60
        match self {
61
            Self::Format1(item) => item.url_template(),
62
            Self::Format2(item) => item.url_template(),
63
        }
64
    }
65
66
    pub fn cff_charstrings_offset(&self) -> Option<u32> {
67
        match self {
68
            Self::Format1(item) => item.cff_charstrings_offset(),
69
            Self::Format2(item) => item.cff_charstrings_offset(),
70
        }
71
    }
72
73
    pub fn cff2_charstrings_offset(&self) -> Option<u32> {
74
        match self {
75
            Self::Format1(item) => item.cff2_charstrings_offset(),
76
            Self::Format2(item) => item.cff2_charstrings_offset(),
77
        }
78
    }
79
}
80
81
impl ReadArgs for Ift<'_> {
82
    type Args = ();
83
}
84
85
impl<'a> FontRead<'a> for Ift<'a> {
86
    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
87
        let format: u8 = data.read_at(0usize)?;
88
        match format {
89
            PatchMapFormat1::FORMAT => Ok(Self::Format1(FontRead::read(data)?)),
90
            PatchMapFormat2::FORMAT => Ok(Self::Format2(FontRead::read(data)?)),
91
            other => Err(ReadError::InvalidFormat(other.into())),
92
        }
93
    }
94
}
95
96
impl<'a> MinByteRange<'a> for Ift<'a> {
97
    fn min_byte_range(&self) -> Range<usize> {
98
        match self {
99
            Self::Format1(item) => item.min_byte_range(),
100
            Self::Format2(item) => item.min_byte_range(),
101
        }
102
    }
103
    fn min_table_bytes(&self) -> &'a [u8] {
104
        match self {
105
            Self::Format1(item) => item.min_table_bytes(),
106
            Self::Format2(item) => item.min_table_bytes(),
107
        }
108
    }
109
}
110
111
#[cfg(feature = "experimental_traverse")]
112
impl<'a> Ift<'a> {
113
    fn dyn_inner<'b>(&'b self) -> &'b dyn SomeTable<'a> {
114
        match self {
115
            Self::Format1(table) => table,
116
            Self::Format2(table) => table,
117
        }
118
    }
119
}
120
121
#[cfg(feature = "experimental_traverse")]
122
impl std::fmt::Debug for Ift<'_> {
123
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
124
        self.dyn_inner().fmt(f)
125
    }
126
}
127
128
#[cfg(feature = "experimental_traverse")]
129
impl<'a> SomeTable<'a> for Ift<'a> {
130
    fn type_name(&self) -> &str {
131
        self.dyn_inner().type_name()
132
    }
133
    fn get_field(&self, idx: usize) -> Option<Field<'a>> {
134
        self.dyn_inner().get_field(idx)
135
    }
136
}
137
138
#[derive(Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash, bytemuck :: AnyBitPattern)]
139
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
140
#[repr(transparent)]
141
pub struct PatchMapFieldPresenceFlags {
142
    bits: u8,
143
}
144
145
impl PatchMapFieldPresenceFlags {
146
    pub const CFF_CHARSTRINGS_OFFSET: Self = Self { bits: 0b00000001 };
147
148
    pub const CFF2_CHARSTRINGS_OFFSET: Self = Self { bits: 0b00000010 };
149
}
150
151
impl PatchMapFieldPresenceFlags {
152
    ///  Returns an empty set of flags.
153
    #[inline]
154
    pub const fn empty() -> Self {
155
        Self { bits: 0 }
156
    }
157
158
    /// Returns the set containing all flags.
159
    #[inline]
160
    pub const fn all() -> Self {
161
        Self {
162
            bits: Self::CFF_CHARSTRINGS_OFFSET.bits | Self::CFF2_CHARSTRINGS_OFFSET.bits,
163
        }
164
    }
165
166
    /// Returns the raw value of the flags currently stored.
167
    #[inline]
168
0
    pub const fn bits(&self) -> u8 {
169
0
        self.bits
170
0
    }
171
172
    /// Convert from underlying bit representation, unless that
173
    /// representation contains bits that do not correspond to a flag.
174
    #[inline]
175
    pub const fn from_bits(bits: u8) -> Option<Self> {
176
        if (bits & !Self::all().bits()) == 0 {
177
            Some(Self { bits })
178
        } else {
179
            None
180
        }
181
    }
182
183
    /// Convert from underlying bit representation, dropping any bits
184
    /// that do not correspond to flags.
185
    #[inline]
186
    pub const fn from_bits_truncate(bits: u8) -> Self {
187
        Self {
188
            bits: bits & Self::all().bits,
189
        }
190
    }
191
192
    /// Returns `true` if no flags are currently stored.
193
    #[inline]
194
    pub const fn is_empty(&self) -> bool {
195
        self.bits() == Self::empty().bits()
196
    }
197
198
    /// Returns `true` if there are flags common to both `self` and `other`.
199
    #[inline]
200
    pub const fn intersects(&self, other: Self) -> bool {
201
        !(Self {
202
            bits: self.bits & other.bits,
203
        })
204
        .is_empty()
205
    }
206
207
    /// Returns `true` if all of the flags in `other` are contained within `self`.
208
    #[inline]
209
0
    pub const fn contains(&self, other: Self) -> bool {
210
0
        (self.bits & other.bits) == other.bits
211
0
    }
212
213
    /// Inserts the specified flags in-place.
214
    #[inline]
215
    pub fn insert(&mut self, other: Self) {
216
        self.bits |= other.bits;
217
    }
218
219
    /// Removes the specified flags in-place.
220
    #[inline]
221
    pub fn remove(&mut self, other: Self) {
222
        self.bits &= !other.bits;
223
    }
224
225
    /// Toggles the specified flags in-place.
226
    #[inline]
227
    pub fn toggle(&mut self, other: Self) {
228
        self.bits ^= other.bits;
229
    }
230
231
    /// Returns the intersection between the flags in `self` and
232
    /// `other`.
233
    ///
234
    /// Specifically, the returned set contains only the flags which are
235
    /// present in *both* `self` *and* `other`.
236
    ///
237
    /// This is equivalent to using the `&` operator (e.g.
238
    /// [`ops::BitAnd`]), as in `flags & other`.
239
    ///
240
    /// [`ops::BitAnd`]: https://doc.rust-lang.org/std/ops/trait.BitAnd.html
241
    #[inline]
242
    #[must_use]
243
    pub const fn intersection(self, other: Self) -> Self {
244
        Self {
245
            bits: self.bits & other.bits,
246
        }
247
    }
248
249
    /// Returns the union of between the flags in `self` and `other`.
250
    ///
251
    /// Specifically, the returned set contains all flags which are
252
    /// present in *either* `self` *or* `other`, including any which are
253
    /// present in both.
254
    ///
255
    /// This is equivalent to using the `|` operator (e.g.
256
    /// [`ops::BitOr`]), as in `flags | other`.
257
    ///
258
    /// [`ops::BitOr`]: https://doc.rust-lang.org/std/ops/trait.BitOr.html
259
    #[inline]
260
    #[must_use]
261
    pub const fn union(self, other: Self) -> Self {
262
        Self {
263
            bits: self.bits | other.bits,
264
        }
265
    }
266
267
    /// Returns the difference between the flags in `self` and `other`.
268
    ///
269
    /// Specifically, the returned set contains all flags present in
270
    /// `self`, except for the ones present in `other`.
271
    ///
272
    /// It is also conceptually equivalent to the "bit-clear" operation:
273
    /// `flags & !other` (and this syntax is also supported).
274
    ///
275
    /// This is equivalent to using the `-` operator (e.g.
276
    /// [`ops::Sub`]), as in `flags - other`.
277
    ///
278
    /// [`ops::Sub`]: https://doc.rust-lang.org/std/ops/trait.Sub.html
279
    #[inline]
280
    #[must_use]
281
    pub const fn difference(self, other: Self) -> Self {
282
        Self {
283
            bits: self.bits & !other.bits,
284
        }
285
    }
286
}
287
288
impl std::ops::BitOr for PatchMapFieldPresenceFlags {
289
    type Output = Self;
290
291
    /// Returns the union of the two sets of flags.
292
    #[inline]
293
    fn bitor(self, other: PatchMapFieldPresenceFlags) -> Self {
294
        Self {
295
            bits: self.bits | other.bits,
296
        }
297
    }
298
}
299
300
impl std::ops::BitOrAssign for PatchMapFieldPresenceFlags {
301
    /// Adds the set of flags.
302
    #[inline]
303
    fn bitor_assign(&mut self, other: Self) {
304
        self.bits |= other.bits;
305
    }
306
}
307
308
impl std::ops::BitXor for PatchMapFieldPresenceFlags {
309
    type Output = Self;
310
311
    /// Returns the left flags, but with all the right flags toggled.
312
    #[inline]
313
    fn bitxor(self, other: Self) -> Self {
314
        Self {
315
            bits: self.bits ^ other.bits,
316
        }
317
    }
318
}
319
320
impl std::ops::BitXorAssign for PatchMapFieldPresenceFlags {
321
    /// Toggles the set of flags.
322
    #[inline]
323
    fn bitxor_assign(&mut self, other: Self) {
324
        self.bits ^= other.bits;
325
    }
326
}
327
328
impl std::ops::BitAnd for PatchMapFieldPresenceFlags {
329
    type Output = Self;
330
331
    /// Returns the intersection between the two sets of flags.
332
    #[inline]
333
    fn bitand(self, other: Self) -> Self {
334
        Self {
335
            bits: self.bits & other.bits,
336
        }
337
    }
338
}
339
340
impl std::ops::BitAndAssign for PatchMapFieldPresenceFlags {
341
    /// Disables all flags disabled in the set.
342
    #[inline]
343
    fn bitand_assign(&mut self, other: Self) {
344
        self.bits &= other.bits;
345
    }
346
}
347
348
impl std::ops::Sub for PatchMapFieldPresenceFlags {
349
    type Output = Self;
350
351
    /// Returns the set difference of the two sets of flags.
352
    #[inline]
353
    fn sub(self, other: Self) -> Self {
354
        Self {
355
            bits: self.bits & !other.bits,
356
        }
357
    }
358
}
359
360
impl std::ops::SubAssign for PatchMapFieldPresenceFlags {
361
    /// Disables all flags enabled in the set.
362
    #[inline]
363
    fn sub_assign(&mut self, other: Self) {
364
        self.bits &= !other.bits;
365
    }
366
}
367
368
impl std::ops::Not for PatchMapFieldPresenceFlags {
369
    type Output = Self;
370
371
    /// Returns the complement of this set of flags.
372
    #[inline]
373
    fn not(self) -> Self {
374
        Self { bits: !self.bits } & Self::all()
375
    }
376
}
377
378
impl std::fmt::Debug for PatchMapFieldPresenceFlags {
379
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
380
        let members: &[(&str, Self)] = &[
381
            ("CFF_CHARSTRINGS_OFFSET", Self::CFF_CHARSTRINGS_OFFSET),
382
            ("CFF2_CHARSTRINGS_OFFSET", Self::CFF2_CHARSTRINGS_OFFSET),
383
        ];
384
        let mut first = true;
385
        for (name, value) in members {
386
            if self.contains(*value) {
387
                if !first {
388
                    f.write_str(" | ")?;
389
                }
390
                first = false;
391
                f.write_str(name)?;
392
            }
393
        }
394
        if first {
395
            f.write_str("(empty)")?;
396
        }
397
        Ok(())
398
    }
399
}
400
401
impl std::fmt::Binary for PatchMapFieldPresenceFlags {
402
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
403
        std::fmt::Binary::fmt(&self.bits, f)
404
    }
405
}
406
407
impl std::fmt::Octal for PatchMapFieldPresenceFlags {
408
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
409
        std::fmt::Octal::fmt(&self.bits, f)
410
    }
411
}
412
413
impl std::fmt::LowerHex for PatchMapFieldPresenceFlags {
414
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
415
        std::fmt::LowerHex::fmt(&self.bits, f)
416
    }
417
}
418
419
impl std::fmt::UpperHex for PatchMapFieldPresenceFlags {
420
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
421
        std::fmt::UpperHex::fmt(&self.bits, f)
422
    }
423
}
424
425
impl font_types::Scalar for PatchMapFieldPresenceFlags {
426
    type Raw = <u8 as font_types::Scalar>::Raw;
427
    fn to_raw(self) -> Self::Raw {
428
        self.bits().to_raw()
429
    }
430
    fn from_raw(raw: Self::Raw) -> Self {
431
        let t = <u8>::from_raw(raw);
432
        Self::from_bits_truncate(t)
433
    }
434
}
435
436
#[cfg(feature = "experimental_traverse")]
437
impl<'a> From<PatchMapFieldPresenceFlags> for FieldType<'a> {
438
    fn from(src: PatchMapFieldPresenceFlags) -> FieldType<'a> {
439
        src.bits().into()
440
    }
441
}
442
443
impl Format<u8> for PatchMapFormat1<'_> {
444
    const FORMAT: u8 = 1;
445
}
446
447
impl<'a> MinByteRange<'a> for PatchMapFormat1<'a> {
448
    fn min_byte_range(&self) -> Range<usize> {
449
        0..self.patch_format_byte_range().end
450
    }
451
    fn min_table_bytes(&self) -> &'a [u8] {
452
        let range = self.min_byte_range();
453
        self.data.as_bytes().get(range).unwrap_or_default()
454
    }
455
}
456
457
impl ReadArgs for PatchMapFormat1<'_> {
458
    type Args = ();
459
}
460
461
impl<'a> FontRead<'a> for PatchMapFormat1<'a> {
462
    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
463
        #[allow(clippy::absurd_extreme_comparisons)]
464
        if data.len() < Self::MIN_SIZE {
465
            return Err(ReadError::OutOfBounds);
466
        }
467
        Ok(Self { data })
468
    }
469
}
470
471
/// [Patch Map Format Format 1](https://w3c.github.io/IFT/Overview.html#patch-map-format-1)
472
#[derive(Clone)]
473
pub struct PatchMapFormat1<'a> {
474
    data: FontData<'a>,
475
}
476
477
#[allow(clippy::needless_lifetimes)]
478
impl<'a> PatchMapFormat1<'a> {
479
    pub const MIN_SIZE: usize = (u8::RAW_BYTE_LEN
480
        + u8::RAW_BYTE_LEN
481
        + u8::RAW_BYTE_LEN
482
        + u8::RAW_BYTE_LEN
483
        + PatchMapFieldPresenceFlags::RAW_BYTE_LEN
484
        + CompatibilityId::RAW_BYTE_LEN
485
        + u16::RAW_BYTE_LEN
486
        + u16::RAW_BYTE_LEN
487
        + Uint24::RAW_BYTE_LEN
488
        + Offset32::RAW_BYTE_LEN
489
        + Offset32::RAW_BYTE_LEN
490
        + u16::RAW_BYTE_LEN
491
        + u8::RAW_BYTE_LEN);
492
    basic_table_impls!(impl_the_methods);
493
494
    /// Format identifier: format = 1
495
    pub fn format(&self) -> u8 {
496
        let range = self.format_byte_range();
497
        self.data.read_at(range.start).ok().unwrap()
498
    }
499
500
    pub fn field_flags(&self) -> PatchMapFieldPresenceFlags {
501
        let range = self.field_flags_byte_range();
502
        self.data.read_at(range.start).ok().unwrap()
503
    }
504
505
    /// Unique ID that identifies compatible patches.
506
    pub fn compatibility_id(&self) -> CompatibilityId {
507
        let range = self.compatibility_id_byte_range();
508
        self.data.read_at(range.start).ok().unwrap()
509
    }
510
511
    /// Largest entry index which appears in either the glyph map or feature map.
512
    pub fn max_entry_index(&self) -> u16 {
513
        let range = self.max_entry_index_byte_range();
514
        self.data.read_at(range.start).ok().unwrap()
515
    }
516
517
    /// Largest entry index which appears in the glyph map.
518
    pub fn max_glyph_map_entry_index(&self) -> u16 {
519
        let range = self.max_glyph_map_entry_index_byte_range();
520
        self.data.read_at(range.start).ok().unwrap()
521
    }
522
523
    pub fn glyph_count(&self) -> Uint24 {
524
        let range = self.glyph_count_byte_range();
525
        self.data.read_at(range.start).ok().unwrap()
526
    }
527
528
    /// Sub table that maps glyph ids to entry indices.
529
    pub fn glyph_map_offset(&self) -> Offset32 {
530
        let range = self.glyph_map_offset_byte_range();
531
        self.data.read_at(range.start).ok().unwrap()
532
    }
533
534
    /// Attempt to resolve [`glyph_map_offset`][Self::glyph_map_offset].
535
    pub fn glyph_map(&self) -> Result<GlyphMap<'a>, ReadError> {
536
        let data = self.data;
537
        let args = (self.glyph_count(), self.max_entry_index());
538
        self.glyph_map_offset().resolve_with_args(data, args)
539
    }
540
541
    /// Sub table that maps feature and glyph ids to entry indices.
542
    pub fn feature_map_offset(&self) -> Nullable<Offset32> {
543
        let range = self.feature_map_offset_byte_range();
544
        self.data.read_at(range.start).ok().unwrap()
545
    }
546
547
    /// Attempt to resolve [`feature_map_offset`][Self::feature_map_offset].
548
    pub fn feature_map(&self) -> Option<Result<FeatureMap<'a>, ReadError>> {
549
        let data = self.data;
550
        let args = self.max_entry_index();
551
        self.feature_map_offset().resolve_with_args(data, args)
552
    }
553
554
    pub fn applied_entries_bitmap(&self) -> &'a [u8] {
555
        let range = self.applied_entries_bitmap_byte_range();
556
        self.data.read_array(range).ok().unwrap_or_default()
557
    }
558
559
    pub fn url_template_length(&self) -> u16 {
560
        let range = self.url_template_length_byte_range();
561
        self.data.read_at(range.start).ok().unwrap_or_default()
562
    }
563
564
    pub fn url_template(&self) -> &'a [u8] {
565
        let range = self.url_template_byte_range();
566
        self.data.read_array(range).ok().unwrap_or_default()
567
    }
568
569
    /// Patch format number for patches referenced by this mapping.
570
    pub fn patch_format(&self) -> u8 {
571
        let range = self.patch_format_byte_range();
572
        self.data.read_at(range.start).ok().unwrap_or_default()
573
    }
574
575
    pub fn cff_charstrings_offset(&self) -> Option<u32> {
576
        let range = self.cff_charstrings_offset_byte_range();
577
        (!range.is_empty())
578
            .then(|| self.data.read_at(range.start).ok())
579
            .flatten()
580
    }
581
582
    pub fn cff2_charstrings_offset(&self) -> Option<u32> {
583
        let range = self.cff2_charstrings_offset_byte_range();
584
        (!range.is_empty())
585
            .then(|| self.data.read_at(range.start).ok())
586
            .flatten()
587
    }
588
589
    pub fn format_byte_range(&self) -> Range<usize> {
590
        let start = 0;
591
        let end = start + u8::RAW_BYTE_LEN;
592
        start..end
593
    }
594
595
    pub fn _reserved_0_byte_range(&self) -> Range<usize> {
596
        let start = self.format_byte_range().end;
597
        let end = start + u8::RAW_BYTE_LEN;
598
        start..end
599
    }
600
601
    pub fn _reserved_1_byte_range(&self) -> Range<usize> {
602
        let start = self._reserved_0_byte_range().end;
603
        let end = start + u8::RAW_BYTE_LEN;
604
        start..end
605
    }
606
607
    pub fn _reserved_2_byte_range(&self) -> Range<usize> {
608
        let start = self._reserved_1_byte_range().end;
609
        let end = start + u8::RAW_BYTE_LEN;
610
        start..end
611
    }
612
613
    pub fn field_flags_byte_range(&self) -> Range<usize> {
614
        let start = self._reserved_2_byte_range().end;
615
        let end = start + PatchMapFieldPresenceFlags::RAW_BYTE_LEN;
616
        start..end
617
    }
618
619
    pub fn compatibility_id_byte_range(&self) -> Range<usize> {
620
        let start = self.field_flags_byte_range().end;
621
        let end = start + CompatibilityId::RAW_BYTE_LEN;
622
        start..end
623
    }
624
625
    pub fn max_entry_index_byte_range(&self) -> Range<usize> {
626
        let start = self.compatibility_id_byte_range().end;
627
        let end = start + u16::RAW_BYTE_LEN;
628
        start..end
629
    }
630
631
    pub fn max_glyph_map_entry_index_byte_range(&self) -> Range<usize> {
632
        let start = self.max_entry_index_byte_range().end;
633
        let end = start + u16::RAW_BYTE_LEN;
634
        start..end
635
    }
636
637
    pub fn glyph_count_byte_range(&self) -> Range<usize> {
638
        let start = self.max_glyph_map_entry_index_byte_range().end;
639
        let end = start + Uint24::RAW_BYTE_LEN;
640
        start..end
641
    }
642
643
    pub fn glyph_map_offset_byte_range(&self) -> Range<usize> {
644
        let start = self.glyph_count_byte_range().end;
645
        let end = start + Offset32::RAW_BYTE_LEN;
646
        start..end
647
    }
648
649
    pub fn feature_map_offset_byte_range(&self) -> Range<usize> {
650
        let start = self.glyph_map_offset_byte_range().end;
651
        let end = start + Offset32::RAW_BYTE_LEN;
652
        start..end
653
    }
654
655
    pub fn applied_entries_bitmap_byte_range(&self) -> Range<usize> {
656
        let max_entry_index = self.max_entry_index();
657
        let start = self.feature_map_offset_byte_range().end;
658
        let end = start
659
            + (transforms::max_value_bitmap_len(max_entry_index)).saturating_mul(u8::RAW_BYTE_LEN);
660
        start..end
661
    }
662
663
    pub fn url_template_length_byte_range(&self) -> Range<usize> {
664
        let start = self.applied_entries_bitmap_byte_range().end;
665
        let end = start + u16::RAW_BYTE_LEN;
666
        start..end
667
    }
668
669
    pub fn url_template_byte_range(&self) -> Range<usize> {
670
        let url_template_length = self.url_template_length();
671
        let start = self.url_template_length_byte_range().end;
672
        let end =
673
            start + (transforms::to_usize(url_template_length)).saturating_mul(u8::RAW_BYTE_LEN);
674
        start..end
675
    }
676
677
    pub fn patch_format_byte_range(&self) -> Range<usize> {
678
        let start = self.url_template_byte_range().end;
679
        let end = start + u8::RAW_BYTE_LEN;
680
        start..end
681
    }
682
683
    pub fn cff_charstrings_offset_byte_range(&self) -> Range<usize> {
684
        let start = self.patch_format_byte_range().end;
685
        let end = if self
686
            .field_flags()
687
            .contains(PatchMapFieldPresenceFlags::CFF_CHARSTRINGS_OFFSET)
688
        {
689
            start + u32::RAW_BYTE_LEN
690
        } else {
691
            start
692
        };
693
        start..end
694
    }
695
696
    pub fn cff2_charstrings_offset_byte_range(&self) -> Range<usize> {
697
        let start = self.cff_charstrings_offset_byte_range().end;
698
        let end = if self
699
            .field_flags()
700
            .contains(PatchMapFieldPresenceFlags::CFF2_CHARSTRINGS_OFFSET)
701
        {
702
            start + u32::RAW_BYTE_LEN
703
        } else {
704
            start
705
        };
706
        start..end
707
    }
708
}
709
710
const _: () = assert!(FontData::default_data_long_enough(
711
    PatchMapFormat1::MIN_SIZE
712
));
713
714
impl Default for PatchMapFormat1<'_> {
715
    fn default() -> Self {
716
        Self {
717
            data: FontData::default_format_1_u8_table_data(),
718
        }
719
    }
720
}
721
722
#[cfg(feature = "experimental_traverse")]
723
impl<'a> SomeTable<'a> for PatchMapFormat1<'a> {
724
    fn type_name(&self) -> &str {
725
        "PatchMapFormat1"
726
    }
727
    fn get_field(&self, idx: usize) -> Option<Field<'a>> {
728
        match idx {
729
            0usize => Some(Field::new("format", self.format())),
730
            1usize => Some(Field::new("field_flags", self.field_flags())),
731
            2usize => Some(Field::new(
732
                "compatibility_id",
733
                traversal::FieldType::Unknown,
734
            )),
735
            3usize => Some(Field::new("max_entry_index", self.max_entry_index())),
736
            4usize => Some(Field::new(
737
                "max_glyph_map_entry_index",
738
                self.max_glyph_map_entry_index(),
739
            )),
740
            5usize => Some(Field::new("glyph_count", self.glyph_count())),
741
            6usize => Some(Field::new(
742
                "glyph_map_offset",
743
                FieldType::offset(self.glyph_map_offset(), self.glyph_map()),
744
            )),
745
            7usize => Some(Field::new(
746
                "feature_map_offset",
747
                FieldType::offset(self.feature_map_offset(), self.feature_map()),
748
            )),
749
            8usize => Some(Field::new(
750
                "applied_entries_bitmap",
751
                self.applied_entries_bitmap(),
752
            )),
753
            9usize => Some(Field::new(
754
                "url_template_length",
755
                self.url_template_length(),
756
            )),
757
            10usize => Some(Field::new("url_template", self.url_template())),
758
            11usize => Some(Field::new("patch_format", self.patch_format())),
759
            12usize
760
                if self
761
                    .field_flags()
762
                    .contains(PatchMapFieldPresenceFlags::CFF_CHARSTRINGS_OFFSET) =>
763
            {
764
                Some(Field::new(
765
                    "cff_charstrings_offset",
766
                    self.cff_charstrings_offset().unwrap(),
767
                ))
768
            }
769
            13usize
770
                if self
771
                    .field_flags()
772
                    .contains(PatchMapFieldPresenceFlags::CFF2_CHARSTRINGS_OFFSET) =>
773
            {
774
                Some(Field::new(
775
                    "cff2_charstrings_offset",
776
                    self.cff2_charstrings_offset().unwrap(),
777
                ))
778
            }
779
            _ => None,
780
        }
781
    }
782
}
783
784
#[cfg(feature = "experimental_traverse")]
785
#[allow(clippy::needless_lifetimes)]
786
impl<'a> std::fmt::Debug for PatchMapFormat1<'a> {
787
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
788
        (self as &dyn SomeTable<'a>).fmt(f)
789
    }
790
}
791
792
impl<'a> MinByteRange<'a> for GlyphMap<'a> {
793
    fn min_byte_range(&self) -> Range<usize> {
794
        0..self.entry_index_byte_range().end
795
    }
796
    fn min_table_bytes(&self) -> &'a [u8] {
797
        let range = self.min_byte_range();
798
        self.data.as_bytes().get(range).unwrap_or_default()
799
    }
800
}
801
802
impl ReadArgs for GlyphMap<'_> {
803
    type Args = (Uint24, u16);
804
}
805
806
impl<'a> FontRead<'a> for GlyphMap<'a> {
807
    fn read_with_args(data: FontData<'a>, args: (Uint24, u16)) -> Result<Self, ReadError> {
808
        let (glyph_count, max_entry_index) = args;
809
810
        #[allow(clippy::absurd_extreme_comparisons)]
811
        if data.len() < Self::MIN_SIZE {
812
            return Err(ReadError::OutOfBounds);
813
        }
814
        Ok(Self {
815
            data,
816
            glyph_count,
817
            max_entry_index,
818
        })
819
    }
820
}
821
822
impl<'a> GlyphMap<'a> {
823
    /// A constructor that requires additional arguments.
824
    ///
825
    /// This type requires some external state in order to be
826
    /// parsed.
827
    pub fn read(
828
        data: FontData<'a>,
829
        glyph_count: Uint24,
830
        max_entry_index: u16,
831
    ) -> Result<Self, ReadError> {
832
        let args = (glyph_count, max_entry_index);
833
        Self::read_with_args(data, args)
834
    }
835
}
836
837
#[derive(Clone)]
838
pub struct GlyphMap<'a> {
839
    data: FontData<'a>,
840
    glyph_count: Uint24,
841
    max_entry_index: u16,
842
}
843
844
#[allow(clippy::needless_lifetimes)]
845
impl<'a> GlyphMap<'a> {
846
    pub const MIN_SIZE: usize = u16::RAW_BYTE_LEN;
847
    basic_table_impls!(impl_the_methods);
848
849
    pub fn first_mapped_glyph(&self) -> u16 {
850
        let range = self.first_mapped_glyph_byte_range();
851
        self.data.read_at(range.start).ok().unwrap()
852
    }
853
854
    pub fn entry_index(&self) -> ComputedArray<'a, U8Or16> {
855
        let range = self.entry_index_byte_range();
856
        self.data
857
            .read_with_args(range, self.max_entry_index())
858
            .unwrap_or_default()
859
    }
860
861
    pub(crate) fn glyph_count(&self) -> Uint24 {
862
        self.glyph_count
863
    }
864
865
    pub(crate) fn max_entry_index(&self) -> u16 {
866
        self.max_entry_index
867
    }
868
869
    pub fn first_mapped_glyph_byte_range(&self) -> Range<usize> {
870
        let start = 0;
871
        let end = start + u16::RAW_BYTE_LEN;
872
        start..end
873
    }
874
875
    pub fn entry_index_byte_range(&self) -> Range<usize> {
876
        let glyph_count = self.glyph_count();
877
        let first_mapped_glyph = self.first_mapped_glyph();
878
        let start = self.first_mapped_glyph_byte_range().end;
879
        let end = start
880
            + (transforms::subtract(glyph_count, first_mapped_glyph)).saturating_mul(
881
                <U8Or16 as ComputeSize>::compute_size(self.max_entry_index()).unwrap_or(0),
882
            );
883
        start..end
884
    }
885
}
886
887
const _: () = assert!(FontData::default_data_long_enough(GlyphMap::MIN_SIZE));
888
889
impl Default for GlyphMap<'_> {
890
    fn default() -> Self {
891
        Self {
892
            data: FontData::default_table_data(),
893
            glyph_count: Default::default(),
894
            max_entry_index: Default::default(),
895
        }
896
    }
897
}
898
899
#[cfg(feature = "experimental_traverse")]
900
impl<'a> SomeTable<'a> for GlyphMap<'a> {
901
    fn type_name(&self) -> &str {
902
        "GlyphMap"
903
    }
904
    fn get_field(&self, idx: usize) -> Option<Field<'a>> {
905
        match idx {
906
            0usize => Some(Field::new("first_mapped_glyph", self.first_mapped_glyph())),
907
            1usize => Some(Field::new("entry_index", traversal::FieldType::Unknown)),
908
            _ => None,
909
        }
910
    }
911
}
912
913
#[cfg(feature = "experimental_traverse")]
914
#[allow(clippy::needless_lifetimes)]
915
impl<'a> std::fmt::Debug for GlyphMap<'a> {
916
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
917
        (self as &dyn SomeTable<'a>).fmt(f)
918
    }
919
}
920
921
impl<'a> MinByteRange<'a> for FeatureMap<'a> {
922
    fn min_byte_range(&self) -> Range<usize> {
923
        0..self.entry_map_data_byte_range().end
924
    }
925
    fn min_table_bytes(&self) -> &'a [u8] {
926
        let range = self.min_byte_range();
927
        self.data.as_bytes().get(range).unwrap_or_default()
928
    }
929
}
930
931
impl ReadArgs for FeatureMap<'_> {
932
    type Args = u16;
933
}
934
935
impl<'a> FontRead<'a> for FeatureMap<'a> {
936
    fn read_with_args(data: FontData<'a>, args: u16) -> Result<Self, ReadError> {
937
        let max_entry_index = args;
938
939
        #[allow(clippy::absurd_extreme_comparisons)]
940
        if data.len() < Self::MIN_SIZE {
941
            return Err(ReadError::OutOfBounds);
942
        }
943
        Ok(Self {
944
            data,
945
            max_entry_index,
946
        })
947
    }
948
}
949
950
impl<'a> FeatureMap<'a> {
951
    /// A constructor that requires additional arguments.
952
    ///
953
    /// This type requires some external state in order to be
954
    /// parsed.
955
    pub fn read(data: FontData<'a>, max_entry_index: u16) -> Result<Self, ReadError> {
956
        let args = max_entry_index;
957
        Self::read_with_args(data, args)
958
    }
959
}
960
961
#[derive(Clone)]
962
pub struct FeatureMap<'a> {
963
    data: FontData<'a>,
964
    max_entry_index: u16,
965
}
966
967
#[allow(clippy::needless_lifetimes)]
968
impl<'a> FeatureMap<'a> {
969
    pub const MIN_SIZE: usize = u16::RAW_BYTE_LEN;
970
    basic_table_impls!(impl_the_methods);
971
972
    pub fn feature_count(&self) -> u16 {
973
        let range = self.feature_count_byte_range();
974
        self.data.read_at(range.start).ok().unwrap()
975
    }
976
977
    pub fn feature_records(&self) -> ComputedArray<'a, FeatureRecord> {
978
        let range = self.feature_records_byte_range();
979
        self.data
980
            .read_with_args(range, self.max_entry_index())
981
            .unwrap_or_default()
982
    }
983
984
    pub fn entry_map_data(&self) -> &'a [u8] {
985
        let range = self.entry_map_data_byte_range();
986
        self.data.read_array(range).ok().unwrap_or_default()
987
    }
988
989
    pub(crate) fn max_entry_index(&self) -> u16 {
990
        self.max_entry_index
991
    }
992
993
    pub fn feature_count_byte_range(&self) -> Range<usize> {
994
        let start = 0;
995
        let end = start + u16::RAW_BYTE_LEN;
996
        start..end
997
    }
998
999
    pub fn feature_records_byte_range(&self) -> Range<usize> {
1000
        let feature_count = self.feature_count();
1001
        let start = self.feature_count_byte_range().end;
1002
        let end = start
1003
            + (transforms::to_usize(feature_count)).saturating_mul(
1004
                <FeatureRecord as ComputeSize>::compute_size(self.max_entry_index()).unwrap_or(0),
1005
            );
1006
        start..end
1007
    }
1008
1009
    pub fn entry_map_data_byte_range(&self) -> Range<usize> {
1010
        let start = self.feature_records_byte_range().end;
1011
        let end =
1012
            start + self.data.len().saturating_sub(start) / u8::RAW_BYTE_LEN * u8::RAW_BYTE_LEN;
1013
        start..end
1014
    }
1015
}
1016
1017
const _: () = assert!(FontData::default_data_long_enough(FeatureMap::MIN_SIZE));
1018
1019
impl Default for FeatureMap<'_> {
1020
    fn default() -> Self {
1021
        Self {
1022
            data: FontData::default_table_data(),
1023
            max_entry_index: Default::default(),
1024
        }
1025
    }
1026
}
1027
1028
#[cfg(feature = "experimental_traverse")]
1029
impl<'a> SomeTable<'a> for FeatureMap<'a> {
1030
    fn type_name(&self) -> &str {
1031
        "FeatureMap"
1032
    }
1033
    fn get_field(&self, idx: usize) -> Option<Field<'a>> {
1034
        match idx {
1035
            0usize => Some(Field::new("feature_count", self.feature_count())),
1036
            1usize => Some(Field::new("feature_records", traversal::FieldType::Unknown)),
1037
            2usize => Some(Field::new("entry_map_data", self.entry_map_data())),
1038
            _ => None,
1039
        }
1040
    }
1041
}
1042
1043
#[cfg(feature = "experimental_traverse")]
1044
#[allow(clippy::needless_lifetimes)]
1045
impl<'a> std::fmt::Debug for FeatureMap<'a> {
1046
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1047
        (self as &dyn SomeTable<'a>).fmt(f)
1048
    }
1049
}
1050
1051
#[derive(Clone, Debug)]
1052
pub struct FeatureRecord {
1053
    pub feature_tag: BigEndian<Tag>,
1054
    pub first_new_entry_index: U8Or16,
1055
    pub entry_map_count: U8Or16,
1056
}
1057
1058
impl FeatureRecord {
1059
    pub fn feature_tag(&self) -> Tag {
1060
        self.feature_tag.get()
1061
    }
1062
1063
    pub fn first_new_entry_index(&self) -> &U8Or16 {
1064
        &self.first_new_entry_index
1065
    }
1066
1067
    pub fn entry_map_count(&self) -> &U8Or16 {
1068
        &self.entry_map_count
1069
    }
1070
}
1071
1072
impl ReadArgs for FeatureRecord {
1073
    type Args = u16;
1074
}
1075
1076
impl ComputeSize for FeatureRecord {
1077
    #[allow(clippy::needless_question_mark)]
1078
    fn compute_size(args: u16) -> Result<usize, ReadError> {
1079
        let max_entry_index = args;
1080
        let mut result = 0usize;
1081
        result = result
1082
            .checked_add(Tag::RAW_BYTE_LEN)
1083
            .ok_or(ReadError::OutOfBounds)?;
1084
        result = result
1085
            .checked_add(<U8Or16 as ComputeSize>::compute_size(max_entry_index).unwrap_or(0))
1086
            .ok_or(ReadError::OutOfBounds)?;
1087
        result = result
1088
            .checked_add(<U8Or16 as ComputeSize>::compute_size(max_entry_index).unwrap_or(0))
1089
            .ok_or(ReadError::OutOfBounds)?;
1090
        Ok(result)
1091
    }
1092
}
1093
1094
impl<'a> FontRead<'a> for FeatureRecord {
1095
    fn read_with_args(data: FontData<'a>, args: u16) -> Result<Self, ReadError> {
1096
        let mut cursor = data.cursor();
1097
        let max_entry_index = args;
1098
        Ok(Self {
1099
            feature_tag: cursor.read_be()?,
1100
            first_new_entry_index: cursor.read_with_args(max_entry_index)?,
1101
            entry_map_count: cursor.read_with_args(max_entry_index)?,
1102
        })
1103
    }
1104
}
1105
1106
#[allow(clippy::needless_lifetimes)]
1107
impl<'a> FeatureRecord {
1108
    /// A constructor that requires additional arguments.
1109
    ///
1110
    /// This type requires some external state in order to be
1111
    /// parsed.
1112
    pub fn read(data: FontData<'a>, max_entry_index: u16) -> Result<Self, ReadError> {
1113
        let args = max_entry_index;
1114
        Self::read_with_args(data, args)
1115
    }
1116
}
1117
1118
#[cfg(feature = "experimental_traverse")]
1119
impl<'a> SomeRecord<'a> for FeatureRecord {
1120
    fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
1121
        RecordResolver {
1122
            name: "FeatureRecord",
1123
            get_field: Box::new(move |idx, _data| match idx {
1124
                0usize => Some(Field::new("feature_tag", self.feature_tag())),
1125
                1usize => Some(Field::new(
1126
                    "first_new_entry_index",
1127
                    traversal::FieldType::Unknown,
1128
                )),
1129
                2usize => Some(Field::new("entry_map_count", traversal::FieldType::Unknown)),
1130
                _ => None,
1131
            }),
1132
            data,
1133
        }
1134
    }
1135
}
1136
1137
#[derive(Clone, Debug)]
1138
pub struct EntryMapRecord {
1139
    pub first_entry_index: U8Or16,
1140
    pub last_entry_index: U8Or16,
1141
}
1142
1143
impl EntryMapRecord {
1144
    pub fn first_entry_index(&self) -> &U8Or16 {
1145
        &self.first_entry_index
1146
    }
1147
1148
    pub fn last_entry_index(&self) -> &U8Or16 {
1149
        &self.last_entry_index
1150
    }
1151
}
1152
1153
impl ReadArgs for EntryMapRecord {
1154
    type Args = u16;
1155
}
1156
1157
impl ComputeSize for EntryMapRecord {
1158
    #[allow(clippy::needless_question_mark)]
1159
    fn compute_size(args: u16) -> Result<usize, ReadError> {
1160
        let max_entry_index = args;
1161
        let mut result = 0usize;
1162
        result = result
1163
            .checked_add(<U8Or16 as ComputeSize>::compute_size(max_entry_index).unwrap_or(0))
1164
            .ok_or(ReadError::OutOfBounds)?;
1165
        result = result
1166
            .checked_add(<U8Or16 as ComputeSize>::compute_size(max_entry_index).unwrap_or(0))
1167
            .ok_or(ReadError::OutOfBounds)?;
1168
        Ok(result)
1169
    }
1170
}
1171
1172
impl<'a> FontRead<'a> for EntryMapRecord {
1173
    fn read_with_args(data: FontData<'a>, args: u16) -> Result<Self, ReadError> {
1174
        let mut cursor = data.cursor();
1175
        let max_entry_index = args;
1176
        Ok(Self {
1177
            first_entry_index: cursor.read_with_args(max_entry_index)?,
1178
            last_entry_index: cursor.read_with_args(max_entry_index)?,
1179
        })
1180
    }
1181
}
1182
1183
#[allow(clippy::needless_lifetimes)]
1184
impl<'a> EntryMapRecord {
1185
    /// A constructor that requires additional arguments.
1186
    ///
1187
    /// This type requires some external state in order to be
1188
    /// parsed.
1189
    pub fn read(data: FontData<'a>, max_entry_index: u16) -> Result<Self, ReadError> {
1190
        let args = max_entry_index;
1191
        Self::read_with_args(data, args)
1192
    }
1193
}
1194
1195
#[cfg(feature = "experimental_traverse")]
1196
impl<'a> SomeRecord<'a> for EntryMapRecord {
1197
    fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
1198
        RecordResolver {
1199
            name: "EntryMapRecord",
1200
            get_field: Box::new(move |idx, _data| match idx {
1201
                0usize => Some(Field::new(
1202
                    "first_entry_index",
1203
                    traversal::FieldType::Unknown,
1204
                )),
1205
                1usize => Some(Field::new(
1206
                    "last_entry_index",
1207
                    traversal::FieldType::Unknown,
1208
                )),
1209
                _ => None,
1210
            }),
1211
            data,
1212
        }
1213
    }
1214
}
1215
1216
impl Format<u8> for PatchMapFormat2<'_> {
1217
    const FORMAT: u8 = 2;
1218
}
1219
1220
impl<'a> MinByteRange<'a> for PatchMapFormat2<'a> {
1221
    fn min_byte_range(&self) -> Range<usize> {
1222
        0..self.url_template_byte_range().end
1223
    }
1224
    fn min_table_bytes(&self) -> &'a [u8] {
1225
        let range = self.min_byte_range();
1226
        self.data.as_bytes().get(range).unwrap_or_default()
1227
    }
1228
}
1229
1230
impl ReadArgs for PatchMapFormat2<'_> {
1231
    type Args = ();
1232
}
1233
1234
impl<'a> FontRead<'a> for PatchMapFormat2<'a> {
1235
    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1236
        #[allow(clippy::absurd_extreme_comparisons)]
1237
        if data.len() < Self::MIN_SIZE {
1238
            return Err(ReadError::OutOfBounds);
1239
        }
1240
        Ok(Self { data })
1241
    }
1242
}
1243
1244
/// [Patch Map Format Format 2](https://w3c.github.io/IFT/Overview.html#patch-map-format-2)
1245
#[derive(Clone)]
1246
pub struct PatchMapFormat2<'a> {
1247
    data: FontData<'a>,
1248
}
1249
1250
#[allow(clippy::needless_lifetimes)]
1251
impl<'a> PatchMapFormat2<'a> {
1252
    pub const MIN_SIZE: usize = (u8::RAW_BYTE_LEN
1253
        + u8::RAW_BYTE_LEN
1254
        + u8::RAW_BYTE_LEN
1255
        + u8::RAW_BYTE_LEN
1256
        + PatchMapFieldPresenceFlags::RAW_BYTE_LEN
1257
        + CompatibilityId::RAW_BYTE_LEN
1258
        + u8::RAW_BYTE_LEN
1259
        + Uint24::RAW_BYTE_LEN
1260
        + Offset32::RAW_BYTE_LEN
1261
        + Offset32::RAW_BYTE_LEN
1262
        + u16::RAW_BYTE_LEN);
1263
    basic_table_impls!(impl_the_methods);
1264
1265
    /// Format identifier: format = 2
1266
    pub fn format(&self) -> u8 {
1267
        let range = self.format_byte_range();
1268
        self.data.read_at(range.start).ok().unwrap()
1269
    }
1270
1271
    pub fn field_flags(&self) -> PatchMapFieldPresenceFlags {
1272
        let range = self.field_flags_byte_range();
1273
        self.data.read_at(range.start).ok().unwrap()
1274
    }
1275
1276
    /// Unique ID that identifies compatible patches.
1277
    pub fn compatibility_id(&self) -> CompatibilityId {
1278
        let range = self.compatibility_id_byte_range();
1279
        self.data.read_at(range.start).ok().unwrap()
1280
    }
1281
1282
    /// Patch format number for patches referenced by this mapping.
1283
    pub fn default_patch_format(&self) -> u8 {
1284
        let range = self.default_patch_format_byte_range();
1285
        self.data.read_at(range.start).ok().unwrap()
1286
    }
1287
1288
    pub fn entry_count(&self) -> Uint24 {
1289
        let range = self.entry_count_byte_range();
1290
        self.data.read_at(range.start).ok().unwrap()
1291
    }
1292
1293
    pub fn entries_offset(&self) -> Offset32 {
1294
        let range = self.entries_offset_byte_range();
1295
        self.data.read_at(range.start).ok().unwrap()
1296
    }
1297
1298
    /// Attempt to resolve [`entries_offset`][Self::entries_offset].
1299
    pub fn entries(&self) -> Result<MappingEntries<'a>, ReadError> {
1300
        let data = self.data;
1301
        self.entries_offset().resolve(data)
1302
    }
1303
1304
    pub fn entry_id_string_data_offset(&self) -> Nullable<Offset32> {
1305
        let range = self.entry_id_string_data_offset_byte_range();
1306
        self.data.read_at(range.start).ok().unwrap()
1307
    }
1308
1309
    /// Attempt to resolve [`entry_id_string_data_offset`][Self::entry_id_string_data_offset].
1310
    pub fn entry_id_string_data(&self) -> Option<Result<IdStringData<'a>, ReadError>> {
1311
        let data = self.data;
1312
        self.entry_id_string_data_offset().resolve(data)
1313
    }
1314
1315
    pub fn url_template_length(&self) -> u16 {
1316
        let range = self.url_template_length_byte_range();
1317
        self.data.read_at(range.start).ok().unwrap()
1318
    }
1319
1320
    pub fn url_template(&self) -> &'a [u8] {
1321
        let range = self.url_template_byte_range();
1322
        self.data.read_array(range).ok().unwrap_or_default()
1323
    }
1324
1325
    pub fn cff_charstrings_offset(&self) -> Option<u32> {
1326
        let range = self.cff_charstrings_offset_byte_range();
1327
        (!range.is_empty())
1328
            .then(|| self.data.read_at(range.start).ok())
1329
            .flatten()
1330
    }
1331
1332
    pub fn cff2_charstrings_offset(&self) -> Option<u32> {
1333
        let range = self.cff2_charstrings_offset_byte_range();
1334
        (!range.is_empty())
1335
            .then(|| self.data.read_at(range.start).ok())
1336
            .flatten()
1337
    }
1338
1339
    pub fn format_byte_range(&self) -> Range<usize> {
1340
        let start = 0;
1341
        let end = start + u8::RAW_BYTE_LEN;
1342
        start..end
1343
    }
1344
1345
    pub fn _reserved_0_byte_range(&self) -> Range<usize> {
1346
        let start = self.format_byte_range().end;
1347
        let end = start + u8::RAW_BYTE_LEN;
1348
        start..end
1349
    }
1350
1351
    pub fn _reserved_1_byte_range(&self) -> Range<usize> {
1352
        let start = self._reserved_0_byte_range().end;
1353
        let end = start + u8::RAW_BYTE_LEN;
1354
        start..end
1355
    }
1356
1357
    pub fn _reserved_2_byte_range(&self) -> Range<usize> {
1358
        let start = self._reserved_1_byte_range().end;
1359
        let end = start + u8::RAW_BYTE_LEN;
1360
        start..end
1361
    }
1362
1363
    pub fn field_flags_byte_range(&self) -> Range<usize> {
1364
        let start = self._reserved_2_byte_range().end;
1365
        let end = start + PatchMapFieldPresenceFlags::RAW_BYTE_LEN;
1366
        start..end
1367
    }
1368
1369
    pub fn compatibility_id_byte_range(&self) -> Range<usize> {
1370
        let start = self.field_flags_byte_range().end;
1371
        let end = start + CompatibilityId::RAW_BYTE_LEN;
1372
        start..end
1373
    }
1374
1375
    pub fn default_patch_format_byte_range(&self) -> Range<usize> {
1376
        let start = self.compatibility_id_byte_range().end;
1377
        let end = start + u8::RAW_BYTE_LEN;
1378
        start..end
1379
    }
1380
1381
    pub fn entry_count_byte_range(&self) -> Range<usize> {
1382
        let start = self.default_patch_format_byte_range().end;
1383
        let end = start + Uint24::RAW_BYTE_LEN;
1384
        start..end
1385
    }
1386
1387
    pub fn entries_offset_byte_range(&self) -> Range<usize> {
1388
        let start = self.entry_count_byte_range().end;
1389
        let end = start + Offset32::RAW_BYTE_LEN;
1390
        start..end
1391
    }
1392
1393
    pub fn entry_id_string_data_offset_byte_range(&self) -> Range<usize> {
1394
        let start = self.entries_offset_byte_range().end;
1395
        let end = start + Offset32::RAW_BYTE_LEN;
1396
        start..end
1397
    }
1398
1399
    pub fn url_template_length_byte_range(&self) -> Range<usize> {
1400
        let start = self.entry_id_string_data_offset_byte_range().end;
1401
        let end = start + u16::RAW_BYTE_LEN;
1402
        start..end
1403
    }
1404
1405
    pub fn url_template_byte_range(&self) -> Range<usize> {
1406
        let url_template_length = self.url_template_length();
1407
        let start = self.url_template_length_byte_range().end;
1408
        let end =
1409
            start + (transforms::to_usize(url_template_length)).saturating_mul(u8::RAW_BYTE_LEN);
1410
        start..end
1411
    }
1412
1413
    pub fn cff_charstrings_offset_byte_range(&self) -> Range<usize> {
1414
        let start = self.url_template_byte_range().end;
1415
        let end = if self
1416
            .field_flags()
1417
            .contains(PatchMapFieldPresenceFlags::CFF_CHARSTRINGS_OFFSET)
1418
        {
1419
            start + u32::RAW_BYTE_LEN
1420
        } else {
1421
            start
1422
        };
1423
        start..end
1424
    }
1425
1426
    pub fn cff2_charstrings_offset_byte_range(&self) -> Range<usize> {
1427
        let start = self.cff_charstrings_offset_byte_range().end;
1428
        let end = if self
1429
            .field_flags()
1430
            .contains(PatchMapFieldPresenceFlags::CFF2_CHARSTRINGS_OFFSET)
1431
        {
1432
            start + u32::RAW_BYTE_LEN
1433
        } else {
1434
            start
1435
        };
1436
        start..end
1437
    }
1438
}
1439
1440
#[cfg(feature = "experimental_traverse")]
1441
impl<'a> SomeTable<'a> for PatchMapFormat2<'a> {
1442
    fn type_name(&self) -> &str {
1443
        "PatchMapFormat2"
1444
    }
1445
    fn get_field(&self, idx: usize) -> Option<Field<'a>> {
1446
        match idx {
1447
            0usize => Some(Field::new("format", self.format())),
1448
            1usize => Some(Field::new("field_flags", self.field_flags())),
1449
            2usize => Some(Field::new(
1450
                "compatibility_id",
1451
                traversal::FieldType::Unknown,
1452
            )),
1453
            3usize => Some(Field::new(
1454
                "default_patch_format",
1455
                self.default_patch_format(),
1456
            )),
1457
            4usize => Some(Field::new("entry_count", self.entry_count())),
1458
            5usize => Some(Field::new(
1459
                "entries_offset",
1460
                FieldType::offset(self.entries_offset(), self.entries()),
1461
            )),
1462
            6usize => Some(Field::new(
1463
                "entry_id_string_data_offset",
1464
                FieldType::offset(
1465
                    self.entry_id_string_data_offset(),
1466
                    self.entry_id_string_data(),
1467
                ),
1468
            )),
1469
            7usize => Some(Field::new(
1470
                "url_template_length",
1471
                self.url_template_length(),
1472
            )),
1473
            8usize => Some(Field::new("url_template", self.url_template())),
1474
            9usize
1475
                if self
1476
                    .field_flags()
1477
                    .contains(PatchMapFieldPresenceFlags::CFF_CHARSTRINGS_OFFSET) =>
1478
            {
1479
                Some(Field::new(
1480
                    "cff_charstrings_offset",
1481
                    self.cff_charstrings_offset().unwrap(),
1482
                ))
1483
            }
1484
            10usize
1485
                if self
1486
                    .field_flags()
1487
                    .contains(PatchMapFieldPresenceFlags::CFF2_CHARSTRINGS_OFFSET) =>
1488
            {
1489
                Some(Field::new(
1490
                    "cff2_charstrings_offset",
1491
                    self.cff2_charstrings_offset().unwrap(),
1492
                ))
1493
            }
1494
            _ => None,
1495
        }
1496
    }
1497
}
1498
1499
#[cfg(feature = "experimental_traverse")]
1500
#[allow(clippy::needless_lifetimes)]
1501
impl<'a> std::fmt::Debug for PatchMapFormat2<'a> {
1502
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1503
        (self as &dyn SomeTable<'a>).fmt(f)
1504
    }
1505
}
1506
1507
impl<'a> MinByteRange<'a> for MappingEntries<'a> {
1508
    fn min_byte_range(&self) -> Range<usize> {
1509
        0..self.entry_data_byte_range().end
1510
    }
1511
    fn min_table_bytes(&self) -> &'a [u8] {
1512
        let range = self.min_byte_range();
1513
        self.data.as_bytes().get(range).unwrap_or_default()
1514
    }
1515
}
1516
1517
impl ReadArgs for MappingEntries<'_> {
1518
    type Args = ();
1519
}
1520
1521
impl<'a> FontRead<'a> for MappingEntries<'a> {
1522
    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1523
        #[allow(clippy::absurd_extreme_comparisons)]
1524
        if data.len() < Self::MIN_SIZE {
1525
            return Err(ReadError::OutOfBounds);
1526
        }
1527
        Ok(Self { data })
1528
    }
1529
}
1530
1531
#[derive(Clone)]
1532
pub struct MappingEntries<'a> {
1533
    data: FontData<'a>,
1534
}
1535
1536
#[allow(clippy::needless_lifetimes)]
1537
impl<'a> MappingEntries<'a> {
1538
    pub const MIN_SIZE: usize = 0;
1539
    basic_table_impls!(impl_the_methods);
1540
1541
    pub fn entry_data(&self) -> &'a [u8] {
1542
        let range = self.entry_data_byte_range();
1543
        self.data.read_array(range).ok().unwrap_or_default()
1544
    }
1545
1546
    pub fn entry_data_byte_range(&self) -> Range<usize> {
1547
        let start = 0;
1548
        let end =
1549
            start + self.data.len().saturating_sub(start) / u8::RAW_BYTE_LEN * u8::RAW_BYTE_LEN;
1550
        start..end
1551
    }
1552
}
1553
1554
#[allow(clippy::absurd_extreme_comparisons)]
1555
const _: () = assert!(FontData::default_data_long_enough(MappingEntries::MIN_SIZE));
1556
1557
impl Default for MappingEntries<'_> {
1558
    fn default() -> Self {
1559
        Self {
1560
            data: FontData::default_table_data(),
1561
        }
1562
    }
1563
}
1564
1565
#[cfg(feature = "experimental_traverse")]
1566
impl<'a> SomeTable<'a> for MappingEntries<'a> {
1567
    fn type_name(&self) -> &str {
1568
        "MappingEntries"
1569
    }
1570
    fn get_field(&self, idx: usize) -> Option<Field<'a>> {
1571
        match idx {
1572
            0usize => Some(Field::new("entry_data", self.entry_data())),
1573
            _ => None,
1574
        }
1575
    }
1576
}
1577
1578
#[cfg(feature = "experimental_traverse")]
1579
#[allow(clippy::needless_lifetimes)]
1580
impl<'a> std::fmt::Debug for MappingEntries<'a> {
1581
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1582
        (self as &dyn SomeTable<'a>).fmt(f)
1583
    }
1584
}
1585
1586
impl<'a> MinByteRange<'a> for EntryData<'a> {
1587
    fn min_byte_range(&self) -> Range<usize> {
1588
        0..self.trailing_data_byte_range().end
1589
    }
1590
    fn min_table_bytes(&self) -> &'a [u8] {
1591
        let range = self.min_byte_range();
1592
        self.data.as_bytes().get(range).unwrap_or_default()
1593
    }
1594
}
1595
1596
impl ReadArgs for EntryData<'_> {
1597
    type Args = ();
1598
}
1599
1600
impl<'a> FontRead<'a> for EntryData<'a> {
1601
    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
1602
        #[allow(clippy::absurd_extreme_comparisons)]
1603
        if data.len() < Self::MIN_SIZE {
1604
            return Err(ReadError::OutOfBounds);
1605
        }
1606
        Ok(Self { data })
1607
    }
1608
}
1609
1610
#[derive(Clone)]
1611
pub struct EntryData<'a> {
1612
    data: FontData<'a>,
1613
}
1614
1615
#[allow(clippy::needless_lifetimes)]
1616
impl<'a> EntryData<'a> {
1617
    pub const MIN_SIZE: usize = EntryFormatFlags::RAW_BYTE_LEN;
1618
    basic_table_impls!(impl_the_methods);
1619
1620
    pub fn format_flags(&self) -> EntryFormatFlags {
1621
        let range = self.format_flags_byte_range();
1622
        self.data.read_at(range.start).ok().unwrap()
1623
    }
1624
1625
    pub fn feature_count(&self) -> Option<u8> {
1626
        let range = self.feature_count_byte_range();
1627
        (!range.is_empty())
1628
            .then(|| self.data.read_at(range.start).ok())
1629
            .flatten()
1630
    }
1631
1632
    pub fn feature_tags(&self) -> Option<&'a [BigEndian<Tag>]> {
1633
        let range = self.feature_tags_byte_range();
1634
        (!range.is_empty())
1635
            .then(|| self.data.read_array(range).ok())
1636
            .flatten()
1637
    }
1638
1639
    pub fn design_space_count(&self) -> Option<u16> {
1640
        let range = self.design_space_count_byte_range();
1641
        (!range.is_empty())
1642
            .then(|| self.data.read_at(range.start).ok())
1643
            .flatten()
1644
    }
1645
1646
    pub fn design_space_segments(&self) -> Option<&'a [DesignSpaceSegment]> {
1647
        let range = self.design_space_segments_byte_range();
1648
        (!range.is_empty())
1649
            .then(|| self.data.read_array(range).ok())
1650
            .flatten()
1651
    }
1652
1653
    pub fn match_mode_and_count(&self) -> Option<MatchModeAndCount> {
1654
        let range = self.match_mode_and_count_byte_range();
1655
        (!range.is_empty())
1656
            .then(|| self.data.read_at(range.start).ok())
1657
            .flatten()
1658
    }
1659
1660
    pub fn child_indices(&self) -> Option<&'a [BigEndian<Uint24>]> {
1661
        let range = self.child_indices_byte_range();
1662
        (!range.is_empty())
1663
            .then(|| self.data.read_array(range).ok())
1664
            .flatten()
1665
    }
1666
1667
    pub fn format_flags_byte_range(&self) -> Range<usize> {
1668
        let start = 0;
1669
        let end = start + EntryFormatFlags::RAW_BYTE_LEN;
1670
        start..end
1671
    }
1672
1673
    pub fn feature_count_byte_range(&self) -> Range<usize> {
1674
        let start = self.format_flags_byte_range().end;
1675
        let end = if self
1676
            .format_flags()
1677
            .contains(EntryFormatFlags::FEATURES_AND_DESIGN_SPACE)
1678
        {
1679
            start + u8::RAW_BYTE_LEN
1680
        } else {
1681
            start
1682
        };
1683
        start..end
1684
    }
1685
1686
    pub fn feature_tags_byte_range(&self) -> Range<usize> {
1687
        let feature_count = self.feature_count().unwrap_or_default();
1688
        let start = self.feature_count_byte_range().end;
1689
        let end = if self
1690
            .format_flags()
1691
            .contains(EntryFormatFlags::FEATURES_AND_DESIGN_SPACE)
1692
        {
1693
            start + (transforms::to_usize(feature_count)).saturating_mul(Tag::RAW_BYTE_LEN)
1694
        } else {
1695
            start
1696
        };
1697
        start..end
1698
    }
1699
1700
    pub fn design_space_count_byte_range(&self) -> Range<usize> {
1701
        let start = self.feature_tags_byte_range().end;
1702
        let end = if self
1703
            .format_flags()
1704
            .contains(EntryFormatFlags::FEATURES_AND_DESIGN_SPACE)
1705
        {
1706
            start + u16::RAW_BYTE_LEN
1707
        } else {
1708
            start
1709
        };
1710
        start..end
1711
    }
1712
1713
    pub fn design_space_segments_byte_range(&self) -> Range<usize> {
1714
        let design_space_count = self.design_space_count().unwrap_or_default();
1715
        let start = self.design_space_count_byte_range().end;
1716
        let end = if self
1717
            .format_flags()
1718
            .contains(EntryFormatFlags::FEATURES_AND_DESIGN_SPACE)
1719
        {
1720
            start
1721
                + (transforms::to_usize(design_space_count))
1722
                    .saturating_mul(DesignSpaceSegment::RAW_BYTE_LEN)
1723
        } else {
1724
            start
1725
        };
1726
        start..end
1727
    }
1728
1729
    pub fn match_mode_and_count_byte_range(&self) -> Range<usize> {
1730
        let start = self.design_space_segments_byte_range().end;
1731
        let end = if self
1732
            .format_flags()
1733
            .contains(EntryFormatFlags::CHILD_INDICES)
1734
        {
1735
            start + MatchModeAndCount::RAW_BYTE_LEN
1736
        } else {
1737
            start
1738
        };
1739
        start..end
1740
    }
1741
1742
    pub fn child_indices_byte_range(&self) -> Range<usize> {
1743
        let match_mode_and_count = self.match_mode_and_count().unwrap_or_default();
1744
        let start = self.match_mode_and_count_byte_range().end;
1745
        let end = if self
1746
            .format_flags()
1747
            .contains(EntryFormatFlags::CHILD_INDICES)
1748
        {
1749
            start
1750
                + (transforms::to_usize(match_mode_and_count)).saturating_mul(Uint24::RAW_BYTE_LEN)
1751
        } else {
1752
            start
1753
        };
1754
        start..end
1755
    }
1756
1757
    pub fn trailing_data_byte_range(&self) -> Range<usize> {
1758
        let start = self.child_indices_byte_range().end;
1759
        let end =
1760
            start + self.data.len().saturating_sub(start) / u8::RAW_BYTE_LEN * u8::RAW_BYTE_LEN;
1761
        start..end
1762
    }
1763
}
1764
1765
const _: () = assert!(FontData::default_data_long_enough(EntryData::MIN_SIZE));
1766
1767
impl Default for EntryData<'_> {
1768
    fn default() -> Self {
1769
        Self {
1770
            data: FontData::default_table_data(),
1771
        }
1772
    }
1773
}
1774
1775
#[cfg(feature = "experimental_traverse")]
1776
impl<'a> SomeTable<'a> for EntryData<'a> {
1777
    fn type_name(&self) -> &str {
1778
        "EntryData"
1779
    }
1780
    fn get_field(&self, idx: usize) -> Option<Field<'a>> {
1781
        match idx {
1782
            0usize => Some(Field::new("format_flags", self.format_flags())),
1783
            1usize
1784
                if self
1785
                    .format_flags()
1786
                    .contains(EntryFormatFlags::FEATURES_AND_DESIGN_SPACE) =>
1787
            {
1788
                Some(Field::new("feature_count", self.feature_count().unwrap()))
1789
            }
1790
            2usize
1791
                if self
1792
                    .format_flags()
1793
                    .contains(EntryFormatFlags::FEATURES_AND_DESIGN_SPACE) =>
1794
            {
1795
                Some(Field::new("feature_tags", self.feature_tags().unwrap()))
1796
            }
1797
            3usize
1798
                if self
1799
                    .format_flags()
1800
                    .contains(EntryFormatFlags::FEATURES_AND_DESIGN_SPACE) =>
1801
            {
1802
                Some(Field::new(
1803
                    "design_space_count",
1804
                    self.design_space_count().unwrap(),
1805
                ))
1806
            }
1807
            4usize
1808
                if self
1809
                    .format_flags()
1810
                    .contains(EntryFormatFlags::FEATURES_AND_DESIGN_SPACE) =>
1811
            {
1812
                Some(Field::new(
1813
                    "design_space_segments",
1814
                    traversal::FieldType::array_of_records(
1815
                        stringify!(DesignSpaceSegment),
1816
                        self.design_space_segments().unwrap(),
1817
                        self.offset_data(),
1818
                    ),
1819
                ))
1820
            }
1821
            5usize
1822
                if self
1823
                    .format_flags()
1824
                    .contains(EntryFormatFlags::CHILD_INDICES) =>
1825
            {
1826
                Some(Field::new(
1827
                    "match_mode_and_count",
1828
                    traversal::FieldType::Unknown,
1829
                ))
1830
            }
1831
            6usize
1832
                if self
1833
                    .format_flags()
1834
                    .contains(EntryFormatFlags::CHILD_INDICES) =>
1835
            {
1836
                Some(Field::new("child_indices", self.child_indices().unwrap()))
1837
            }
1838
            _ => None,
1839
        }
1840
    }
1841
}
1842
1843
#[cfg(feature = "experimental_traverse")]
1844
#[allow(clippy::needless_lifetimes)]
1845
impl<'a> std::fmt::Debug for EntryData<'a> {
1846
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1847
        (self as &dyn SomeTable<'a>).fmt(f)
1848
    }
1849
}
1850
1851
#[derive(Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash, bytemuck :: AnyBitPattern)]
1852
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
1853
#[repr(transparent)]
1854
pub struct EntryFormatFlags {
1855
    bits: u8,
1856
}
1857
1858
impl EntryFormatFlags {
1859
    pub const FEATURES_AND_DESIGN_SPACE: Self = Self { bits: 0b00000001 };
1860
1861
    pub const CHILD_INDICES: Self = Self { bits: 0b00000010 };
1862
1863
    pub const ENTRY_ID_DELTA: Self = Self { bits: 0b00000100 };
1864
1865
    pub const PATCH_FORMAT: Self = Self { bits: 0b00001000 };
1866
1867
    pub const CODEPOINTS_BIT_1: Self = Self { bits: 0b00010000 };
1868
1869
    pub const CODEPOINTS_BIT_2: Self = Self { bits: 0b00100000 };
1870
1871
    pub const IGNORED: Self = Self { bits: 0b01000000 };
1872
1873
    pub const RESERVED: Self = Self { bits: 0b10000000 };
1874
}
1875
1876
impl EntryFormatFlags {
1877
    ///  Returns an empty set of flags.
1878
    #[inline]
1879
    pub const fn empty() -> Self {
1880
        Self { bits: 0 }
1881
    }
1882
1883
    /// Returns the set containing all flags.
1884
    #[inline]
1885
    pub const fn all() -> Self {
1886
        Self {
1887
            bits: Self::FEATURES_AND_DESIGN_SPACE.bits
1888
                | Self::CHILD_INDICES.bits
1889
                | Self::ENTRY_ID_DELTA.bits
1890
                | Self::PATCH_FORMAT.bits
1891
                | Self::CODEPOINTS_BIT_1.bits
1892
                | Self::CODEPOINTS_BIT_2.bits
1893
                | Self::IGNORED.bits
1894
                | Self::RESERVED.bits,
1895
        }
1896
    }
1897
1898
    /// Returns the raw value of the flags currently stored.
1899
    #[inline]
1900
591k
    pub const fn bits(&self) -> u8 {
1901
591k
        self.bits
1902
591k
    }
<read_fonts::tables::ift::EntryFormatFlags>::bits
Line
Count
Source
1900
591k
    pub const fn bits(&self) -> u8 {
1901
591k
        self.bits
1902
591k
    }
Unexecuted instantiation: <read_fonts::tables::ift::EntryFormatFlags>::bits
1903
1904
    /// Convert from underlying bit representation, unless that
1905
    /// representation contains bits that do not correspond to a flag.
1906
    #[inline]
1907
    pub const fn from_bits(bits: u8) -> Option<Self> {
1908
        if (bits & !Self::all().bits()) == 0 {
1909
            Some(Self { bits })
1910
        } else {
1911
            None
1912
        }
1913
    }
1914
1915
    /// Convert from underlying bit representation, dropping any bits
1916
    /// that do not correspond to flags.
1917
    #[inline]
1918
    pub const fn from_bits_truncate(bits: u8) -> Self {
1919
        Self {
1920
            bits: bits & Self::all().bits,
1921
        }
1922
    }
1923
1924
    /// Returns `true` if no flags are currently stored.
1925
    #[inline]
1926
    pub const fn is_empty(&self) -> bool {
1927
        self.bits() == Self::empty().bits()
1928
    }
1929
1930
    /// Returns `true` if there are flags common to both `self` and `other`.
1931
    #[inline]
1932
    pub const fn intersects(&self, other: Self) -> bool {
1933
        !(Self {
1934
            bits: self.bits & other.bits,
1935
        })
1936
        .is_empty()
1937
    }
1938
1939
    /// Returns `true` if all of the flags in `other` are contained within `self`.
1940
    #[inline]
1941
1.77M
    pub const fn contains(&self, other: Self) -> bool {
1942
1.77M
        (self.bits & other.bits) == other.bits
1943
1.77M
    }
<read_fonts::tables::ift::EntryFormatFlags>::contains
Line
Count
Source
1941
1.77M
    pub const fn contains(&self, other: Self) -> bool {
1942
1.77M
        (self.bits & other.bits) == other.bits
1943
1.77M
    }
Unexecuted instantiation: <read_fonts::tables::ift::EntryFormatFlags>::contains
1944
1945
    /// Inserts the specified flags in-place.
1946
    #[inline]
1947
    pub fn insert(&mut self, other: Self) {
1948
        self.bits |= other.bits;
1949
    }
1950
1951
    /// Removes the specified flags in-place.
1952
    #[inline]
1953
    pub fn remove(&mut self, other: Self) {
1954
        self.bits &= !other.bits;
1955
    }
1956
1957
    /// Toggles the specified flags in-place.
1958
    #[inline]
1959
    pub fn toggle(&mut self, other: Self) {
1960
        self.bits ^= other.bits;
1961
    }
1962
1963
    /// Returns the intersection between the flags in `self` and
1964
    /// `other`.
1965
    ///
1966
    /// Specifically, the returned set contains only the flags which are
1967
    /// present in *both* `self` *and* `other`.
1968
    ///
1969
    /// This is equivalent to using the `&` operator (e.g.
1970
    /// [`ops::BitAnd`]), as in `flags & other`.
1971
    ///
1972
    /// [`ops::BitAnd`]: https://doc.rust-lang.org/std/ops/trait.BitAnd.html
1973
    #[inline]
1974
    #[must_use]
1975
591k
    pub const fn intersection(self, other: Self) -> Self {
1976
591k
        Self {
1977
591k
            bits: self.bits & other.bits,
1978
591k
        }
1979
591k
    }
1980
1981
    /// Returns the union of between the flags in `self` and `other`.
1982
    ///
1983
    /// Specifically, the returned set contains all flags which are
1984
    /// present in *either* `self` *or* `other`, including any which are
1985
    /// present in both.
1986
    ///
1987
    /// This is equivalent to using the `|` operator (e.g.
1988
    /// [`ops::BitOr`]), as in `flags | other`.
1989
    ///
1990
    /// [`ops::BitOr`]: https://doc.rust-lang.org/std/ops/trait.BitOr.html
1991
    #[inline]
1992
    #[must_use]
1993
    pub const fn union(self, other: Self) -> Self {
1994
        Self {
1995
            bits: self.bits | other.bits,
1996
        }
1997
    }
1998
1999
    /// Returns the difference between the flags in `self` and `other`.
2000
    ///
2001
    /// Specifically, the returned set contains all flags present in
2002
    /// `self`, except for the ones present in `other`.
2003
    ///
2004
    /// It is also conceptually equivalent to the "bit-clear" operation:
2005
    /// `flags & !other` (and this syntax is also supported).
2006
    ///
2007
    /// This is equivalent to using the `-` operator (e.g.
2008
    /// [`ops::Sub`]), as in `flags - other`.
2009
    ///
2010
    /// [`ops::Sub`]: https://doc.rust-lang.org/std/ops/trait.Sub.html
2011
    #[inline]
2012
    #[must_use]
2013
    pub const fn difference(self, other: Self) -> Self {
2014
        Self {
2015
            bits: self.bits & !other.bits,
2016
        }
2017
    }
2018
}
2019
2020
impl std::ops::BitOr for EntryFormatFlags {
2021
    type Output = Self;
2022
2023
    /// Returns the union of the two sets of flags.
2024
    #[inline]
2025
659k
    fn bitor(self, other: EntryFormatFlags) -> Self {
2026
659k
        Self {
2027
659k
            bits: self.bits | other.bits,
2028
659k
        }
2029
659k
    }
2030
}
2031
2032
impl std::ops::BitOrAssign for EntryFormatFlags {
2033
    /// Adds the set of flags.
2034
    #[inline]
2035
    fn bitor_assign(&mut self, other: Self) {
2036
        self.bits |= other.bits;
2037
    }
2038
}
2039
2040
impl std::ops::BitXor for EntryFormatFlags {
2041
    type Output = Self;
2042
2043
    /// Returns the left flags, but with all the right flags toggled.
2044
    #[inline]
2045
    fn bitxor(self, other: Self) -> Self {
2046
        Self {
2047
            bits: self.bits ^ other.bits,
2048
        }
2049
    }
2050
}
2051
2052
impl std::ops::BitXorAssign for EntryFormatFlags {
2053
    /// Toggles the set of flags.
2054
    #[inline]
2055
    fn bitxor_assign(&mut self, other: Self) {
2056
        self.bits ^= other.bits;
2057
    }
2058
}
2059
2060
impl std::ops::BitAnd for EntryFormatFlags {
2061
    type Output = Self;
2062
2063
    /// Returns the intersection between the two sets of flags.
2064
    #[inline]
2065
    fn bitand(self, other: Self) -> Self {
2066
        Self {
2067
            bits: self.bits & other.bits,
2068
        }
2069
    }
2070
}
2071
2072
impl std::ops::BitAndAssign for EntryFormatFlags {
2073
    /// Disables all flags disabled in the set.
2074
    #[inline]
2075
    fn bitand_assign(&mut self, other: Self) {
2076
        self.bits &= other.bits;
2077
    }
2078
}
2079
2080
impl std::ops::Sub for EntryFormatFlags {
2081
    type Output = Self;
2082
2083
    /// Returns the set difference of the two sets of flags.
2084
    #[inline]
2085
    fn sub(self, other: Self) -> Self {
2086
        Self {
2087
            bits: self.bits & !other.bits,
2088
        }
2089
    }
2090
}
2091
2092
impl std::ops::SubAssign for EntryFormatFlags {
2093
    /// Disables all flags enabled in the set.
2094
    #[inline]
2095
    fn sub_assign(&mut self, other: Self) {
2096
        self.bits &= !other.bits;
2097
    }
2098
}
2099
2100
impl std::ops::Not for EntryFormatFlags {
2101
    type Output = Self;
2102
2103
    /// Returns the complement of this set of flags.
2104
    #[inline]
2105
    fn not(self) -> Self {
2106
        Self { bits: !self.bits } & Self::all()
2107
    }
2108
}
2109
2110
impl std::fmt::Debug for EntryFormatFlags {
2111
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
2112
        let members: &[(&str, Self)] = &[
2113
            ("FEATURES_AND_DESIGN_SPACE", Self::FEATURES_AND_DESIGN_SPACE),
2114
            ("CHILD_INDICES", Self::CHILD_INDICES),
2115
            ("ENTRY_ID_DELTA", Self::ENTRY_ID_DELTA),
2116
            ("PATCH_FORMAT", Self::PATCH_FORMAT),
2117
            ("CODEPOINTS_BIT_1", Self::CODEPOINTS_BIT_1),
2118
            ("CODEPOINTS_BIT_2", Self::CODEPOINTS_BIT_2),
2119
            ("IGNORED", Self::IGNORED),
2120
            ("RESERVED", Self::RESERVED),
2121
        ];
2122
        let mut first = true;
2123
        for (name, value) in members {
2124
            if self.contains(*value) {
2125
                if !first {
2126
                    f.write_str(" | ")?;
2127
                }
2128
                first = false;
2129
                f.write_str(name)?;
2130
            }
2131
        }
2132
        if first {
2133
            f.write_str("(empty)")?;
2134
        }
2135
        Ok(())
2136
    }
2137
}
2138
2139
impl std::fmt::Binary for EntryFormatFlags {
2140
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
2141
        std::fmt::Binary::fmt(&self.bits, f)
2142
    }
2143
}
2144
2145
impl std::fmt::Octal for EntryFormatFlags {
2146
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
2147
        std::fmt::Octal::fmt(&self.bits, f)
2148
    }
2149
}
2150
2151
impl std::fmt::LowerHex for EntryFormatFlags {
2152
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
2153
        std::fmt::LowerHex::fmt(&self.bits, f)
2154
    }
2155
}
2156
2157
impl std::fmt::UpperHex for EntryFormatFlags {
2158
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
2159
        std::fmt::UpperHex::fmt(&self.bits, f)
2160
    }
2161
}
2162
2163
impl font_types::Scalar for EntryFormatFlags {
2164
    type Raw = <u8 as font_types::Scalar>::Raw;
2165
    fn to_raw(self) -> Self::Raw {
2166
        self.bits().to_raw()
2167
    }
2168
    fn from_raw(raw: Self::Raw) -> Self {
2169
        let t = <u8>::from_raw(raw);
2170
        Self::from_bits_truncate(t)
2171
    }
2172
}
2173
2174
#[cfg(feature = "experimental_traverse")]
2175
impl<'a> From<EntryFormatFlags> for FieldType<'a> {
2176
    fn from(src: EntryFormatFlags) -> FieldType<'a> {
2177
        src.bits().into()
2178
    }
2179
}
2180
2181
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
2182
#[repr(C)]
2183
#[repr(packed)]
2184
pub struct DesignSpaceSegment {
2185
    pub axis_tag: BigEndian<Tag>,
2186
    pub start: BigEndian<Fixed>,
2187
    pub end: BigEndian<Fixed>,
2188
}
2189
2190
impl DesignSpaceSegment {
2191
    pub fn axis_tag(&self) -> Tag {
2192
        self.axis_tag.get()
2193
    }
2194
2195
    pub fn start(&self) -> Fixed {
2196
        self.start.get()
2197
    }
2198
2199
    pub fn end(&self) -> Fixed {
2200
        self.end.get()
2201
    }
2202
}
2203
2204
impl FixedSize for DesignSpaceSegment {
2205
    const RAW_BYTE_LEN: usize = Tag::RAW_BYTE_LEN + Fixed::RAW_BYTE_LEN + Fixed::RAW_BYTE_LEN;
2206
}
2207
2208
#[cfg(feature = "experimental_traverse")]
2209
impl<'a> SomeRecord<'a> for DesignSpaceSegment {
2210
    fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
2211
        RecordResolver {
2212
            name: "DesignSpaceSegment",
2213
            get_field: Box::new(move |idx, _data| match idx {
2214
                0usize => Some(Field::new("axis_tag", self.axis_tag())),
2215
                1usize => Some(Field::new("start", self.start())),
2216
                2usize => Some(Field::new("end", self.end())),
2217
                _ => None,
2218
            }),
2219
            data,
2220
        }
2221
    }
2222
}
2223
2224
impl<'a> MinByteRange<'a> for IdStringData<'a> {
2225
    fn min_byte_range(&self) -> Range<usize> {
2226
        0..self.id_data_byte_range().end
2227
    }
2228
    fn min_table_bytes(&self) -> &'a [u8] {
2229
        let range = self.min_byte_range();
2230
        self.data.as_bytes().get(range).unwrap_or_default()
2231
    }
2232
}
2233
2234
impl ReadArgs for IdStringData<'_> {
2235
    type Args = ();
2236
}
2237
2238
impl<'a> FontRead<'a> for IdStringData<'a> {
2239
    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
2240
        #[allow(clippy::absurd_extreme_comparisons)]
2241
        if data.len() < Self::MIN_SIZE {
2242
            return Err(ReadError::OutOfBounds);
2243
        }
2244
        Ok(Self { data })
2245
    }
2246
}
2247
2248
#[derive(Clone)]
2249
pub struct IdStringData<'a> {
2250
    data: FontData<'a>,
2251
}
2252
2253
#[allow(clippy::needless_lifetimes)]
2254
impl<'a> IdStringData<'a> {
2255
    pub const MIN_SIZE: usize = 0;
2256
    basic_table_impls!(impl_the_methods);
2257
2258
    pub fn id_data(&self) -> &'a [u8] {
2259
        let range = self.id_data_byte_range();
2260
        self.data.read_array(range).ok().unwrap_or_default()
2261
    }
2262
2263
    pub fn id_data_byte_range(&self) -> Range<usize> {
2264
        let start = 0;
2265
        let end =
2266
            start + self.data.len().saturating_sub(start) / u8::RAW_BYTE_LEN * u8::RAW_BYTE_LEN;
2267
        start..end
2268
    }
2269
}
2270
2271
#[allow(clippy::absurd_extreme_comparisons)]
2272
const _: () = assert!(FontData::default_data_long_enough(IdStringData::MIN_SIZE));
2273
2274
impl Default for IdStringData<'_> {
2275
    fn default() -> Self {
2276
        Self {
2277
            data: FontData::default_table_data(),
2278
        }
2279
    }
2280
}
2281
2282
#[cfg(feature = "experimental_traverse")]
2283
impl<'a> SomeTable<'a> for IdStringData<'a> {
2284
    fn type_name(&self) -> &str {
2285
        "IdStringData"
2286
    }
2287
    fn get_field(&self, idx: usize) -> Option<Field<'a>> {
2288
        match idx {
2289
            0usize => Some(Field::new("id_data", self.id_data())),
2290
            _ => None,
2291
        }
2292
    }
2293
}
2294
2295
#[cfg(feature = "experimental_traverse")]
2296
#[allow(clippy::needless_lifetimes)]
2297
impl<'a> std::fmt::Debug for IdStringData<'a> {
2298
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2299
        (self as &dyn SomeTable<'a>).fmt(f)
2300
    }
2301
}
2302
2303
impl<'a> MinByteRange<'a> for TableKeyedPatch<'a> {
2304
    fn min_byte_range(&self) -> Range<usize> {
2305
        0..self.patch_offsets_byte_range().end
2306
    }
2307
    fn min_table_bytes(&self) -> &'a [u8] {
2308
        let range = self.min_byte_range();
2309
        self.data.as_bytes().get(range).unwrap_or_default()
2310
    }
2311
}
2312
2313
impl ReadArgs for TableKeyedPatch<'_> {
2314
    type Args = ();
2315
}
2316
2317
impl<'a> FontRead<'a> for TableKeyedPatch<'a> {
2318
    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
2319
        #[allow(clippy::absurd_extreme_comparisons)]
2320
        if data.len() < Self::MIN_SIZE {
2321
            return Err(ReadError::OutOfBounds);
2322
        }
2323
        Ok(Self { data })
2324
    }
2325
}
2326
2327
/// [Table Keyed Patch](https://w3c.github.io/IFT/Overview.html#table-keyed)
2328
#[derive(Clone)]
2329
pub struct TableKeyedPatch<'a> {
2330
    data: FontData<'a>,
2331
}
2332
2333
#[allow(clippy::needless_lifetimes)]
2334
impl<'a> TableKeyedPatch<'a> {
2335
    pub const MIN_SIZE: usize =
2336
        (Tag::RAW_BYTE_LEN + u32::RAW_BYTE_LEN + CompatibilityId::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
2337
    basic_table_impls!(impl_the_methods);
2338
2339
    pub fn format(&self) -> Tag {
2340
        let range = self.format_byte_range();
2341
        self.data.read_at(range.start).ok().unwrap()
2342
    }
2343
2344
    /// Unique ID that identifies compatible patches.
2345
    pub fn compatibility_id(&self) -> CompatibilityId {
2346
        let range = self.compatibility_id_byte_range();
2347
        self.data.read_at(range.start).ok().unwrap()
2348
    }
2349
2350
    pub fn patches_count(&self) -> u16 {
2351
        let range = self.patches_count_byte_range();
2352
        self.data.read_at(range.start).ok().unwrap()
2353
    }
2354
2355
    pub fn patch_offsets(&self) -> &'a [BigEndian<Offset32>] {
2356
        let range = self.patch_offsets_byte_range();
2357
        self.data.read_array(range).ok().unwrap_or_default()
2358
    }
2359
2360
    /// A dynamically resolving wrapper for [`patch_offsets`][Self::patch_offsets].
2361
    pub fn patches(&self) -> ArrayOfOffsets<'a, TablePatch<'a>, Offset32> {
2362
        let data = self.data;
2363
        let offsets = self.patch_offsets();
2364
        ArrayOfOffsets::new(offsets, data, ())
2365
    }
2366
2367
    pub fn format_byte_range(&self) -> Range<usize> {
2368
        let start = 0;
2369
        let end = start + Tag::RAW_BYTE_LEN;
2370
        start..end
2371
    }
2372
2373
    pub fn _reserved_byte_range(&self) -> Range<usize> {
2374
        let start = self.format_byte_range().end;
2375
        let end = start + u32::RAW_BYTE_LEN;
2376
        start..end
2377
    }
2378
2379
    pub fn compatibility_id_byte_range(&self) -> Range<usize> {
2380
        let start = self._reserved_byte_range().end;
2381
        let end = start + CompatibilityId::RAW_BYTE_LEN;
2382
        start..end
2383
    }
2384
2385
    pub fn patches_count_byte_range(&self) -> Range<usize> {
2386
        let start = self.compatibility_id_byte_range().end;
2387
        let end = start + u16::RAW_BYTE_LEN;
2388
        start..end
2389
    }
2390
2391
    pub fn patch_offsets_byte_range(&self) -> Range<usize> {
2392
        let patches_count = self.patches_count();
2393
        let start = self.patches_count_byte_range().end;
2394
        let end = start
2395
            + (transforms::add(patches_count, 1_usize)).saturating_mul(Offset32::RAW_BYTE_LEN);
2396
        start..end
2397
    }
2398
}
2399
2400
const _: () = assert!(FontData::default_data_long_enough(
2401
    TableKeyedPatch::MIN_SIZE
2402
));
2403
2404
impl Default for TableKeyedPatch<'_> {
2405
    fn default() -> Self {
2406
        Self {
2407
            data: FontData::default_table_data(),
2408
        }
2409
    }
2410
}
2411
2412
#[cfg(feature = "experimental_traverse")]
2413
impl<'a> SomeTable<'a> for TableKeyedPatch<'a> {
2414
    fn type_name(&self) -> &str {
2415
        "TableKeyedPatch"
2416
    }
2417
    fn get_field(&self, idx: usize) -> Option<Field<'a>> {
2418
        match idx {
2419
            0usize => Some(Field::new("format", self.format())),
2420
            1usize => Some(Field::new(
2421
                "compatibility_id",
2422
                traversal::FieldType::Unknown,
2423
            )),
2424
            2usize => Some(Field::new("patches_count", self.patches_count())),
2425
            3usize => Some(Field::new("patch_offsets", FieldType::from(self.patches()))),
2426
            _ => None,
2427
        }
2428
    }
2429
}
2430
2431
#[cfg(feature = "experimental_traverse")]
2432
#[allow(clippy::needless_lifetimes)]
2433
impl<'a> std::fmt::Debug for TableKeyedPatch<'a> {
2434
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2435
        (self as &dyn SomeTable<'a>).fmt(f)
2436
    }
2437
}
2438
2439
impl<'a> MinByteRange<'a> for TablePatch<'a> {
2440
    fn min_byte_range(&self) -> Range<usize> {
2441
        0..self.brotli_stream_byte_range().end
2442
    }
2443
    fn min_table_bytes(&self) -> &'a [u8] {
2444
        let range = self.min_byte_range();
2445
        self.data.as_bytes().get(range).unwrap_or_default()
2446
    }
2447
}
2448
2449
impl ReadArgs for TablePatch<'_> {
2450
    type Args = ();
2451
}
2452
2453
impl<'a> FontRead<'a> for TablePatch<'a> {
2454
    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
2455
        #[allow(clippy::absurd_extreme_comparisons)]
2456
        if data.len() < Self::MIN_SIZE {
2457
            return Err(ReadError::OutOfBounds);
2458
        }
2459
        Ok(Self { data })
2460
    }
2461
}
2462
2463
/// [TablePatch](https://w3c.github.io/IFT/Overview.html#tablepatch)
2464
#[derive(Clone)]
2465
pub struct TablePatch<'a> {
2466
    data: FontData<'a>,
2467
}
2468
2469
#[allow(clippy::needless_lifetimes)]
2470
impl<'a> TablePatch<'a> {
2471
    pub const MIN_SIZE: usize =
2472
        (Tag::RAW_BYTE_LEN + TablePatchFlags::RAW_BYTE_LEN + u32::RAW_BYTE_LEN);
2473
    basic_table_impls!(impl_the_methods);
2474
2475
    pub fn tag(&self) -> Tag {
2476
        let range = self.tag_byte_range();
2477
        self.data.read_at(range.start).ok().unwrap()
2478
    }
2479
2480
    pub fn flags(&self) -> TablePatchFlags {
2481
        let range = self.flags_byte_range();
2482
        self.data.read_at(range.start).ok().unwrap()
2483
    }
2484
2485
    pub fn max_uncompressed_length(&self) -> u32 {
2486
        let range = self.max_uncompressed_length_byte_range();
2487
        self.data.read_at(range.start).ok().unwrap()
2488
    }
2489
2490
    pub fn brotli_stream(&self) -> &'a [u8] {
2491
        let range = self.brotli_stream_byte_range();
2492
        self.data.read_array(range).ok().unwrap_or_default()
2493
    }
2494
2495
    pub fn tag_byte_range(&self) -> Range<usize> {
2496
        let start = 0;
2497
        let end = start + Tag::RAW_BYTE_LEN;
2498
        start..end
2499
    }
2500
2501
    pub fn flags_byte_range(&self) -> Range<usize> {
2502
        let start = self.tag_byte_range().end;
2503
        let end = start + TablePatchFlags::RAW_BYTE_LEN;
2504
        start..end
2505
    }
2506
2507
    pub fn max_uncompressed_length_byte_range(&self) -> Range<usize> {
2508
        let start = self.flags_byte_range().end;
2509
        let end = start + u32::RAW_BYTE_LEN;
2510
        start..end
2511
    }
2512
2513
    pub fn brotli_stream_byte_range(&self) -> Range<usize> {
2514
        let start = self.max_uncompressed_length_byte_range().end;
2515
        let end =
2516
            start + self.data.len().saturating_sub(start) / u8::RAW_BYTE_LEN * u8::RAW_BYTE_LEN;
2517
        start..end
2518
    }
2519
}
2520
2521
const _: () = assert!(FontData::default_data_long_enough(TablePatch::MIN_SIZE));
2522
2523
impl Default for TablePatch<'_> {
2524
    fn default() -> Self {
2525
        Self {
2526
            data: FontData::default_table_data(),
2527
        }
2528
    }
2529
}
2530
2531
#[cfg(feature = "experimental_traverse")]
2532
impl<'a> SomeTable<'a> for TablePatch<'a> {
2533
    fn type_name(&self) -> &str {
2534
        "TablePatch"
2535
    }
2536
    fn get_field(&self, idx: usize) -> Option<Field<'a>> {
2537
        match idx {
2538
            0usize => Some(Field::new("tag", self.tag())),
2539
            1usize => Some(Field::new("flags", self.flags())),
2540
            2usize => Some(Field::new(
2541
                "max_uncompressed_length",
2542
                self.max_uncompressed_length(),
2543
            )),
2544
            3usize => Some(Field::new("brotli_stream", self.brotli_stream())),
2545
            _ => None,
2546
        }
2547
    }
2548
}
2549
2550
#[cfg(feature = "experimental_traverse")]
2551
#[allow(clippy::needless_lifetimes)]
2552
impl<'a> std::fmt::Debug for TablePatch<'a> {
2553
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2554
        (self as &dyn SomeTable<'a>).fmt(f)
2555
    }
2556
}
2557
2558
#[derive(Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash, bytemuck :: AnyBitPattern)]
2559
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
2560
#[repr(transparent)]
2561
pub struct TablePatchFlags {
2562
    bits: u8,
2563
}
2564
2565
impl TablePatchFlags {
2566
    pub const REPLACE_TABLE: Self = Self { bits: 0b01 };
2567
2568
    pub const DROP_TABLE: Self = Self { bits: 0b10 };
2569
}
2570
2571
impl TablePatchFlags {
2572
    ///  Returns an empty set of flags.
2573
    #[inline]
2574
    pub const fn empty() -> Self {
2575
        Self { bits: 0 }
2576
    }
2577
2578
    /// Returns the set containing all flags.
2579
    #[inline]
2580
    pub const fn all() -> Self {
2581
        Self {
2582
            bits: Self::REPLACE_TABLE.bits | Self::DROP_TABLE.bits,
2583
        }
2584
    }
2585
2586
    /// Returns the raw value of the flags currently stored.
2587
    #[inline]
2588
0
    pub const fn bits(&self) -> u8 {
2589
0
        self.bits
2590
0
    }
2591
2592
    /// Convert from underlying bit representation, unless that
2593
    /// representation contains bits that do not correspond to a flag.
2594
    #[inline]
2595
    pub const fn from_bits(bits: u8) -> Option<Self> {
2596
        if (bits & !Self::all().bits()) == 0 {
2597
            Some(Self { bits })
2598
        } else {
2599
            None
2600
        }
2601
    }
2602
2603
    /// Convert from underlying bit representation, dropping any bits
2604
    /// that do not correspond to flags.
2605
    #[inline]
2606
    pub const fn from_bits_truncate(bits: u8) -> Self {
2607
        Self {
2608
            bits: bits & Self::all().bits,
2609
        }
2610
    }
2611
2612
    /// Returns `true` if no flags are currently stored.
2613
    #[inline]
2614
    pub const fn is_empty(&self) -> bool {
2615
        self.bits() == Self::empty().bits()
2616
    }
2617
2618
    /// Returns `true` if there are flags common to both `self` and `other`.
2619
    #[inline]
2620
    pub const fn intersects(&self, other: Self) -> bool {
2621
        !(Self {
2622
            bits: self.bits & other.bits,
2623
        })
2624
        .is_empty()
2625
    }
2626
2627
    /// Returns `true` if all of the flags in `other` are contained within `self`.
2628
    #[inline]
2629
0
    pub const fn contains(&self, other: Self) -> bool {
2630
0
        (self.bits & other.bits) == other.bits
2631
0
    }
Unexecuted instantiation: <read_fonts::tables::ift::TablePatchFlags>::contains
Unexecuted instantiation: <read_fonts::tables::ift::TablePatchFlags>::contains
2632
2633
    /// Inserts the specified flags in-place.
2634
    #[inline]
2635
    pub fn insert(&mut self, other: Self) {
2636
        self.bits |= other.bits;
2637
    }
2638
2639
    /// Removes the specified flags in-place.
2640
    #[inline]
2641
    pub fn remove(&mut self, other: Self) {
2642
        self.bits &= !other.bits;
2643
    }
2644
2645
    /// Toggles the specified flags in-place.
2646
    #[inline]
2647
    pub fn toggle(&mut self, other: Self) {
2648
        self.bits ^= other.bits;
2649
    }
2650
2651
    /// Returns the intersection between the flags in `self` and
2652
    /// `other`.
2653
    ///
2654
    /// Specifically, the returned set contains only the flags which are
2655
    /// present in *both* `self` *and* `other`.
2656
    ///
2657
    /// This is equivalent to using the `&` operator (e.g.
2658
    /// [`ops::BitAnd`]), as in `flags & other`.
2659
    ///
2660
    /// [`ops::BitAnd`]: https://doc.rust-lang.org/std/ops/trait.BitAnd.html
2661
    #[inline]
2662
    #[must_use]
2663
    pub const fn intersection(self, other: Self) -> Self {
2664
        Self {
2665
            bits: self.bits & other.bits,
2666
        }
2667
    }
2668
2669
    /// Returns the union of between the flags in `self` and `other`.
2670
    ///
2671
    /// Specifically, the returned set contains all flags which are
2672
    /// present in *either* `self` *or* `other`, including any which are
2673
    /// present in both.
2674
    ///
2675
    /// This is equivalent to using the `|` operator (e.g.
2676
    /// [`ops::BitOr`]), as in `flags | other`.
2677
    ///
2678
    /// [`ops::BitOr`]: https://doc.rust-lang.org/std/ops/trait.BitOr.html
2679
    #[inline]
2680
    #[must_use]
2681
    pub const fn union(self, other: Self) -> Self {
2682
        Self {
2683
            bits: self.bits | other.bits,
2684
        }
2685
    }
2686
2687
    /// Returns the difference between the flags in `self` and `other`.
2688
    ///
2689
    /// Specifically, the returned set contains all flags present in
2690
    /// `self`, except for the ones present in `other`.
2691
    ///
2692
    /// It is also conceptually equivalent to the "bit-clear" operation:
2693
    /// `flags & !other` (and this syntax is also supported).
2694
    ///
2695
    /// This is equivalent to using the `-` operator (e.g.
2696
    /// [`ops::Sub`]), as in `flags - other`.
2697
    ///
2698
    /// [`ops::Sub`]: https://doc.rust-lang.org/std/ops/trait.Sub.html
2699
    #[inline]
2700
    #[must_use]
2701
    pub const fn difference(self, other: Self) -> Self {
2702
        Self {
2703
            bits: self.bits & !other.bits,
2704
        }
2705
    }
2706
}
2707
2708
impl std::ops::BitOr for TablePatchFlags {
2709
    type Output = Self;
2710
2711
    /// Returns the union of the two sets of flags.
2712
    #[inline]
2713
    fn bitor(self, other: TablePatchFlags) -> Self {
2714
        Self {
2715
            bits: self.bits | other.bits,
2716
        }
2717
    }
2718
}
2719
2720
impl std::ops::BitOrAssign for TablePatchFlags {
2721
    /// Adds the set of flags.
2722
    #[inline]
2723
    fn bitor_assign(&mut self, other: Self) {
2724
        self.bits |= other.bits;
2725
    }
2726
}
2727
2728
impl std::ops::BitXor for TablePatchFlags {
2729
    type Output = Self;
2730
2731
    /// Returns the left flags, but with all the right flags toggled.
2732
    #[inline]
2733
    fn bitxor(self, other: Self) -> Self {
2734
        Self {
2735
            bits: self.bits ^ other.bits,
2736
        }
2737
    }
2738
}
2739
2740
impl std::ops::BitXorAssign for TablePatchFlags {
2741
    /// Toggles the set of flags.
2742
    #[inline]
2743
    fn bitxor_assign(&mut self, other: Self) {
2744
        self.bits ^= other.bits;
2745
    }
2746
}
2747
2748
impl std::ops::BitAnd for TablePatchFlags {
2749
    type Output = Self;
2750
2751
    /// Returns the intersection between the two sets of flags.
2752
    #[inline]
2753
    fn bitand(self, other: Self) -> Self {
2754
        Self {
2755
            bits: self.bits & other.bits,
2756
        }
2757
    }
2758
}
2759
2760
impl std::ops::BitAndAssign for TablePatchFlags {
2761
    /// Disables all flags disabled in the set.
2762
    #[inline]
2763
    fn bitand_assign(&mut self, other: Self) {
2764
        self.bits &= other.bits;
2765
    }
2766
}
2767
2768
impl std::ops::Sub for TablePatchFlags {
2769
    type Output = Self;
2770
2771
    /// Returns the set difference of the two sets of flags.
2772
    #[inline]
2773
    fn sub(self, other: Self) -> Self {
2774
        Self {
2775
            bits: self.bits & !other.bits,
2776
        }
2777
    }
2778
}
2779
2780
impl std::ops::SubAssign for TablePatchFlags {
2781
    /// Disables all flags enabled in the set.
2782
    #[inline]
2783
    fn sub_assign(&mut self, other: Self) {
2784
        self.bits &= !other.bits;
2785
    }
2786
}
2787
2788
impl std::ops::Not for TablePatchFlags {
2789
    type Output = Self;
2790
2791
    /// Returns the complement of this set of flags.
2792
    #[inline]
2793
    fn not(self) -> Self {
2794
        Self { bits: !self.bits } & Self::all()
2795
    }
2796
}
2797
2798
impl std::fmt::Debug for TablePatchFlags {
2799
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
2800
        let members: &[(&str, Self)] = &[
2801
            ("REPLACE_TABLE", Self::REPLACE_TABLE),
2802
            ("DROP_TABLE", Self::DROP_TABLE),
2803
        ];
2804
        let mut first = true;
2805
        for (name, value) in members {
2806
            if self.contains(*value) {
2807
                if !first {
2808
                    f.write_str(" | ")?;
2809
                }
2810
                first = false;
2811
                f.write_str(name)?;
2812
            }
2813
        }
2814
        if first {
2815
            f.write_str("(empty)")?;
2816
        }
2817
        Ok(())
2818
    }
2819
}
2820
2821
impl std::fmt::Binary for TablePatchFlags {
2822
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
2823
        std::fmt::Binary::fmt(&self.bits, f)
2824
    }
2825
}
2826
2827
impl std::fmt::Octal for TablePatchFlags {
2828
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
2829
        std::fmt::Octal::fmt(&self.bits, f)
2830
    }
2831
}
2832
2833
impl std::fmt::LowerHex for TablePatchFlags {
2834
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
2835
        std::fmt::LowerHex::fmt(&self.bits, f)
2836
    }
2837
}
2838
2839
impl std::fmt::UpperHex for TablePatchFlags {
2840
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
2841
        std::fmt::UpperHex::fmt(&self.bits, f)
2842
    }
2843
}
2844
2845
impl font_types::Scalar for TablePatchFlags {
2846
    type Raw = <u8 as font_types::Scalar>::Raw;
2847
    fn to_raw(self) -> Self::Raw {
2848
        self.bits().to_raw()
2849
    }
2850
    fn from_raw(raw: Self::Raw) -> Self {
2851
        let t = <u8>::from_raw(raw);
2852
        Self::from_bits_truncate(t)
2853
    }
2854
}
2855
2856
#[cfg(feature = "experimental_traverse")]
2857
impl<'a> From<TablePatchFlags> for FieldType<'a> {
2858
    fn from(src: TablePatchFlags) -> FieldType<'a> {
2859
        src.bits().into()
2860
    }
2861
}
2862
2863
impl<'a> MinByteRange<'a> for GlyphKeyedPatch<'a> {
2864
    fn min_byte_range(&self) -> Range<usize> {
2865
        0..self.brotli_stream_byte_range().end
2866
    }
2867
    fn min_table_bytes(&self) -> &'a [u8] {
2868
        let range = self.min_byte_range();
2869
        self.data.as_bytes().get(range).unwrap_or_default()
2870
    }
2871
}
2872
2873
impl ReadArgs for GlyphKeyedPatch<'_> {
2874
    type Args = ();
2875
}
2876
2877
impl<'a> FontRead<'a> for GlyphKeyedPatch<'a> {
2878
    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
2879
        #[allow(clippy::absurd_extreme_comparisons)]
2880
        if data.len() < Self::MIN_SIZE {
2881
            return Err(ReadError::OutOfBounds);
2882
        }
2883
        Ok(Self { data })
2884
    }
2885
}
2886
2887
/// [Glyph Keyed Patch](https://w3c.github.io/IFT/Overview.html#glyph-keyed)
2888
#[derive(Clone)]
2889
pub struct GlyphKeyedPatch<'a> {
2890
    data: FontData<'a>,
2891
}
2892
2893
#[allow(clippy::needless_lifetimes)]
2894
impl<'a> GlyphKeyedPatch<'a> {
2895
    pub const MIN_SIZE: usize = (Tag::RAW_BYTE_LEN
2896
        + u32::RAW_BYTE_LEN
2897
        + GlyphKeyedFlags::RAW_BYTE_LEN
2898
        + CompatibilityId::RAW_BYTE_LEN
2899
        + u32::RAW_BYTE_LEN);
2900
    basic_table_impls!(impl_the_methods);
2901
2902
    pub fn format(&self) -> Tag {
2903
        let range = self.format_byte_range();
2904
        self.data.read_at(range.start).ok().unwrap()
2905
    }
2906
2907
    pub fn flags(&self) -> GlyphKeyedFlags {
2908
        let range = self.flags_byte_range();
2909
        self.data.read_at(range.start).ok().unwrap()
2910
    }
2911
2912
    pub fn compatibility_id(&self) -> CompatibilityId {
2913
        let range = self.compatibility_id_byte_range();
2914
        self.data.read_at(range.start).ok().unwrap()
2915
    }
2916
2917
    pub fn max_uncompressed_length(&self) -> u32 {
2918
        let range = self.max_uncompressed_length_byte_range();
2919
        self.data.read_at(range.start).ok().unwrap()
2920
    }
2921
2922
    pub fn brotli_stream(&self) -> &'a [u8] {
2923
        let range = self.brotli_stream_byte_range();
2924
        self.data.read_array(range).ok().unwrap_or_default()
2925
    }
2926
2927
    pub fn format_byte_range(&self) -> Range<usize> {
2928
        let start = 0;
2929
        let end = start + Tag::RAW_BYTE_LEN;
2930
        start..end
2931
    }
2932
2933
    pub fn _reserved_byte_range(&self) -> Range<usize> {
2934
        let start = self.format_byte_range().end;
2935
        let end = start + u32::RAW_BYTE_LEN;
2936
        start..end
2937
    }
2938
2939
    pub fn flags_byte_range(&self) -> Range<usize> {
2940
        let start = self._reserved_byte_range().end;
2941
        let end = start + GlyphKeyedFlags::RAW_BYTE_LEN;
2942
        start..end
2943
    }
2944
2945
    pub fn compatibility_id_byte_range(&self) -> Range<usize> {
2946
        let start = self.flags_byte_range().end;
2947
        let end = start + CompatibilityId::RAW_BYTE_LEN;
2948
        start..end
2949
    }
2950
2951
    pub fn max_uncompressed_length_byte_range(&self) -> Range<usize> {
2952
        let start = self.compatibility_id_byte_range().end;
2953
        let end = start + u32::RAW_BYTE_LEN;
2954
        start..end
2955
    }
2956
2957
    pub fn brotli_stream_byte_range(&self) -> Range<usize> {
2958
        let start = self.max_uncompressed_length_byte_range().end;
2959
        let end =
2960
            start + self.data.len().saturating_sub(start) / u8::RAW_BYTE_LEN * u8::RAW_BYTE_LEN;
2961
        start..end
2962
    }
2963
}
2964
2965
const _: () = assert!(FontData::default_data_long_enough(
2966
    GlyphKeyedPatch::MIN_SIZE
2967
));
2968
2969
impl Default for GlyphKeyedPatch<'_> {
2970
    fn default() -> Self {
2971
        Self {
2972
            data: FontData::default_table_data(),
2973
        }
2974
    }
2975
}
2976
2977
#[cfg(feature = "experimental_traverse")]
2978
impl<'a> SomeTable<'a> for GlyphKeyedPatch<'a> {
2979
    fn type_name(&self) -> &str {
2980
        "GlyphKeyedPatch"
2981
    }
2982
    fn get_field(&self, idx: usize) -> Option<Field<'a>> {
2983
        match idx {
2984
            0usize => Some(Field::new("format", self.format())),
2985
            1usize => Some(Field::new("flags", self.flags())),
2986
            2usize => Some(Field::new(
2987
                "compatibility_id",
2988
                traversal::FieldType::Unknown,
2989
            )),
2990
            3usize => Some(Field::new(
2991
                "max_uncompressed_length",
2992
                self.max_uncompressed_length(),
2993
            )),
2994
            4usize => Some(Field::new("brotli_stream", self.brotli_stream())),
2995
            _ => None,
2996
        }
2997
    }
2998
}
2999
3000
#[cfg(feature = "experimental_traverse")]
3001
#[allow(clippy::needless_lifetimes)]
3002
impl<'a> std::fmt::Debug for GlyphKeyedPatch<'a> {
3003
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3004
        (self as &dyn SomeTable<'a>).fmt(f)
3005
    }
3006
}
3007
3008
#[derive(Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash, bytemuck :: AnyBitPattern)]
3009
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
3010
#[repr(transparent)]
3011
pub struct GlyphKeyedFlags {
3012
    bits: u8,
3013
}
3014
3015
impl GlyphKeyedFlags {
3016
    pub const NONE: Self = Self { bits: 0b0 };
3017
3018
    pub const WIDE_GLYPH_IDS: Self = Self { bits: 0b1 };
3019
}
3020
3021
impl GlyphKeyedFlags {
3022
    ///  Returns an empty set of flags.
3023
    #[inline]
3024
    pub const fn empty() -> Self {
3025
        Self { bits: 0 }
3026
    }
3027
3028
    /// Returns the set containing all flags.
3029
    #[inline]
3030
    pub const fn all() -> Self {
3031
        Self {
3032
            bits: Self::NONE.bits | Self::WIDE_GLYPH_IDS.bits,
3033
        }
3034
    }
3035
3036
    /// Returns the raw value of the flags currently stored.
3037
    #[inline]
3038
0
    pub const fn bits(&self) -> u8 {
3039
0
        self.bits
3040
0
    }
3041
3042
    /// Convert from underlying bit representation, unless that
3043
    /// representation contains bits that do not correspond to a flag.
3044
    #[inline]
3045
    pub const fn from_bits(bits: u8) -> Option<Self> {
3046
        if (bits & !Self::all().bits()) == 0 {
3047
            Some(Self { bits })
3048
        } else {
3049
            None
3050
        }
3051
    }
3052
3053
    /// Convert from underlying bit representation, dropping any bits
3054
    /// that do not correspond to flags.
3055
    #[inline]
3056
    pub const fn from_bits_truncate(bits: u8) -> Self {
3057
        Self {
3058
            bits: bits & Self::all().bits,
3059
        }
3060
    }
3061
3062
    /// Returns `true` if no flags are currently stored.
3063
    #[inline]
3064
    pub const fn is_empty(&self) -> bool {
3065
        self.bits() == Self::empty().bits()
3066
    }
3067
3068
    /// Returns `true` if there are flags common to both `self` and `other`.
3069
    #[inline]
3070
    pub const fn intersects(&self, other: Self) -> bool {
3071
        !(Self {
3072
            bits: self.bits & other.bits,
3073
        })
3074
        .is_empty()
3075
    }
3076
3077
    /// Returns `true` if all of the flags in `other` are contained within `self`.
3078
    #[inline]
3079
    pub const fn contains(&self, other: Self) -> bool {
3080
        (self.bits & other.bits) == other.bits
3081
    }
3082
3083
    /// Inserts the specified flags in-place.
3084
    #[inline]
3085
    pub fn insert(&mut self, other: Self) {
3086
        self.bits |= other.bits;
3087
    }
3088
3089
    /// Removes the specified flags in-place.
3090
    #[inline]
3091
    pub fn remove(&mut self, other: Self) {
3092
        self.bits &= !other.bits;
3093
    }
3094
3095
    /// Toggles the specified flags in-place.
3096
    #[inline]
3097
    pub fn toggle(&mut self, other: Self) {
3098
        self.bits ^= other.bits;
3099
    }
3100
3101
    /// Returns the intersection between the flags in `self` and
3102
    /// `other`.
3103
    ///
3104
    /// Specifically, the returned set contains only the flags which are
3105
    /// present in *both* `self` *and* `other`.
3106
    ///
3107
    /// This is equivalent to using the `&` operator (e.g.
3108
    /// [`ops::BitAnd`]), as in `flags & other`.
3109
    ///
3110
    /// [`ops::BitAnd`]: https://doc.rust-lang.org/std/ops/trait.BitAnd.html
3111
    #[inline]
3112
    #[must_use]
3113
    pub const fn intersection(self, other: Self) -> Self {
3114
        Self {
3115
            bits: self.bits & other.bits,
3116
        }
3117
    }
3118
3119
    /// Returns the union of between the flags in `self` and `other`.
3120
    ///
3121
    /// Specifically, the returned set contains all flags which are
3122
    /// present in *either* `self` *or* `other`, including any which are
3123
    /// present in both.
3124
    ///
3125
    /// This is equivalent to using the `|` operator (e.g.
3126
    /// [`ops::BitOr`]), as in `flags | other`.
3127
    ///
3128
    /// [`ops::BitOr`]: https://doc.rust-lang.org/std/ops/trait.BitOr.html
3129
    #[inline]
3130
    #[must_use]
3131
    pub const fn union(self, other: Self) -> Self {
3132
        Self {
3133
            bits: self.bits | other.bits,
3134
        }
3135
    }
3136
3137
    /// Returns the difference between the flags in `self` and `other`.
3138
    ///
3139
    /// Specifically, the returned set contains all flags present in
3140
    /// `self`, except for the ones present in `other`.
3141
    ///
3142
    /// It is also conceptually equivalent to the "bit-clear" operation:
3143
    /// `flags & !other` (and this syntax is also supported).
3144
    ///
3145
    /// This is equivalent to using the `-` operator (e.g.
3146
    /// [`ops::Sub`]), as in `flags - other`.
3147
    ///
3148
    /// [`ops::Sub`]: https://doc.rust-lang.org/std/ops/trait.Sub.html
3149
    #[inline]
3150
    #[must_use]
3151
    pub const fn difference(self, other: Self) -> Self {
3152
        Self {
3153
            bits: self.bits & !other.bits,
3154
        }
3155
    }
3156
}
3157
3158
impl std::ops::BitOr for GlyphKeyedFlags {
3159
    type Output = Self;
3160
3161
    /// Returns the union of the two sets of flags.
3162
    #[inline]
3163
    fn bitor(self, other: GlyphKeyedFlags) -> Self {
3164
        Self {
3165
            bits: self.bits | other.bits,
3166
        }
3167
    }
3168
}
3169
3170
impl std::ops::BitOrAssign for GlyphKeyedFlags {
3171
    /// Adds the set of flags.
3172
    #[inline]
3173
    fn bitor_assign(&mut self, other: Self) {
3174
        self.bits |= other.bits;
3175
    }
3176
}
3177
3178
impl std::ops::BitXor for GlyphKeyedFlags {
3179
    type Output = Self;
3180
3181
    /// Returns the left flags, but with all the right flags toggled.
3182
    #[inline]
3183
    fn bitxor(self, other: Self) -> Self {
3184
        Self {
3185
            bits: self.bits ^ other.bits,
3186
        }
3187
    }
3188
}
3189
3190
impl std::ops::BitXorAssign for GlyphKeyedFlags {
3191
    /// Toggles the set of flags.
3192
    #[inline]
3193
    fn bitxor_assign(&mut self, other: Self) {
3194
        self.bits ^= other.bits;
3195
    }
3196
}
3197
3198
impl std::ops::BitAnd for GlyphKeyedFlags {
3199
    type Output = Self;
3200
3201
    /// Returns the intersection between the two sets of flags.
3202
    #[inline]
3203
    fn bitand(self, other: Self) -> Self {
3204
        Self {
3205
            bits: self.bits & other.bits,
3206
        }
3207
    }
3208
}
3209
3210
impl std::ops::BitAndAssign for GlyphKeyedFlags {
3211
    /// Disables all flags disabled in the set.
3212
    #[inline]
3213
    fn bitand_assign(&mut self, other: Self) {
3214
        self.bits &= other.bits;
3215
    }
3216
}
3217
3218
impl std::ops::Sub for GlyphKeyedFlags {
3219
    type Output = Self;
3220
3221
    /// Returns the set difference of the two sets of flags.
3222
    #[inline]
3223
    fn sub(self, other: Self) -> Self {
3224
        Self {
3225
            bits: self.bits & !other.bits,
3226
        }
3227
    }
3228
}
3229
3230
impl std::ops::SubAssign for GlyphKeyedFlags {
3231
    /// Disables all flags enabled in the set.
3232
    #[inline]
3233
    fn sub_assign(&mut self, other: Self) {
3234
        self.bits &= !other.bits;
3235
    }
3236
}
3237
3238
impl std::ops::Not for GlyphKeyedFlags {
3239
    type Output = Self;
3240
3241
    /// Returns the complement of this set of flags.
3242
    #[inline]
3243
    fn not(self) -> Self {
3244
        Self { bits: !self.bits } & Self::all()
3245
    }
3246
}
3247
3248
impl std::fmt::Debug for GlyphKeyedFlags {
3249
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
3250
        let members: &[(&str, Self)] = &[
3251
            ("NONE", Self::NONE),
3252
            ("WIDE_GLYPH_IDS", Self::WIDE_GLYPH_IDS),
3253
        ];
3254
        let mut first = true;
3255
        for (name, value) in members {
3256
            if self.contains(*value) {
3257
                if !first {
3258
                    f.write_str(" | ")?;
3259
                }
3260
                first = false;
3261
                f.write_str(name)?;
3262
            }
3263
        }
3264
        if first {
3265
            f.write_str("(empty)")?;
3266
        }
3267
        Ok(())
3268
    }
3269
}
3270
3271
impl std::fmt::Binary for GlyphKeyedFlags {
3272
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
3273
        std::fmt::Binary::fmt(&self.bits, f)
3274
    }
3275
}
3276
3277
impl std::fmt::Octal for GlyphKeyedFlags {
3278
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
3279
        std::fmt::Octal::fmt(&self.bits, f)
3280
    }
3281
}
3282
3283
impl std::fmt::LowerHex for GlyphKeyedFlags {
3284
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
3285
        std::fmt::LowerHex::fmt(&self.bits, f)
3286
    }
3287
}
3288
3289
impl std::fmt::UpperHex for GlyphKeyedFlags {
3290
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
3291
        std::fmt::UpperHex::fmt(&self.bits, f)
3292
    }
3293
}
3294
3295
impl font_types::Scalar for GlyphKeyedFlags {
3296
    type Raw = <u8 as font_types::Scalar>::Raw;
3297
    fn to_raw(self) -> Self::Raw {
3298
        self.bits().to_raw()
3299
    }
3300
    fn from_raw(raw: Self::Raw) -> Self {
3301
        let t = <u8>::from_raw(raw);
3302
        Self::from_bits_truncate(t)
3303
    }
3304
}
3305
3306
#[cfg(feature = "experimental_traverse")]
3307
impl<'a> From<GlyphKeyedFlags> for FieldType<'a> {
3308
    fn from(src: GlyphKeyedFlags) -> FieldType<'a> {
3309
        src.bits().into()
3310
    }
3311
}
3312
3313
impl<'a> MinByteRange<'a> for GlyphPatches<'a> {
3314
    fn min_byte_range(&self) -> Range<usize> {
3315
        0..self.glyph_data_offsets_byte_range().end
3316
    }
3317
    fn min_table_bytes(&self) -> &'a [u8] {
3318
        let range = self.min_byte_range();
3319
        self.data.as_bytes().get(range).unwrap_or_default()
3320
    }
3321
}
3322
3323
impl ReadArgs for GlyphPatches<'_> {
3324
    type Args = GlyphKeyedFlags;
3325
}
3326
3327
impl<'a> FontRead<'a> for GlyphPatches<'a> {
3328
    fn read_with_args(data: FontData<'a>, args: GlyphKeyedFlags) -> Result<Self, ReadError> {
3329
        let flags = args;
3330
3331
        #[allow(clippy::absurd_extreme_comparisons)]
3332
        if data.len() < Self::MIN_SIZE {
3333
            return Err(ReadError::OutOfBounds);
3334
        }
3335
        Ok(Self { data, flags })
3336
    }
3337
}
3338
3339
impl<'a> GlyphPatches<'a> {
3340
    /// A constructor that requires additional arguments.
3341
    ///
3342
    /// This type requires some external state in order to be
3343
    /// parsed.
3344
    pub fn read(data: FontData<'a>, flags: GlyphKeyedFlags) -> Result<Self, ReadError> {
3345
        let args = flags;
3346
        Self::read_with_args(data, args)
3347
    }
3348
}
3349
3350
/// [GlyphPatches](https://w3c.github.io/IFT/Overview.html#glyphpatches)
3351
#[derive(Clone)]
3352
pub struct GlyphPatches<'a> {
3353
    data: FontData<'a>,
3354
    flags: GlyphKeyedFlags,
3355
}
3356
3357
#[allow(clippy::needless_lifetimes)]
3358
impl<'a> GlyphPatches<'a> {
3359
    pub const MIN_SIZE: usize = (u32::RAW_BYTE_LEN + u8::RAW_BYTE_LEN);
3360
    basic_table_impls!(impl_the_methods);
3361
3362
    pub fn glyph_count(&self) -> u32 {
3363
        let range = self.glyph_count_byte_range();
3364
        self.data.read_at(range.start).ok().unwrap()
3365
    }
3366
3367
    pub fn table_count(&self) -> u8 {
3368
        let range = self.table_count_byte_range();
3369
        self.data.read_at(range.start).ok().unwrap()
3370
    }
3371
3372
    pub fn glyph_ids(&self) -> ComputedArray<'a, U16Or24> {
3373
        let range = self.glyph_ids_byte_range();
3374
        self.data
3375
            .read_with_args(range, self.flags())
3376
            .unwrap_or_default()
3377
    }
3378
3379
    pub fn tables(&self) -> &'a [BigEndian<Tag>] {
3380
        let range = self.tables_byte_range();
3381
        self.data.read_array(range).ok().unwrap_or_default()
3382
    }
3383
3384
    pub fn glyph_data_offsets(&self) -> &'a [BigEndian<Offset32>] {
3385
        let range = self.glyph_data_offsets_byte_range();
3386
        self.data.read_array(range).ok().unwrap_or_default()
3387
    }
3388
3389
    /// A dynamically resolving wrapper for [`glyph_data_offsets`][Self::glyph_data_offsets].
3390
    pub fn glyph_data(&self) -> ArrayOfOffsets<'a, GlyphData<'a>, Offset32> {
3391
        let data = self.data;
3392
        let offsets = self.glyph_data_offsets();
3393
        ArrayOfOffsets::new(offsets, data, ())
3394
    }
3395
3396
    pub(crate) fn flags(&self) -> GlyphKeyedFlags {
3397
        self.flags
3398
    }
3399
3400
    pub fn glyph_count_byte_range(&self) -> Range<usize> {
3401
        let start = 0;
3402
        let end = start + u32::RAW_BYTE_LEN;
3403
        start..end
3404
    }
3405
3406
    pub fn table_count_byte_range(&self) -> Range<usize> {
3407
        let start = self.glyph_count_byte_range().end;
3408
        let end = start + u8::RAW_BYTE_LEN;
3409
        start..end
3410
    }
3411
3412
    pub fn glyph_ids_byte_range(&self) -> Range<usize> {
3413
        let glyph_count = self.glyph_count();
3414
        let start = self.table_count_byte_range().end;
3415
        let end = start
3416
            + (transforms::to_usize(glyph_count))
3417
                .saturating_mul(<U16Or24 as ComputeSize>::compute_size(self.flags()).unwrap_or(0));
3418
        start..end
3419
    }
3420
3421
    pub fn tables_byte_range(&self) -> Range<usize> {
3422
        let table_count = self.table_count();
3423
        let start = self.glyph_ids_byte_range().end;
3424
        let end = start + (transforms::to_usize(table_count)).saturating_mul(Tag::RAW_BYTE_LEN);
3425
        start..end
3426
    }
3427
3428
    pub fn glyph_data_offsets_byte_range(&self) -> Range<usize> {
3429
        let glyph_count = self.glyph_count();
3430
        let table_count = self.table_count();
3431
        let start = self.tables_byte_range().end;
3432
        let end = start
3433
            + (transforms::multiply_add(glyph_count, table_count, 1_usize))
3434
                .saturating_mul(Offset32::RAW_BYTE_LEN);
3435
        start..end
3436
    }
3437
}
3438
3439
const _: () = assert!(FontData::default_data_long_enough(GlyphPatches::MIN_SIZE));
3440
3441
impl Default for GlyphPatches<'_> {
3442
    fn default() -> Self {
3443
        Self {
3444
            data: FontData::default_table_data(),
3445
            flags: Default::default(),
3446
        }
3447
    }
3448
}
3449
3450
#[cfg(feature = "experimental_traverse")]
3451
impl<'a> SomeTable<'a> for GlyphPatches<'a> {
3452
    fn type_name(&self) -> &str {
3453
        "GlyphPatches"
3454
    }
3455
    fn get_field(&self, idx: usize) -> Option<Field<'a>> {
3456
        match idx {
3457
            0usize => Some(Field::new("glyph_count", self.glyph_count())),
3458
            1usize => Some(Field::new("table_count", self.table_count())),
3459
            2usize => Some(Field::new("glyph_ids", traversal::FieldType::Unknown)),
3460
            3usize => Some(Field::new("tables", self.tables())),
3461
            4usize => Some(Field::new(
3462
                "glyph_data_offsets",
3463
                FieldType::from(self.glyph_data()),
3464
            )),
3465
            _ => None,
3466
        }
3467
    }
3468
}
3469
3470
#[cfg(feature = "experimental_traverse")]
3471
#[allow(clippy::needless_lifetimes)]
3472
impl<'a> std::fmt::Debug for GlyphPatches<'a> {
3473
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3474
        (self as &dyn SomeTable<'a>).fmt(f)
3475
    }
3476
}
3477
3478
impl<'a> MinByteRange<'a> for GlyphData<'a> {
3479
    fn min_byte_range(&self) -> Range<usize> {
3480
        0..self.data_byte_range().end
3481
    }
3482
    fn min_table_bytes(&self) -> &'a [u8] {
3483
        let range = self.min_byte_range();
3484
        self.data.as_bytes().get(range).unwrap_or_default()
3485
    }
3486
}
3487
3488
impl ReadArgs for GlyphData<'_> {
3489
    type Args = ();
3490
}
3491
3492
impl<'a> FontRead<'a> for GlyphData<'a> {
3493
    fn read_with_args(data: FontData<'a>, _: ()) -> Result<Self, ReadError> {
3494
        #[allow(clippy::absurd_extreme_comparisons)]
3495
        if data.len() < Self::MIN_SIZE {
3496
            return Err(ReadError::OutOfBounds);
3497
        }
3498
        Ok(Self { data })
3499
    }
3500
}
3501
3502
#[derive(Clone)]
3503
pub struct GlyphData<'a> {
3504
    data: FontData<'a>,
3505
}
3506
3507
#[allow(clippy::needless_lifetimes)]
3508
impl<'a> GlyphData<'a> {
3509
    pub const MIN_SIZE: usize = 0;
3510
    basic_table_impls!(impl_the_methods);
3511
3512
    pub fn data(&self) -> &'a [u8] {
3513
        let range = self.data_byte_range();
3514
        self.data.read_array(range).ok().unwrap_or_default()
3515
    }
3516
3517
    pub fn data_byte_range(&self) -> Range<usize> {
3518
        let start = 0;
3519
        let end =
3520
            start + self.data.len().saturating_sub(start) / u8::RAW_BYTE_LEN * u8::RAW_BYTE_LEN;
3521
        start..end
3522
    }
3523
}
3524
3525
#[allow(clippy::absurd_extreme_comparisons)]
3526
const _: () = assert!(FontData::default_data_long_enough(GlyphData::MIN_SIZE));
3527
3528
impl Default for GlyphData<'_> {
3529
    fn default() -> Self {
3530
        Self {
3531
            data: FontData::default_table_data(),
3532
        }
3533
    }
3534
}
3535
3536
#[cfg(feature = "experimental_traverse")]
3537
impl<'a> SomeTable<'a> for GlyphData<'a> {
3538
    fn type_name(&self) -> &str {
3539
        "GlyphData"
3540
    }
3541
    fn get_field(&self, idx: usize) -> Option<Field<'a>> {
3542
        match idx {
3543
            0usize => Some(Field::new("data", self.data())),
3544
            _ => None,
3545
        }
3546
    }
3547
}
3548
3549
#[cfg(feature = "experimental_traverse")]
3550
#[allow(clippy::needless_lifetimes)]
3551
impl<'a> std::fmt::Debug for GlyphData<'a> {
3552
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3553
        (self as &dyn SomeTable<'a>).fmt(f)
3554
    }
3555
}