1#[allow(unused_imports)]
6use crate::codegen_prelude::*;
7
8#[derive(Clone)]
11pub enum Lookup<'a> {
12 Format0(Lookup0<'a>),
13 Format2(Lookup2<'a>),
14 Format4(Lookup4<'a>),
15 Format6(Lookup6<'a>),
16 Format8(Lookup8<'a>),
17 Format10(Lookup10<'a>),
18}
19
20impl Default for Lookup<'_> {
21 fn default() -> Self {
22 Self::Format0(Default::default())
23 }
24}
25
26impl<'a> Lookup<'a> {
27 pub fn offset_data(&self) -> FontData<'a> {
29 match self {
30 Self::Format0(item) => item.offset_data(),
31 Self::Format2(item) => item.offset_data(),
32 Self::Format4(item) => item.offset_data(),
33 Self::Format6(item) => item.offset_data(),
34 Self::Format8(item) => item.offset_data(),
35 Self::Format10(item) => item.offset_data(),
36 }
37 }
38
39 pub fn format(&self) -> u16 {
41 match self {
42 Self::Format0(item) => item.format(),
43 Self::Format2(item) => item.format(),
44 Self::Format4(item) => item.format(),
45 Self::Format6(item) => item.format(),
46 Self::Format8(item) => item.format(),
47 Self::Format10(item) => item.format(),
48 }
49 }
50}
51
52impl<'a> FontRead<'a> for Lookup<'a> {
53 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
54 let format: u16 = data.read_at(0usize)?;
55 match format {
56 Lookup0::FORMAT => Ok(Self::Format0(FontRead::read(data)?)),
57 Lookup2::FORMAT => Ok(Self::Format2(FontRead::read(data)?)),
58 Lookup4::FORMAT => Ok(Self::Format4(FontRead::read(data)?)),
59 Lookup6::FORMAT => Ok(Self::Format6(FontRead::read(data)?)),
60 Lookup8::FORMAT => Ok(Self::Format8(FontRead::read(data)?)),
61 Lookup10::FORMAT => Ok(Self::Format10(FontRead::read(data)?)),
62 other => Err(ReadError::InvalidFormat(other.into())),
63 }
64 }
65}
66
67impl<'a> MinByteRange<'a> for Lookup<'a> {
68 fn min_byte_range(&self) -> Range<usize> {
69 match self {
70 Self::Format0(item) => item.min_byte_range(),
71 Self::Format2(item) => item.min_byte_range(),
72 Self::Format4(item) => item.min_byte_range(),
73 Self::Format6(item) => item.min_byte_range(),
74 Self::Format8(item) => item.min_byte_range(),
75 Self::Format10(item) => item.min_byte_range(),
76 }
77 }
78 fn min_table_bytes(&self) -> &'a [u8] {
79 match self {
80 Self::Format0(item) => item.min_table_bytes(),
81 Self::Format2(item) => item.min_table_bytes(),
82 Self::Format4(item) => item.min_table_bytes(),
83 Self::Format6(item) => item.min_table_bytes(),
84 Self::Format8(item) => item.min_table_bytes(),
85 Self::Format10(item) => item.min_table_bytes(),
86 }
87 }
88}
89
90#[cfg(feature = "experimental_traverse")]
91impl<'a> Lookup<'a> {
92 fn dyn_inner<'b>(&'b self) -> &'b dyn SomeTable<'a> {
93 match self {
94 Self::Format0(table) => table,
95 Self::Format2(table) => table,
96 Self::Format4(table) => table,
97 Self::Format6(table) => table,
98 Self::Format8(table) => table,
99 Self::Format10(table) => table,
100 }
101 }
102}
103
104#[cfg(feature = "experimental_traverse")]
105impl std::fmt::Debug for Lookup<'_> {
106 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
107 self.dyn_inner().fmt(f)
108 }
109}
110
111#[cfg(feature = "experimental_traverse")]
112impl<'a> SomeTable<'a> for Lookup<'a> {
113 fn type_name(&self) -> &str {
114 self.dyn_inner().type_name()
115 }
116 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
117 self.dyn_inner().get_field(idx)
118 }
119}
120
121impl Format<u16> for Lookup0<'_> {
122 const FORMAT: u16 = 0;
123}
124
125impl<'a> MinByteRange<'a> for Lookup0<'a> {
126 fn min_byte_range(&self) -> Range<usize> {
127 0..self.values_data_byte_range().end
128 }
129 fn min_table_bytes(&self) -> &'a [u8] {
130 let range = self.min_byte_range();
131 self.data.as_bytes().get(range).unwrap_or_default()
132 }
133}
134
135impl<'a> FontRead<'a> for Lookup0<'a> {
136 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
137 #[allow(clippy::absurd_extreme_comparisons)]
138 if data.len() < Self::MIN_SIZE {
139 return Err(ReadError::OutOfBounds);
140 }
141 Ok(Self { data })
142 }
143}
144
145#[derive(Clone)]
148pub struct Lookup0<'a> {
149 data: FontData<'a>,
150}
151
152#[allow(clippy::needless_lifetimes)]
153impl<'a> Lookup0<'a> {
154 pub const MIN_SIZE: usize = u16::RAW_BYTE_LEN;
155 basic_table_impls!(impl_the_methods);
156
157 pub fn format(&self) -> u16 {
159 let range = self.format_byte_range();
160 self.data.read_at(range.start).ok().unwrap()
161 }
162
163 pub fn values_data(&self) -> &'a [u8] {
165 let range = self.values_data_byte_range();
166 self.data.read_array(range).ok().unwrap_or_default()
167 }
168
169 pub fn format_byte_range(&self) -> Range<usize> {
170 let start = 0;
171 start..start + u16::RAW_BYTE_LEN
172 }
173
174 pub fn values_data_byte_range(&self) -> Range<usize> {
175 let start = self.format_byte_range().end;
176 start..start + self.data.len().saturating_sub(start) / u8::RAW_BYTE_LEN * u8::RAW_BYTE_LEN
177 }
178}
179
180const _: () = assert!(FontData::default_data_long_enough(Lookup0::MIN_SIZE));
181
182impl Default for Lookup0<'_> {
183 fn default() -> Self {
184 Self {
185 data: FontData::default_table_data(),
186 }
187 }
188}
189
190#[cfg(feature = "experimental_traverse")]
191impl<'a> SomeTable<'a> for Lookup0<'a> {
192 fn type_name(&self) -> &str {
193 "Lookup0"
194 }
195 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
196 match idx {
197 0usize => Some(Field::new("format", self.format())),
198 1usize => Some(Field::new("values_data", self.values_data())),
199 _ => None,
200 }
201 }
202}
203
204#[cfg(feature = "experimental_traverse")]
205#[allow(clippy::needless_lifetimes)]
206impl<'a> std::fmt::Debug for Lookup0<'a> {
207 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
208 (self as &dyn SomeTable<'a>).fmt(f)
209 }
210}
211
212impl Format<u16> for Lookup2<'_> {
213 const FORMAT: u16 = 2;
214}
215
216impl<'a> MinByteRange<'a> for Lookup2<'a> {
217 fn min_byte_range(&self) -> Range<usize> {
218 0..self.segments_data_byte_range().end
219 }
220 fn min_table_bytes(&self) -> &'a [u8] {
221 let range = self.min_byte_range();
222 self.data.as_bytes().get(range).unwrap_or_default()
223 }
224}
225
226impl<'a> FontRead<'a> for Lookup2<'a> {
227 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
228 #[allow(clippy::absurd_extreme_comparisons)]
229 if data.len() < Self::MIN_SIZE {
230 return Err(ReadError::OutOfBounds);
231 }
232 Ok(Self { data })
233 }
234}
235
236#[derive(Clone)]
240pub struct Lookup2<'a> {
241 data: FontData<'a>,
242}
243
244#[allow(clippy::needless_lifetimes)]
245impl<'a> Lookup2<'a> {
246 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN
247 + u16::RAW_BYTE_LEN
248 + u16::RAW_BYTE_LEN
249 + u16::RAW_BYTE_LEN
250 + u16::RAW_BYTE_LEN
251 + u16::RAW_BYTE_LEN);
252 basic_table_impls!(impl_the_methods);
253
254 pub fn format(&self) -> u16 {
256 let range = self.format_byte_range();
257 self.data.read_at(range.start).ok().unwrap()
258 }
259
260 pub fn unit_size(&self) -> u16 {
262 let range = self.unit_size_byte_range();
263 self.data.read_at(range.start).ok().unwrap()
264 }
265
266 pub fn n_units(&self) -> u16 {
268 let range = self.n_units_byte_range();
269 self.data.read_at(range.start).ok().unwrap()
270 }
271
272 pub fn search_range(&self) -> u16 {
274 let range = self.search_range_byte_range();
275 self.data.read_at(range.start).ok().unwrap()
276 }
277
278 pub fn entry_selector(&self) -> u16 {
280 let range = self.entry_selector_byte_range();
281 self.data.read_at(range.start).ok().unwrap()
282 }
283
284 pub fn range_shift(&self) -> u16 {
286 let range = self.range_shift_byte_range();
287 self.data.read_at(range.start).ok().unwrap()
288 }
289
290 pub fn segments_data(&self) -> &'a [u8] {
292 let range = self.segments_data_byte_range();
293 self.data.read_array(range).ok().unwrap_or_default()
294 }
295
296 pub fn format_byte_range(&self) -> Range<usize> {
297 let start = 0;
298 start..start + u16::RAW_BYTE_LEN
299 }
300
301 pub fn unit_size_byte_range(&self) -> Range<usize> {
302 let start = self.format_byte_range().end;
303 start..start + u16::RAW_BYTE_LEN
304 }
305
306 pub fn n_units_byte_range(&self) -> Range<usize> {
307 let start = self.unit_size_byte_range().end;
308 start..start + u16::RAW_BYTE_LEN
309 }
310
311 pub fn search_range_byte_range(&self) -> Range<usize> {
312 let start = self.n_units_byte_range().end;
313 start..start + u16::RAW_BYTE_LEN
314 }
315
316 pub fn entry_selector_byte_range(&self) -> Range<usize> {
317 let start = self.search_range_byte_range().end;
318 start..start + u16::RAW_BYTE_LEN
319 }
320
321 pub fn range_shift_byte_range(&self) -> Range<usize> {
322 let start = self.entry_selector_byte_range().end;
323 start..start + u16::RAW_BYTE_LEN
324 }
325
326 pub fn segments_data_byte_range(&self) -> Range<usize> {
327 let unit_size = self.unit_size();
328 let n_units = self.n_units();
329 let start = self.range_shift_byte_range().end;
330 start
331 ..start
332 + (transforms::add_multiply(unit_size, 0_usize, n_units))
333 .saturating_mul(u8::RAW_BYTE_LEN)
334 }
335}
336
337#[cfg(feature = "experimental_traverse")]
338impl<'a> SomeTable<'a> for Lookup2<'a> {
339 fn type_name(&self) -> &str {
340 "Lookup2"
341 }
342 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
343 match idx {
344 0usize => Some(Field::new("format", self.format())),
345 1usize => Some(Field::new("unit_size", self.unit_size())),
346 2usize => Some(Field::new("n_units", self.n_units())),
347 3usize => Some(Field::new("search_range", self.search_range())),
348 4usize => Some(Field::new("entry_selector", self.entry_selector())),
349 5usize => Some(Field::new("range_shift", self.range_shift())),
350 6usize => Some(Field::new("segments_data", self.segments_data())),
351 _ => None,
352 }
353 }
354}
355
356#[cfg(feature = "experimental_traverse")]
357#[allow(clippy::needless_lifetimes)]
358impl<'a> std::fmt::Debug for Lookup2<'a> {
359 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
360 (self as &dyn SomeTable<'a>).fmt(f)
361 }
362}
363
364impl Format<u16> for Lookup4<'_> {
365 const FORMAT: u16 = 4;
366}
367
368impl<'a> MinByteRange<'a> for Lookup4<'a> {
369 fn min_byte_range(&self) -> Range<usize> {
370 0..self.segments_byte_range().end
371 }
372 fn min_table_bytes(&self) -> &'a [u8] {
373 let range = self.min_byte_range();
374 self.data.as_bytes().get(range).unwrap_or_default()
375 }
376}
377
378impl<'a> FontRead<'a> for Lookup4<'a> {
379 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
380 #[allow(clippy::absurd_extreme_comparisons)]
381 if data.len() < Self::MIN_SIZE {
382 return Err(ReadError::OutOfBounds);
383 }
384 Ok(Self { data })
385 }
386}
387
388#[derive(Clone)]
392pub struct Lookup4<'a> {
393 data: FontData<'a>,
394}
395
396#[allow(clippy::needless_lifetimes)]
397impl<'a> Lookup4<'a> {
398 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN
399 + u16::RAW_BYTE_LEN
400 + u16::RAW_BYTE_LEN
401 + u16::RAW_BYTE_LEN
402 + u16::RAW_BYTE_LEN
403 + u16::RAW_BYTE_LEN);
404 basic_table_impls!(impl_the_methods);
405
406 pub fn format(&self) -> u16 {
408 let range = self.format_byte_range();
409 self.data.read_at(range.start).ok().unwrap()
410 }
411
412 pub fn unit_size(&self) -> u16 {
414 let range = self.unit_size_byte_range();
415 self.data.read_at(range.start).ok().unwrap()
416 }
417
418 pub fn n_units(&self) -> u16 {
420 let range = self.n_units_byte_range();
421 self.data.read_at(range.start).ok().unwrap()
422 }
423
424 pub fn search_range(&self) -> u16 {
426 let range = self.search_range_byte_range();
427 self.data.read_at(range.start).ok().unwrap()
428 }
429
430 pub fn entry_selector(&self) -> u16 {
432 let range = self.entry_selector_byte_range();
433 self.data.read_at(range.start).ok().unwrap()
434 }
435
436 pub fn range_shift(&self) -> u16 {
438 let range = self.range_shift_byte_range();
439 self.data.read_at(range.start).ok().unwrap()
440 }
441
442 pub fn segments(&self) -> &'a [LookupSegment4] {
444 let range = self.segments_byte_range();
445 self.data.read_array(range).ok().unwrap_or_default()
446 }
447
448 pub fn format_byte_range(&self) -> Range<usize> {
449 let start = 0;
450 start..start + u16::RAW_BYTE_LEN
451 }
452
453 pub fn unit_size_byte_range(&self) -> Range<usize> {
454 let start = self.format_byte_range().end;
455 start..start + u16::RAW_BYTE_LEN
456 }
457
458 pub fn n_units_byte_range(&self) -> Range<usize> {
459 let start = self.unit_size_byte_range().end;
460 start..start + u16::RAW_BYTE_LEN
461 }
462
463 pub fn search_range_byte_range(&self) -> Range<usize> {
464 let start = self.n_units_byte_range().end;
465 start..start + u16::RAW_BYTE_LEN
466 }
467
468 pub fn entry_selector_byte_range(&self) -> Range<usize> {
469 let start = self.search_range_byte_range().end;
470 start..start + u16::RAW_BYTE_LEN
471 }
472
473 pub fn range_shift_byte_range(&self) -> Range<usize> {
474 let start = self.entry_selector_byte_range().end;
475 start..start + u16::RAW_BYTE_LEN
476 }
477
478 pub fn segments_byte_range(&self) -> Range<usize> {
479 let n_units = self.n_units();
480 let start = self.range_shift_byte_range().end;
481 start..start + (transforms::to_usize(n_units)).saturating_mul(LookupSegment4::RAW_BYTE_LEN)
482 }
483}
484
485#[cfg(feature = "experimental_traverse")]
486impl<'a> SomeTable<'a> for Lookup4<'a> {
487 fn type_name(&self) -> &str {
488 "Lookup4"
489 }
490 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
491 match idx {
492 0usize => Some(Field::new("format", self.format())),
493 1usize => Some(Field::new("unit_size", self.unit_size())),
494 2usize => Some(Field::new("n_units", self.n_units())),
495 3usize => Some(Field::new("search_range", self.search_range())),
496 4usize => Some(Field::new("entry_selector", self.entry_selector())),
497 5usize => Some(Field::new("range_shift", self.range_shift())),
498 6usize => Some(Field::new(
499 "segments",
500 traversal::FieldType::array_of_records(
501 stringify!(LookupSegment4),
502 self.segments(),
503 self.offset_data(),
504 ),
505 )),
506 _ => None,
507 }
508 }
509}
510
511#[cfg(feature = "experimental_traverse")]
512#[allow(clippy::needless_lifetimes)]
513impl<'a> std::fmt::Debug for Lookup4<'a> {
514 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
515 (self as &dyn SomeTable<'a>).fmt(f)
516 }
517}
518
519#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
521#[repr(C)]
522#[repr(packed)]
523pub struct LookupSegment4 {
524 pub last_glyph: BigEndian<u16>,
526 pub first_glyph: BigEndian<u16>,
528 pub value_offset: BigEndian<u16>,
530}
531
532impl LookupSegment4 {
533 pub fn last_glyph(&self) -> u16 {
535 self.last_glyph.get()
536 }
537
538 pub fn first_glyph(&self) -> u16 {
540 self.first_glyph.get()
541 }
542
543 pub fn value_offset(&self) -> u16 {
545 self.value_offset.get()
546 }
547}
548
549impl FixedSize for LookupSegment4 {
550 const RAW_BYTE_LEN: usize = u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN;
551}
552
553#[cfg(feature = "experimental_traverse")]
554impl<'a> SomeRecord<'a> for LookupSegment4 {
555 fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
556 RecordResolver {
557 name: "LookupSegment4",
558 get_field: Box::new(move |idx, _data| match idx {
559 0usize => Some(Field::new("last_glyph", self.last_glyph())),
560 1usize => Some(Field::new("first_glyph", self.first_glyph())),
561 2usize => Some(Field::new("value_offset", self.value_offset())),
562 _ => None,
563 }),
564 data,
565 }
566 }
567}
568
569impl Format<u16> for Lookup6<'_> {
570 const FORMAT: u16 = 6;
571}
572
573impl<'a> MinByteRange<'a> for Lookup6<'a> {
574 fn min_byte_range(&self) -> Range<usize> {
575 0..self.entries_data_byte_range().end
576 }
577 fn min_table_bytes(&self) -> &'a [u8] {
578 let range = self.min_byte_range();
579 self.data.as_bytes().get(range).unwrap_or_default()
580 }
581}
582
583impl<'a> FontRead<'a> for Lookup6<'a> {
584 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
585 #[allow(clippy::absurd_extreme_comparisons)]
586 if data.len() < Self::MIN_SIZE {
587 return Err(ReadError::OutOfBounds);
588 }
589 Ok(Self { data })
590 }
591}
592
593#[derive(Clone)]
596pub struct Lookup6<'a> {
597 data: FontData<'a>,
598}
599
600#[allow(clippy::needless_lifetimes)]
601impl<'a> Lookup6<'a> {
602 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN
603 + u16::RAW_BYTE_LEN
604 + u16::RAW_BYTE_LEN
605 + u16::RAW_BYTE_LEN
606 + u16::RAW_BYTE_LEN
607 + u16::RAW_BYTE_LEN);
608 basic_table_impls!(impl_the_methods);
609
610 pub fn format(&self) -> u16 {
612 let range = self.format_byte_range();
613 self.data.read_at(range.start).ok().unwrap()
614 }
615
616 pub fn unit_size(&self) -> u16 {
618 let range = self.unit_size_byte_range();
619 self.data.read_at(range.start).ok().unwrap()
620 }
621
622 pub fn n_units(&self) -> u16 {
624 let range = self.n_units_byte_range();
625 self.data.read_at(range.start).ok().unwrap()
626 }
627
628 pub fn search_range(&self) -> u16 {
630 let range = self.search_range_byte_range();
631 self.data.read_at(range.start).ok().unwrap()
632 }
633
634 pub fn entry_selector(&self) -> u16 {
636 let range = self.entry_selector_byte_range();
637 self.data.read_at(range.start).ok().unwrap()
638 }
639
640 pub fn range_shift(&self) -> u16 {
642 let range = self.range_shift_byte_range();
643 self.data.read_at(range.start).ok().unwrap()
644 }
645
646 pub fn entries_data(&self) -> &'a [u8] {
648 let range = self.entries_data_byte_range();
649 self.data.read_array(range).ok().unwrap_or_default()
650 }
651
652 pub fn format_byte_range(&self) -> Range<usize> {
653 let start = 0;
654 start..start + u16::RAW_BYTE_LEN
655 }
656
657 pub fn unit_size_byte_range(&self) -> Range<usize> {
658 let start = self.format_byte_range().end;
659 start..start + u16::RAW_BYTE_LEN
660 }
661
662 pub fn n_units_byte_range(&self) -> Range<usize> {
663 let start = self.unit_size_byte_range().end;
664 start..start + u16::RAW_BYTE_LEN
665 }
666
667 pub fn search_range_byte_range(&self) -> Range<usize> {
668 let start = self.n_units_byte_range().end;
669 start..start + u16::RAW_BYTE_LEN
670 }
671
672 pub fn entry_selector_byte_range(&self) -> Range<usize> {
673 let start = self.search_range_byte_range().end;
674 start..start + u16::RAW_BYTE_LEN
675 }
676
677 pub fn range_shift_byte_range(&self) -> Range<usize> {
678 let start = self.entry_selector_byte_range().end;
679 start..start + u16::RAW_BYTE_LEN
680 }
681
682 pub fn entries_data_byte_range(&self) -> Range<usize> {
683 let unit_size = self.unit_size();
684 let n_units = self.n_units();
685 let start = self.range_shift_byte_range().end;
686 start
687 ..start
688 + (transforms::add_multiply(unit_size, 0_usize, n_units))
689 .saturating_mul(u8::RAW_BYTE_LEN)
690 }
691}
692
693#[cfg(feature = "experimental_traverse")]
694impl<'a> SomeTable<'a> for Lookup6<'a> {
695 fn type_name(&self) -> &str {
696 "Lookup6"
697 }
698 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
699 match idx {
700 0usize => Some(Field::new("format", self.format())),
701 1usize => Some(Field::new("unit_size", self.unit_size())),
702 2usize => Some(Field::new("n_units", self.n_units())),
703 3usize => Some(Field::new("search_range", self.search_range())),
704 4usize => Some(Field::new("entry_selector", self.entry_selector())),
705 5usize => Some(Field::new("range_shift", self.range_shift())),
706 6usize => Some(Field::new("entries_data", self.entries_data())),
707 _ => None,
708 }
709 }
710}
711
712#[cfg(feature = "experimental_traverse")]
713#[allow(clippy::needless_lifetimes)]
714impl<'a> std::fmt::Debug for Lookup6<'a> {
715 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
716 (self as &dyn SomeTable<'a>).fmt(f)
717 }
718}
719
720impl Format<u16> for Lookup8<'_> {
721 const FORMAT: u16 = 8;
722}
723
724impl<'a> MinByteRange<'a> for Lookup8<'a> {
725 fn min_byte_range(&self) -> Range<usize> {
726 0..self.value_array_byte_range().end
727 }
728 fn min_table_bytes(&self) -> &'a [u8] {
729 let range = self.min_byte_range();
730 self.data.as_bytes().get(range).unwrap_or_default()
731 }
732}
733
734impl<'a> FontRead<'a> for Lookup8<'a> {
735 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
736 #[allow(clippy::absurd_extreme_comparisons)]
737 if data.len() < Self::MIN_SIZE {
738 return Err(ReadError::OutOfBounds);
739 }
740 Ok(Self { data })
741 }
742}
743
744#[derive(Clone)]
747pub struct Lookup8<'a> {
748 data: FontData<'a>,
749}
750
751#[allow(clippy::needless_lifetimes)]
752impl<'a> Lookup8<'a> {
753 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
754 basic_table_impls!(impl_the_methods);
755
756 pub fn format(&self) -> u16 {
758 let range = self.format_byte_range();
759 self.data.read_at(range.start).ok().unwrap()
760 }
761
762 pub fn first_glyph(&self) -> u16 {
764 let range = self.first_glyph_byte_range();
765 self.data.read_at(range.start).ok().unwrap()
766 }
767
768 pub fn glyph_count(&self) -> u16 {
771 let range = self.glyph_count_byte_range();
772 self.data.read_at(range.start).ok().unwrap()
773 }
774
775 pub fn value_array(&self) -> &'a [BigEndian<u16>] {
778 let range = self.value_array_byte_range();
779 self.data.read_array(range).ok().unwrap_or_default()
780 }
781
782 pub fn format_byte_range(&self) -> Range<usize> {
783 let start = 0;
784 start..start + u16::RAW_BYTE_LEN
785 }
786
787 pub fn first_glyph_byte_range(&self) -> Range<usize> {
788 let start = self.format_byte_range().end;
789 start..start + u16::RAW_BYTE_LEN
790 }
791
792 pub fn glyph_count_byte_range(&self) -> Range<usize> {
793 let start = self.first_glyph_byte_range().end;
794 start..start + u16::RAW_BYTE_LEN
795 }
796
797 pub fn value_array_byte_range(&self) -> Range<usize> {
798 let glyph_count = self.glyph_count();
799 let start = self.glyph_count_byte_range().end;
800 start..start + (transforms::to_usize(glyph_count)).saturating_mul(u16::RAW_BYTE_LEN)
801 }
802}
803
804#[cfg(feature = "experimental_traverse")]
805impl<'a> SomeTable<'a> for Lookup8<'a> {
806 fn type_name(&self) -> &str {
807 "Lookup8"
808 }
809 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
810 match idx {
811 0usize => Some(Field::new("format", self.format())),
812 1usize => Some(Field::new("first_glyph", self.first_glyph())),
813 2usize => Some(Field::new("glyph_count", self.glyph_count())),
814 3usize => Some(Field::new("value_array", self.value_array())),
815 _ => None,
816 }
817 }
818}
819
820#[cfg(feature = "experimental_traverse")]
821#[allow(clippy::needless_lifetimes)]
822impl<'a> std::fmt::Debug for Lookup8<'a> {
823 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
824 (self as &dyn SomeTable<'a>).fmt(f)
825 }
826}
827
828impl Format<u16> for Lookup10<'_> {
829 const FORMAT: u16 = 10;
830}
831
832impl<'a> MinByteRange<'a> for Lookup10<'a> {
833 fn min_byte_range(&self) -> Range<usize> {
834 0..self.values_data_byte_range().end
835 }
836 fn min_table_bytes(&self) -> &'a [u8] {
837 let range = self.min_byte_range();
838 self.data.as_bytes().get(range).unwrap_or_default()
839 }
840}
841
842impl<'a> FontRead<'a> for Lookup10<'a> {
843 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
844 #[allow(clippy::absurd_extreme_comparisons)]
845 if data.len() < Self::MIN_SIZE {
846 return Err(ReadError::OutOfBounds);
847 }
848 Ok(Self { data })
849 }
850}
851
852#[derive(Clone)]
855pub struct Lookup10<'a> {
856 data: FontData<'a>,
857}
858
859#[allow(clippy::needless_lifetimes)]
860impl<'a> Lookup10<'a> {
861 pub const MIN_SIZE: usize =
862 (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
863 basic_table_impls!(impl_the_methods);
864
865 pub fn format(&self) -> u16 {
867 let range = self.format_byte_range();
868 self.data.read_at(range.start).ok().unwrap()
869 }
870
871 pub fn unit_size(&self) -> u16 {
874 let range = self.unit_size_byte_range();
875 self.data.read_at(range.start).ok().unwrap()
876 }
877
878 pub fn first_glyph(&self) -> u16 {
880 let range = self.first_glyph_byte_range();
881 self.data.read_at(range.start).ok().unwrap()
882 }
883
884 pub fn glyph_count(&self) -> u16 {
887 let range = self.glyph_count_byte_range();
888 self.data.read_at(range.start).ok().unwrap()
889 }
890
891 pub fn values_data(&self) -> &'a [u8] {
894 let range = self.values_data_byte_range();
895 self.data.read_array(range).ok().unwrap_or_default()
896 }
897
898 pub fn format_byte_range(&self) -> Range<usize> {
899 let start = 0;
900 start..start + u16::RAW_BYTE_LEN
901 }
902
903 pub fn unit_size_byte_range(&self) -> Range<usize> {
904 let start = self.format_byte_range().end;
905 start..start + u16::RAW_BYTE_LEN
906 }
907
908 pub fn first_glyph_byte_range(&self) -> Range<usize> {
909 let start = self.unit_size_byte_range().end;
910 start..start + u16::RAW_BYTE_LEN
911 }
912
913 pub fn glyph_count_byte_range(&self) -> Range<usize> {
914 let start = self.first_glyph_byte_range().end;
915 start..start + u16::RAW_BYTE_LEN
916 }
917
918 pub fn values_data_byte_range(&self) -> Range<usize> {
919 let glyph_count = self.glyph_count();
920 let unit_size = self.unit_size();
921 let start = self.glyph_count_byte_range().end;
922 start
923 ..start
924 + (transforms::add_multiply(glyph_count, 0_usize, unit_size))
925 .saturating_mul(u8::RAW_BYTE_LEN)
926 }
927}
928
929#[cfg(feature = "experimental_traverse")]
930impl<'a> SomeTable<'a> for Lookup10<'a> {
931 fn type_name(&self) -> &str {
932 "Lookup10"
933 }
934 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
935 match idx {
936 0usize => Some(Field::new("format", self.format())),
937 1usize => Some(Field::new("unit_size", self.unit_size())),
938 2usize => Some(Field::new("first_glyph", self.first_glyph())),
939 3usize => Some(Field::new("glyph_count", self.glyph_count())),
940 4usize => Some(Field::new("values_data", self.values_data())),
941 _ => None,
942 }
943 }
944}
945
946#[cfg(feature = "experimental_traverse")]
947#[allow(clippy::needless_lifetimes)]
948impl<'a> std::fmt::Debug for Lookup10<'a> {
949 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
950 (self as &dyn SomeTable<'a>).fmt(f)
951 }
952}
953
954impl<'a> MinByteRange<'a> for StateHeader<'a> {
955 fn min_byte_range(&self) -> Range<usize> {
956 0..self.entry_table_offset_byte_range().end
957 }
958 fn min_table_bytes(&self) -> &'a [u8] {
959 let range = self.min_byte_range();
960 self.data.as_bytes().get(range).unwrap_or_default()
961 }
962}
963
964impl<'a> FontRead<'a> for StateHeader<'a> {
965 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
966 #[allow(clippy::absurd_extreme_comparisons)]
967 if data.len() < Self::MIN_SIZE {
968 return Err(ReadError::OutOfBounds);
969 }
970 Ok(Self { data })
971 }
972}
973
974#[derive(Clone)]
976pub struct StateHeader<'a> {
977 data: FontData<'a>,
978}
979
980#[allow(clippy::needless_lifetimes)]
981impl<'a> StateHeader<'a> {
982 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN
983 + Offset16::RAW_BYTE_LEN
984 + Offset16::RAW_BYTE_LEN
985 + Offset16::RAW_BYTE_LEN);
986 basic_table_impls!(impl_the_methods);
987
988 pub fn state_size(&self) -> u16 {
991 let range = self.state_size_byte_range();
992 self.data.read_at(range.start).ok().unwrap()
993 }
994
995 pub fn class_table_offset(&self) -> Offset16 {
997 let range = self.class_table_offset_byte_range();
998 self.data.read_at(range.start).ok().unwrap()
999 }
1000
1001 pub fn class_table(&self) -> Result<ClassSubtable<'a>, ReadError> {
1003 let data = self.data;
1004 self.class_table_offset().resolve(data)
1005 }
1006
1007 pub fn state_array_offset(&self) -> Offset16 {
1009 let range = self.state_array_offset_byte_range();
1010 self.data.read_at(range.start).ok().unwrap()
1011 }
1012
1013 pub fn state_array(&self) -> Result<RawBytes<'a>, ReadError> {
1015 let data = self.data;
1016 self.state_array_offset().resolve(data)
1017 }
1018
1019 pub fn entry_table_offset(&self) -> Offset16 {
1021 let range = self.entry_table_offset_byte_range();
1022 self.data.read_at(range.start).ok().unwrap()
1023 }
1024
1025 pub fn entry_table(&self) -> Result<RawBytes<'a>, ReadError> {
1027 let data = self.data;
1028 self.entry_table_offset().resolve(data)
1029 }
1030
1031 pub fn state_size_byte_range(&self) -> Range<usize> {
1032 let start = 0;
1033 start..start + u16::RAW_BYTE_LEN
1034 }
1035
1036 pub fn class_table_offset_byte_range(&self) -> Range<usize> {
1037 let start = self.state_size_byte_range().end;
1038 start..start + Offset16::RAW_BYTE_LEN
1039 }
1040
1041 pub fn state_array_offset_byte_range(&self) -> Range<usize> {
1042 let start = self.class_table_offset_byte_range().end;
1043 start..start + Offset16::RAW_BYTE_LEN
1044 }
1045
1046 pub fn entry_table_offset_byte_range(&self) -> Range<usize> {
1047 let start = self.state_array_offset_byte_range().end;
1048 start..start + Offset16::RAW_BYTE_LEN
1049 }
1050}
1051
1052const _: () = assert!(FontData::default_data_long_enough(StateHeader::MIN_SIZE));
1053
1054impl Default for StateHeader<'_> {
1055 fn default() -> Self {
1056 Self {
1057 data: FontData::default_table_data(),
1058 }
1059 }
1060}
1061
1062#[cfg(feature = "experimental_traverse")]
1063impl<'a> SomeTable<'a> for StateHeader<'a> {
1064 fn type_name(&self) -> &str {
1065 "StateHeader"
1066 }
1067 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
1068 match idx {
1069 0usize => Some(Field::new("state_size", self.state_size())),
1070 1usize => Some(Field::new(
1071 "class_table_offset",
1072 FieldType::offset(self.class_table_offset(), self.class_table()),
1073 )),
1074 2usize => Some(Field::new(
1075 "state_array_offset",
1076 FieldType::offset(self.state_array_offset(), self.state_array()),
1077 )),
1078 3usize => Some(Field::new(
1079 "entry_table_offset",
1080 FieldType::offset(self.entry_table_offset(), self.entry_table()),
1081 )),
1082 _ => None,
1083 }
1084 }
1085}
1086
1087#[cfg(feature = "experimental_traverse")]
1088#[allow(clippy::needless_lifetimes)]
1089impl<'a> std::fmt::Debug for StateHeader<'a> {
1090 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1091 (self as &dyn SomeTable<'a>).fmt(f)
1092 }
1093}
1094
1095impl<'a> MinByteRange<'a> for ClassSubtable<'a> {
1096 fn min_byte_range(&self) -> Range<usize> {
1097 0..self.class_array_byte_range().end
1098 }
1099 fn min_table_bytes(&self) -> &'a [u8] {
1100 let range = self.min_byte_range();
1101 self.data.as_bytes().get(range).unwrap_or_default()
1102 }
1103}
1104
1105impl<'a> FontRead<'a> for ClassSubtable<'a> {
1106 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
1107 #[allow(clippy::absurd_extreme_comparisons)]
1108 if data.len() < Self::MIN_SIZE {
1109 return Err(ReadError::OutOfBounds);
1110 }
1111 Ok(Self { data })
1112 }
1113}
1114
1115#[derive(Clone)]
1117pub struct ClassSubtable<'a> {
1118 data: FontData<'a>,
1119}
1120
1121#[allow(clippy::needless_lifetimes)]
1122impl<'a> ClassSubtable<'a> {
1123 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
1124 basic_table_impls!(impl_the_methods);
1125
1126 pub fn first_glyph(&self) -> u16 {
1128 let range = self.first_glyph_byte_range();
1129 self.data.read_at(range.start).ok().unwrap()
1130 }
1131
1132 pub fn n_glyphs(&self) -> u16 {
1134 let range = self.n_glyphs_byte_range();
1135 self.data.read_at(range.start).ok().unwrap()
1136 }
1137
1138 pub fn class_array(&self) -> &'a [u8] {
1141 let range = self.class_array_byte_range();
1142 self.data.read_array(range).ok().unwrap_or_default()
1143 }
1144
1145 pub fn first_glyph_byte_range(&self) -> Range<usize> {
1146 let start = 0;
1147 start..start + u16::RAW_BYTE_LEN
1148 }
1149
1150 pub fn n_glyphs_byte_range(&self) -> Range<usize> {
1151 let start = self.first_glyph_byte_range().end;
1152 start..start + u16::RAW_BYTE_LEN
1153 }
1154
1155 pub fn class_array_byte_range(&self) -> Range<usize> {
1156 let n_glyphs = self.n_glyphs();
1157 let start = self.n_glyphs_byte_range().end;
1158 start..start + (transforms::to_usize(n_glyphs)).saturating_mul(u8::RAW_BYTE_LEN)
1159 }
1160}
1161
1162const _: () = assert!(FontData::default_data_long_enough(ClassSubtable::MIN_SIZE));
1163
1164impl Default for ClassSubtable<'_> {
1165 fn default() -> Self {
1166 Self {
1167 data: FontData::default_table_data(),
1168 }
1169 }
1170}
1171
1172#[cfg(feature = "experimental_traverse")]
1173impl<'a> SomeTable<'a> for ClassSubtable<'a> {
1174 fn type_name(&self) -> &str {
1175 "ClassSubtable"
1176 }
1177 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
1178 match idx {
1179 0usize => Some(Field::new("first_glyph", self.first_glyph())),
1180 1usize => Some(Field::new("n_glyphs", self.n_glyphs())),
1181 2usize => Some(Field::new("class_array", self.class_array())),
1182 _ => None,
1183 }
1184 }
1185}
1186
1187#[cfg(feature = "experimental_traverse")]
1188#[allow(clippy::needless_lifetimes)]
1189impl<'a> std::fmt::Debug for ClassSubtable<'a> {
1190 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1191 (self as &dyn SomeTable<'a>).fmt(f)
1192 }
1193}
1194
1195impl<'a> MinByteRange<'a> for RawBytes<'a> {
1196 fn min_byte_range(&self) -> Range<usize> {
1197 0..self.data_byte_range().end
1198 }
1199 fn min_table_bytes(&self) -> &'a [u8] {
1200 let range = self.min_byte_range();
1201 self.data.as_bytes().get(range).unwrap_or_default()
1202 }
1203}
1204
1205impl<'a> FontRead<'a> for RawBytes<'a> {
1206 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
1207 #[allow(clippy::absurd_extreme_comparisons)]
1208 if data.len() < Self::MIN_SIZE {
1209 return Err(ReadError::OutOfBounds);
1210 }
1211 Ok(Self { data })
1212 }
1213}
1214
1215#[derive(Clone)]
1217pub struct RawBytes<'a> {
1218 data: FontData<'a>,
1219}
1220
1221#[allow(clippy::needless_lifetimes)]
1222impl<'a> RawBytes<'a> {
1223 pub const MIN_SIZE: usize = 0;
1224 basic_table_impls!(impl_the_methods);
1225
1226 pub fn data(&self) -> &'a [u8] {
1227 let range = self.data_byte_range();
1228 self.data.read_array(range).ok().unwrap_or_default()
1229 }
1230
1231 pub fn data_byte_range(&self) -> Range<usize> {
1232 let start = 0;
1233 start..start + self.data.len().saturating_sub(start) / u8::RAW_BYTE_LEN * u8::RAW_BYTE_LEN
1234 }
1235}
1236
1237#[allow(clippy::absurd_extreme_comparisons)]
1238const _: () = assert!(FontData::default_data_long_enough(RawBytes::MIN_SIZE));
1239
1240impl Default for RawBytes<'_> {
1241 fn default() -> Self {
1242 Self {
1243 data: FontData::default_table_data(),
1244 }
1245 }
1246}
1247
1248#[cfg(feature = "experimental_traverse")]
1249impl<'a> SomeTable<'a> for RawBytes<'a> {
1250 fn type_name(&self) -> &str {
1251 "RawBytes"
1252 }
1253 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
1254 match idx {
1255 0usize => Some(Field::new("data", self.data())),
1256 _ => None,
1257 }
1258 }
1259}
1260
1261#[cfg(feature = "experimental_traverse")]
1262#[allow(clippy::needless_lifetimes)]
1263impl<'a> std::fmt::Debug for RawBytes<'a> {
1264 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1265 (self as &dyn SomeTable<'a>).fmt(f)
1266 }
1267}
1268
1269impl<'a> MinByteRange<'a> for StxHeader<'a> {
1270 fn min_byte_range(&self) -> Range<usize> {
1271 0..self.entry_table_offset_byte_range().end
1272 }
1273 fn min_table_bytes(&self) -> &'a [u8] {
1274 let range = self.min_byte_range();
1275 self.data.as_bytes().get(range).unwrap_or_default()
1276 }
1277}
1278
1279impl<'a> FontRead<'a> for StxHeader<'a> {
1280 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
1281 #[allow(clippy::absurd_extreme_comparisons)]
1282 if data.len() < Self::MIN_SIZE {
1283 return Err(ReadError::OutOfBounds);
1284 }
1285 Ok(Self { data })
1286 }
1287}
1288
1289#[derive(Clone)]
1291pub struct StxHeader<'a> {
1292 data: FontData<'a>,
1293}
1294
1295#[allow(clippy::needless_lifetimes)]
1296impl<'a> StxHeader<'a> {
1297 pub const MIN_SIZE: usize = (u32::RAW_BYTE_LEN
1298 + Offset32::RAW_BYTE_LEN
1299 + Offset32::RAW_BYTE_LEN
1300 + Offset32::RAW_BYTE_LEN);
1301 basic_table_impls!(impl_the_methods);
1302
1303 pub fn n_classes(&self) -> u32 {
1305 let range = self.n_classes_byte_range();
1306 self.data.read_at(range.start).ok().unwrap()
1307 }
1308
1309 pub fn class_table_offset(&self) -> Offset32 {
1311 let range = self.class_table_offset_byte_range();
1312 self.data.read_at(range.start).ok().unwrap()
1313 }
1314
1315 pub fn class_table(&self) -> Result<LookupU16<'a>, ReadError> {
1317 let data = self.data;
1318 self.class_table_offset().resolve(data)
1319 }
1320
1321 pub fn state_array_offset(&self) -> Offset32 {
1323 let range = self.state_array_offset_byte_range();
1324 self.data.read_at(range.start).ok().unwrap()
1325 }
1326
1327 pub fn state_array(&self) -> Result<RawWords<'a>, ReadError> {
1329 let data = self.data;
1330 self.state_array_offset().resolve(data)
1331 }
1332
1333 pub fn entry_table_offset(&self) -> Offset32 {
1335 let range = self.entry_table_offset_byte_range();
1336 self.data.read_at(range.start).ok().unwrap()
1337 }
1338
1339 pub fn entry_table(&self) -> Result<RawBytes<'a>, ReadError> {
1341 let data = self.data;
1342 self.entry_table_offset().resolve(data)
1343 }
1344
1345 pub fn n_classes_byte_range(&self) -> Range<usize> {
1346 let start = 0;
1347 start..start + u32::RAW_BYTE_LEN
1348 }
1349
1350 pub fn class_table_offset_byte_range(&self) -> Range<usize> {
1351 let start = self.n_classes_byte_range().end;
1352 start..start + Offset32::RAW_BYTE_LEN
1353 }
1354
1355 pub fn state_array_offset_byte_range(&self) -> Range<usize> {
1356 let start = self.class_table_offset_byte_range().end;
1357 start..start + Offset32::RAW_BYTE_LEN
1358 }
1359
1360 pub fn entry_table_offset_byte_range(&self) -> Range<usize> {
1361 let start = self.state_array_offset_byte_range().end;
1362 start..start + Offset32::RAW_BYTE_LEN
1363 }
1364}
1365
1366const _: () = assert!(FontData::default_data_long_enough(StxHeader::MIN_SIZE));
1367
1368impl Default for StxHeader<'_> {
1369 fn default() -> Self {
1370 Self {
1371 data: FontData::default_table_data(),
1372 }
1373 }
1374}
1375
1376#[cfg(feature = "experimental_traverse")]
1377impl<'a> SomeTable<'a> for StxHeader<'a> {
1378 fn type_name(&self) -> &str {
1379 "StxHeader"
1380 }
1381 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
1382 match idx {
1383 0usize => Some(Field::new("n_classes", self.n_classes())),
1384 1usize => Some(Field::new(
1385 "class_table_offset",
1386 FieldType::offset(self.class_table_offset(), self.class_table()),
1387 )),
1388 2usize => Some(Field::new(
1389 "state_array_offset",
1390 FieldType::offset(self.state_array_offset(), self.state_array()),
1391 )),
1392 3usize => Some(Field::new(
1393 "entry_table_offset",
1394 FieldType::offset(self.entry_table_offset(), self.entry_table()),
1395 )),
1396 _ => None,
1397 }
1398 }
1399}
1400
1401#[cfg(feature = "experimental_traverse")]
1402#[allow(clippy::needless_lifetimes)]
1403impl<'a> std::fmt::Debug for StxHeader<'a> {
1404 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1405 (self as &dyn SomeTable<'a>).fmt(f)
1406 }
1407}
1408
1409impl<'a> MinByteRange<'a> for RawWords<'a> {
1410 fn min_byte_range(&self) -> Range<usize> {
1411 0..self.data_byte_range().end
1412 }
1413 fn min_table_bytes(&self) -> &'a [u8] {
1414 let range = self.min_byte_range();
1415 self.data.as_bytes().get(range).unwrap_or_default()
1416 }
1417}
1418
1419impl<'a> FontRead<'a> for RawWords<'a> {
1420 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
1421 #[allow(clippy::absurd_extreme_comparisons)]
1422 if data.len() < Self::MIN_SIZE {
1423 return Err(ReadError::OutOfBounds);
1424 }
1425 Ok(Self { data })
1426 }
1427}
1428
1429#[derive(Clone)]
1431pub struct RawWords<'a> {
1432 data: FontData<'a>,
1433}
1434
1435#[allow(clippy::needless_lifetimes)]
1436impl<'a> RawWords<'a> {
1437 pub const MIN_SIZE: usize = 0;
1438 basic_table_impls!(impl_the_methods);
1439
1440 pub fn data(&self) -> &'a [BigEndian<u16>] {
1441 let range = self.data_byte_range();
1442 self.data.read_array(range).ok().unwrap_or_default()
1443 }
1444
1445 pub fn data_byte_range(&self) -> Range<usize> {
1446 let start = 0;
1447 start..start + self.data.len().saturating_sub(start) / u16::RAW_BYTE_LEN * u16::RAW_BYTE_LEN
1448 }
1449}
1450
1451#[allow(clippy::absurd_extreme_comparisons)]
1452const _: () = assert!(FontData::default_data_long_enough(RawWords::MIN_SIZE));
1453
1454impl Default for RawWords<'_> {
1455 fn default() -> Self {
1456 Self {
1457 data: FontData::default_table_data(),
1458 }
1459 }
1460}
1461
1462#[cfg(feature = "experimental_traverse")]
1463impl<'a> SomeTable<'a> for RawWords<'a> {
1464 fn type_name(&self) -> &str {
1465 "RawWords"
1466 }
1467 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
1468 match idx {
1469 0usize => Some(Field::new("data", self.data())),
1470 _ => None,
1471 }
1472 }
1473}
1474
1475#[cfg(feature = "experimental_traverse")]
1476#[allow(clippy::needless_lifetimes)]
1477impl<'a> std::fmt::Debug for RawWords<'a> {
1478 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1479 (self as &dyn SomeTable<'a>).fmt(f)
1480 }
1481}