Coverage Report

Created: 2025-07-23 06:50

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