1#[allow(unused_imports)]
6use crate::codegen_prelude::*;
7
8impl<'a> MinByteRange<'a> for Index1<'a> {
9 fn min_byte_range(&self) -> Range<usize> {
10 0..self.data_byte_range().end
11 }
12 fn min_table_bytes(&self) -> &'a [u8] {
13 let range = self.min_byte_range();
14 self.data.as_bytes().get(range).unwrap_or_default()
15 }
16}
17
18impl<'a> FontRead<'a> for Index1<'a> {
19 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
20 #[allow(clippy::absurd_extreme_comparisons)]
21 if data.len() < Self::MIN_SIZE {
22 return Err(ReadError::OutOfBounds);
23 }
24 Ok(Self { data })
25 }
26}
27
28#[derive(Clone)]
30pub struct Index1<'a> {
31 data: FontData<'a>,
32}
33
34#[allow(clippy::needless_lifetimes)]
35impl<'a> Index1<'a> {
36 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u8::RAW_BYTE_LEN);
37 basic_table_impls!(impl_the_methods);
38
39 pub fn count(&self) -> u16 {
41 let range = self.count_byte_range();
42 self.data.read_at(range.start).ok().unwrap()
43 }
44
45 pub fn off_size(&self) -> u8 {
47 let range = self.off_size_byte_range();
48 self.data.read_at(range.start).ok().unwrap()
49 }
50
51 pub fn offsets(&self) -> &'a [u8] {
53 let range = self.offsets_byte_range();
54 self.data.read_array(range).ok().unwrap_or_default()
55 }
56
57 pub fn data(&self) -> &'a [u8] {
59 let range = self.data_byte_range();
60 self.data.read_array(range).ok().unwrap_or_default()
61 }
62
63 pub fn count_byte_range(&self) -> Range<usize> {
64 let start = 0;
65 start..start + u16::RAW_BYTE_LEN
66 }
67
68 pub fn off_size_byte_range(&self) -> Range<usize> {
69 let start = self.count_byte_range().end;
70 start..start + u8::RAW_BYTE_LEN
71 }
72
73 pub fn offsets_byte_range(&self) -> Range<usize> {
74 let count = self.count();
75 let off_size = self.off_size();
76 let start = self.off_size_byte_range().end;
77 start
78 ..start
79 + (transforms::add_multiply(count, 1_usize, off_size))
80 .saturating_mul(u8::RAW_BYTE_LEN)
81 }
82
83 pub fn data_byte_range(&self) -> Range<usize> {
84 let start = self.offsets_byte_range().end;
85 start..start + self.data.len().saturating_sub(start) / u8::RAW_BYTE_LEN * u8::RAW_BYTE_LEN
86 }
87}
88
89#[cfg(feature = "experimental_traverse")]
90impl<'a> SomeTable<'a> for Index1<'a> {
91 fn type_name(&self) -> &str {
92 "Index1"
93 }
94 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
95 match idx {
96 0usize => Some(Field::new("count", self.count())),
97 1usize => Some(Field::new("off_size", self.off_size())),
98 2usize => Some(Field::new("offsets", self.offsets())),
99 3usize => Some(Field::new("data", self.data())),
100 _ => None,
101 }
102 }
103}
104
105#[cfg(feature = "experimental_traverse")]
106#[allow(clippy::needless_lifetimes)]
107impl<'a> std::fmt::Debug for Index1<'a> {
108 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
109 (self as &dyn SomeTable<'a>).fmt(f)
110 }
111}
112
113impl<'a> MinByteRange<'a> for Index2<'a> {
114 fn min_byte_range(&self) -> Range<usize> {
115 0..self.data_byte_range().end
116 }
117 fn min_table_bytes(&self) -> &'a [u8] {
118 let range = self.min_byte_range();
119 self.data.as_bytes().get(range).unwrap_or_default()
120 }
121}
122
123impl<'a> FontRead<'a> for Index2<'a> {
124 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
125 #[allow(clippy::absurd_extreme_comparisons)]
126 if data.len() < Self::MIN_SIZE {
127 return Err(ReadError::OutOfBounds);
128 }
129 Ok(Self { data })
130 }
131}
132
133#[derive(Clone)]
135pub struct Index2<'a> {
136 data: FontData<'a>,
137}
138
139#[allow(clippy::needless_lifetimes)]
140impl<'a> Index2<'a> {
141 pub const MIN_SIZE: usize = (u32::RAW_BYTE_LEN + u8::RAW_BYTE_LEN);
142 basic_table_impls!(impl_the_methods);
143
144 pub fn count(&self) -> u32 {
146 let range = self.count_byte_range();
147 self.data.read_at(range.start).ok().unwrap()
148 }
149
150 pub fn off_size(&self) -> u8 {
152 let range = self.off_size_byte_range();
153 self.data.read_at(range.start).ok().unwrap()
154 }
155
156 pub fn offsets(&self) -> &'a [u8] {
158 let range = self.offsets_byte_range();
159 self.data.read_array(range).ok().unwrap_or_default()
160 }
161
162 pub fn data(&self) -> &'a [u8] {
164 let range = self.data_byte_range();
165 self.data.read_array(range).ok().unwrap_or_default()
166 }
167
168 pub fn count_byte_range(&self) -> Range<usize> {
169 let start = 0;
170 start..start + u32::RAW_BYTE_LEN
171 }
172
173 pub fn off_size_byte_range(&self) -> Range<usize> {
174 let start = self.count_byte_range().end;
175 start..start + u8::RAW_BYTE_LEN
176 }
177
178 pub fn offsets_byte_range(&self) -> Range<usize> {
179 let count = self.count();
180 let off_size = self.off_size();
181 let start = self.off_size_byte_range().end;
182 start
183 ..start
184 + (transforms::add_multiply(count, 1_usize, off_size))
185 .saturating_mul(u8::RAW_BYTE_LEN)
186 }
187
188 pub fn data_byte_range(&self) -> Range<usize> {
189 let start = self.offsets_byte_range().end;
190 start..start + self.data.len().saturating_sub(start) / u8::RAW_BYTE_LEN * u8::RAW_BYTE_LEN
191 }
192}
193
194#[cfg(feature = "experimental_traverse")]
195impl<'a> SomeTable<'a> for Index2<'a> {
196 fn type_name(&self) -> &str {
197 "Index2"
198 }
199 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
200 match idx {
201 0usize => Some(Field::new("count", self.count())),
202 1usize => Some(Field::new("off_size", self.off_size())),
203 2usize => Some(Field::new("offsets", self.offsets())),
204 3usize => Some(Field::new("data", self.data())),
205 _ => None,
206 }
207 }
208}
209
210#[cfg(feature = "experimental_traverse")]
211#[allow(clippy::needless_lifetimes)]
212impl<'a> std::fmt::Debug for Index2<'a> {
213 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
214 (self as &dyn SomeTable<'a>).fmt(f)
215 }
216}
217
218#[derive(Clone)]
220pub enum FdSelect<'a> {
221 Format0(FdSelectFormat0<'a>),
222 Format3(FdSelectFormat3<'a>),
223 Format4(FdSelectFormat4<'a>),
224}
225
226impl<'a> FdSelect<'a> {
227 pub fn offset_data(&self) -> FontData<'a> {
229 match self {
230 Self::Format0(item) => item.offset_data(),
231 Self::Format3(item) => item.offset_data(),
232 Self::Format4(item) => item.offset_data(),
233 }
234 }
235
236 pub fn format(&self) -> u8 {
238 match self {
239 Self::Format0(item) => item.format(),
240 Self::Format3(item) => item.format(),
241 Self::Format4(item) => item.format(),
242 }
243 }
244}
245
246impl<'a> FontRead<'a> for FdSelect<'a> {
247 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
248 let format: u8 = data.read_at(0usize)?;
249 match format {
250 FdSelectFormat0::FORMAT => Ok(Self::Format0(FontRead::read(data)?)),
251 FdSelectFormat3::FORMAT => Ok(Self::Format3(FontRead::read(data)?)),
252 FdSelectFormat4::FORMAT => Ok(Self::Format4(FontRead::read(data)?)),
253 other => Err(ReadError::InvalidFormat(other.into())),
254 }
255 }
256}
257
258impl<'a> MinByteRange<'a> for FdSelect<'a> {
259 fn min_byte_range(&self) -> Range<usize> {
260 match self {
261 Self::Format0(item) => item.min_byte_range(),
262 Self::Format3(item) => item.min_byte_range(),
263 Self::Format4(item) => item.min_byte_range(),
264 }
265 }
266 fn min_table_bytes(&self) -> &'a [u8] {
267 match self {
268 Self::Format0(item) => item.min_table_bytes(),
269 Self::Format3(item) => item.min_table_bytes(),
270 Self::Format4(item) => item.min_table_bytes(),
271 }
272 }
273}
274
275#[cfg(feature = "experimental_traverse")]
276impl<'a> FdSelect<'a> {
277 fn dyn_inner<'b>(&'b self) -> &'b dyn SomeTable<'a> {
278 match self {
279 Self::Format0(table) => table,
280 Self::Format3(table) => table,
281 Self::Format4(table) => table,
282 }
283 }
284}
285
286#[cfg(feature = "experimental_traverse")]
287impl std::fmt::Debug for FdSelect<'_> {
288 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
289 self.dyn_inner().fmt(f)
290 }
291}
292
293#[cfg(feature = "experimental_traverse")]
294impl<'a> SomeTable<'a> for FdSelect<'a> {
295 fn type_name(&self) -> &str {
296 self.dyn_inner().type_name()
297 }
298 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
299 self.dyn_inner().get_field(idx)
300 }
301}
302
303impl Format<u8> for FdSelectFormat0<'_> {
304 const FORMAT: u8 = 0;
305}
306
307impl<'a> MinByteRange<'a> for FdSelectFormat0<'a> {
308 fn min_byte_range(&self) -> Range<usize> {
309 0..self.fds_byte_range().end
310 }
311 fn min_table_bytes(&self) -> &'a [u8] {
312 let range = self.min_byte_range();
313 self.data.as_bytes().get(range).unwrap_or_default()
314 }
315}
316
317impl<'a> FontRead<'a> for FdSelectFormat0<'a> {
318 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
319 #[allow(clippy::absurd_extreme_comparisons)]
320 if data.len() < Self::MIN_SIZE {
321 return Err(ReadError::OutOfBounds);
322 }
323 Ok(Self { data })
324 }
325}
326
327#[derive(Clone)]
329pub struct FdSelectFormat0<'a> {
330 data: FontData<'a>,
331}
332
333#[allow(clippy::needless_lifetimes)]
334impl<'a> FdSelectFormat0<'a> {
335 pub const MIN_SIZE: usize = u8::RAW_BYTE_LEN;
336 basic_table_impls!(impl_the_methods);
337
338 pub fn format(&self) -> u8 {
340 let range = self.format_byte_range();
341 self.data.read_at(range.start).ok().unwrap()
342 }
343
344 pub fn fds(&self) -> &'a [u8] {
346 let range = self.fds_byte_range();
347 self.data.read_array(range).ok().unwrap_or_default()
348 }
349
350 pub fn format_byte_range(&self) -> Range<usize> {
351 let start = 0;
352 start..start + u8::RAW_BYTE_LEN
353 }
354
355 pub fn fds_byte_range(&self) -> Range<usize> {
356 let start = self.format_byte_range().end;
357 start..start + self.data.len().saturating_sub(start) / u8::RAW_BYTE_LEN * u8::RAW_BYTE_LEN
358 }
359}
360
361#[cfg(feature = "experimental_traverse")]
362impl<'a> SomeTable<'a> for FdSelectFormat0<'a> {
363 fn type_name(&self) -> &str {
364 "FdSelectFormat0"
365 }
366 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
367 match idx {
368 0usize => Some(Field::new("format", self.format())),
369 1usize => Some(Field::new("fds", self.fds())),
370 _ => None,
371 }
372 }
373}
374
375#[cfg(feature = "experimental_traverse")]
376#[allow(clippy::needless_lifetimes)]
377impl<'a> std::fmt::Debug for FdSelectFormat0<'a> {
378 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
379 (self as &dyn SomeTable<'a>).fmt(f)
380 }
381}
382
383impl Format<u8> for FdSelectFormat3<'_> {
384 const FORMAT: u8 = 3;
385}
386
387impl<'a> MinByteRange<'a> for FdSelectFormat3<'a> {
388 fn min_byte_range(&self) -> Range<usize> {
389 0..self.sentinel_byte_range().end
390 }
391 fn min_table_bytes(&self) -> &'a [u8] {
392 let range = self.min_byte_range();
393 self.data.as_bytes().get(range).unwrap_or_default()
394 }
395}
396
397impl<'a> FontRead<'a> for FdSelectFormat3<'a> {
398 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
399 #[allow(clippy::absurd_extreme_comparisons)]
400 if data.len() < Self::MIN_SIZE {
401 return Err(ReadError::OutOfBounds);
402 }
403 Ok(Self { data })
404 }
405}
406
407#[derive(Clone)]
409pub struct FdSelectFormat3<'a> {
410 data: FontData<'a>,
411}
412
413#[allow(clippy::needless_lifetimes)]
414impl<'a> FdSelectFormat3<'a> {
415 pub const MIN_SIZE: usize = (u8::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
416 basic_table_impls!(impl_the_methods);
417
418 pub fn format(&self) -> u8 {
420 let range = self.format_byte_range();
421 self.data.read_at(range.start).ok().unwrap()
422 }
423
424 pub fn n_ranges(&self) -> u16 {
426 let range = self.n_ranges_byte_range();
427 self.data.read_at(range.start).ok().unwrap()
428 }
429
430 pub fn ranges(&self) -> &'a [FdSelectRange3] {
432 let range = self.ranges_byte_range();
433 self.data.read_array(range).ok().unwrap_or_default()
434 }
435
436 pub fn sentinel(&self) -> u16 {
438 let range = self.sentinel_byte_range();
439 self.data.read_at(range.start).ok().unwrap_or_default()
440 }
441
442 pub fn format_byte_range(&self) -> Range<usize> {
443 let start = 0;
444 start..start + u8::RAW_BYTE_LEN
445 }
446
447 pub fn n_ranges_byte_range(&self) -> Range<usize> {
448 let start = self.format_byte_range().end;
449 start..start + u16::RAW_BYTE_LEN
450 }
451
452 pub fn ranges_byte_range(&self) -> Range<usize> {
453 let n_ranges = self.n_ranges();
454 let start = self.n_ranges_byte_range().end;
455 start..start + (n_ranges as usize).saturating_mul(FdSelectRange3::RAW_BYTE_LEN)
456 }
457
458 pub fn sentinel_byte_range(&self) -> Range<usize> {
459 let start = self.ranges_byte_range().end;
460 start..start + u16::RAW_BYTE_LEN
461 }
462}
463
464#[cfg(feature = "experimental_traverse")]
465impl<'a> SomeTable<'a> for FdSelectFormat3<'a> {
466 fn type_name(&self) -> &str {
467 "FdSelectFormat3"
468 }
469 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
470 match idx {
471 0usize => Some(Field::new("format", self.format())),
472 1usize => Some(Field::new("n_ranges", self.n_ranges())),
473 2usize => Some(Field::new(
474 "ranges",
475 traversal::FieldType::array_of_records(
476 stringify!(FdSelectRange3),
477 self.ranges(),
478 self.offset_data(),
479 ),
480 )),
481 3usize => Some(Field::new("sentinel", self.sentinel())),
482 _ => None,
483 }
484 }
485}
486
487#[cfg(feature = "experimental_traverse")]
488#[allow(clippy::needless_lifetimes)]
489impl<'a> std::fmt::Debug for FdSelectFormat3<'a> {
490 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
491 (self as &dyn SomeTable<'a>).fmt(f)
492 }
493}
494
495#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
497#[repr(C)]
498#[repr(packed)]
499pub struct FdSelectRange3 {
500 pub first: BigEndian<u16>,
502 pub fd: u8,
504}
505
506impl FdSelectRange3 {
507 pub fn first(&self) -> u16 {
509 self.first.get()
510 }
511
512 pub fn fd(&self) -> u8 {
514 self.fd
515 }
516}
517
518impl FixedSize for FdSelectRange3 {
519 const RAW_BYTE_LEN: usize = u16::RAW_BYTE_LEN + u8::RAW_BYTE_LEN;
520}
521
522#[cfg(feature = "experimental_traverse")]
523impl<'a> SomeRecord<'a> for FdSelectRange3 {
524 fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
525 RecordResolver {
526 name: "FdSelectRange3",
527 get_field: Box::new(move |idx, _data| match idx {
528 0usize => Some(Field::new("first", self.first())),
529 1usize => Some(Field::new("fd", self.fd())),
530 _ => None,
531 }),
532 data,
533 }
534 }
535}
536
537impl Format<u8> for FdSelectFormat4<'_> {
538 const FORMAT: u8 = 4;
539}
540
541impl<'a> MinByteRange<'a> for FdSelectFormat4<'a> {
542 fn min_byte_range(&self) -> Range<usize> {
543 0..self.sentinel_byte_range().end
544 }
545 fn min_table_bytes(&self) -> &'a [u8] {
546 let range = self.min_byte_range();
547 self.data.as_bytes().get(range).unwrap_or_default()
548 }
549}
550
551impl<'a> FontRead<'a> for FdSelectFormat4<'a> {
552 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
553 #[allow(clippy::absurd_extreme_comparisons)]
554 if data.len() < Self::MIN_SIZE {
555 return Err(ReadError::OutOfBounds);
556 }
557 Ok(Self { data })
558 }
559}
560
561#[derive(Clone)]
563pub struct FdSelectFormat4<'a> {
564 data: FontData<'a>,
565}
566
567#[allow(clippy::needless_lifetimes)]
568impl<'a> FdSelectFormat4<'a> {
569 pub const MIN_SIZE: usize = (u8::RAW_BYTE_LEN + u32::RAW_BYTE_LEN + u32::RAW_BYTE_LEN);
570 basic_table_impls!(impl_the_methods);
571
572 pub fn format(&self) -> u8 {
574 let range = self.format_byte_range();
575 self.data.read_at(range.start).ok().unwrap()
576 }
577
578 pub fn n_ranges(&self) -> u32 {
580 let range = self.n_ranges_byte_range();
581 self.data.read_at(range.start).ok().unwrap()
582 }
583
584 pub fn ranges(&self) -> &'a [FdSelectRange4] {
586 let range = self.ranges_byte_range();
587 self.data.read_array(range).ok().unwrap_or_default()
588 }
589
590 pub fn sentinel(&self) -> u32 {
592 let range = self.sentinel_byte_range();
593 self.data.read_at(range.start).ok().unwrap_or_default()
594 }
595
596 pub fn format_byte_range(&self) -> Range<usize> {
597 let start = 0;
598 start..start + u8::RAW_BYTE_LEN
599 }
600
601 pub fn n_ranges_byte_range(&self) -> Range<usize> {
602 let start = self.format_byte_range().end;
603 start..start + u32::RAW_BYTE_LEN
604 }
605
606 pub fn ranges_byte_range(&self) -> Range<usize> {
607 let n_ranges = self.n_ranges();
608 let start = self.n_ranges_byte_range().end;
609 start..start + (n_ranges as usize).saturating_mul(FdSelectRange4::RAW_BYTE_LEN)
610 }
611
612 pub fn sentinel_byte_range(&self) -> Range<usize> {
613 let start = self.ranges_byte_range().end;
614 start..start + u32::RAW_BYTE_LEN
615 }
616}
617
618#[cfg(feature = "experimental_traverse")]
619impl<'a> SomeTable<'a> for FdSelectFormat4<'a> {
620 fn type_name(&self) -> &str {
621 "FdSelectFormat4"
622 }
623 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
624 match idx {
625 0usize => Some(Field::new("format", self.format())),
626 1usize => Some(Field::new("n_ranges", self.n_ranges())),
627 2usize => Some(Field::new(
628 "ranges",
629 traversal::FieldType::array_of_records(
630 stringify!(FdSelectRange4),
631 self.ranges(),
632 self.offset_data(),
633 ),
634 )),
635 3usize => Some(Field::new("sentinel", self.sentinel())),
636 _ => None,
637 }
638 }
639}
640
641#[cfg(feature = "experimental_traverse")]
642#[allow(clippy::needless_lifetimes)]
643impl<'a> std::fmt::Debug for FdSelectFormat4<'a> {
644 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
645 (self as &dyn SomeTable<'a>).fmt(f)
646 }
647}
648
649#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
651#[repr(C)]
652#[repr(packed)]
653pub struct FdSelectRange4 {
654 pub first: BigEndian<u32>,
656 pub fd: BigEndian<u16>,
658}
659
660impl FdSelectRange4 {
661 pub fn first(&self) -> u32 {
663 self.first.get()
664 }
665
666 pub fn fd(&self) -> u16 {
668 self.fd.get()
669 }
670}
671
672impl FixedSize for FdSelectRange4 {
673 const RAW_BYTE_LEN: usize = u32::RAW_BYTE_LEN + u16::RAW_BYTE_LEN;
674}
675
676#[cfg(feature = "experimental_traverse")]
677impl<'a> SomeRecord<'a> for FdSelectRange4 {
678 fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
679 RecordResolver {
680 name: "FdSelectRange4",
681 get_field: Box::new(move |idx, _data| match idx {
682 0usize => Some(Field::new("first", self.first())),
683 1usize => Some(Field::new("fd", self.fd())),
684 _ => None,
685 }),
686 data,
687 }
688 }
689}
690
691#[derive(Clone)]
693pub enum CustomCharset<'a> {
694 Format0(CharsetFormat0<'a>),
695 Format1(CharsetFormat1<'a>),
696 Format2(CharsetFormat2<'a>),
697}
698
699impl<'a> CustomCharset<'a> {
700 pub fn offset_data(&self) -> FontData<'a> {
702 match self {
703 Self::Format0(item) => item.offset_data(),
704 Self::Format1(item) => item.offset_data(),
705 Self::Format2(item) => item.offset_data(),
706 }
707 }
708
709 pub fn format(&self) -> u8 {
711 match self {
712 Self::Format0(item) => item.format(),
713 Self::Format1(item) => item.format(),
714 Self::Format2(item) => item.format(),
715 }
716 }
717}
718
719impl<'a> FontRead<'a> for CustomCharset<'a> {
720 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
721 let format: u8 = data.read_at(0usize)?;
722 match format {
723 CharsetFormat0::FORMAT => Ok(Self::Format0(FontRead::read(data)?)),
724 CharsetFormat1::FORMAT => Ok(Self::Format1(FontRead::read(data)?)),
725 CharsetFormat2::FORMAT => Ok(Self::Format2(FontRead::read(data)?)),
726 other => Err(ReadError::InvalidFormat(other.into())),
727 }
728 }
729}
730
731impl<'a> MinByteRange<'a> for CustomCharset<'a> {
732 fn min_byte_range(&self) -> Range<usize> {
733 match self {
734 Self::Format0(item) => item.min_byte_range(),
735 Self::Format1(item) => item.min_byte_range(),
736 Self::Format2(item) => item.min_byte_range(),
737 }
738 }
739 fn min_table_bytes(&self) -> &'a [u8] {
740 match self {
741 Self::Format0(item) => item.min_table_bytes(),
742 Self::Format1(item) => item.min_table_bytes(),
743 Self::Format2(item) => item.min_table_bytes(),
744 }
745 }
746}
747
748#[cfg(feature = "experimental_traverse")]
749impl<'a> CustomCharset<'a> {
750 fn dyn_inner<'b>(&'b self) -> &'b dyn SomeTable<'a> {
751 match self {
752 Self::Format0(table) => table,
753 Self::Format1(table) => table,
754 Self::Format2(table) => table,
755 }
756 }
757}
758
759#[cfg(feature = "experimental_traverse")]
760impl std::fmt::Debug for CustomCharset<'_> {
761 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
762 self.dyn_inner().fmt(f)
763 }
764}
765
766#[cfg(feature = "experimental_traverse")]
767impl<'a> SomeTable<'a> for CustomCharset<'a> {
768 fn type_name(&self) -> &str {
769 self.dyn_inner().type_name()
770 }
771 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
772 self.dyn_inner().get_field(idx)
773 }
774}
775
776impl Format<u8> for CharsetFormat0<'_> {
777 const FORMAT: u8 = 0;
778}
779
780impl<'a> MinByteRange<'a> for CharsetFormat0<'a> {
781 fn min_byte_range(&self) -> Range<usize> {
782 0..self.glyph_byte_range().end
783 }
784 fn min_table_bytes(&self) -> &'a [u8] {
785 let range = self.min_byte_range();
786 self.data.as_bytes().get(range).unwrap_or_default()
787 }
788}
789
790impl<'a> FontRead<'a> for CharsetFormat0<'a> {
791 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
792 #[allow(clippy::absurd_extreme_comparisons)]
793 if data.len() < Self::MIN_SIZE {
794 return Err(ReadError::OutOfBounds);
795 }
796 Ok(Self { data })
797 }
798}
799
800#[derive(Clone)]
802pub struct CharsetFormat0<'a> {
803 data: FontData<'a>,
804}
805
806#[allow(clippy::needless_lifetimes)]
807impl<'a> CharsetFormat0<'a> {
808 pub const MIN_SIZE: usize = u8::RAW_BYTE_LEN;
809 basic_table_impls!(impl_the_methods);
810
811 pub fn format(&self) -> u8 {
813 let range = self.format_byte_range();
814 self.data.read_at(range.start).ok().unwrap()
815 }
816
817 pub fn glyph(&self) -> &'a [BigEndian<u16>] {
819 let range = self.glyph_byte_range();
820 self.data.read_array(range).ok().unwrap_or_default()
821 }
822
823 pub fn format_byte_range(&self) -> Range<usize> {
824 let start = 0;
825 start..start + u8::RAW_BYTE_LEN
826 }
827
828 pub fn glyph_byte_range(&self) -> Range<usize> {
829 let start = self.format_byte_range().end;
830 start..start + self.data.len().saturating_sub(start) / u16::RAW_BYTE_LEN * u16::RAW_BYTE_LEN
831 }
832}
833
834#[cfg(feature = "experimental_traverse")]
835impl<'a> SomeTable<'a> for CharsetFormat0<'a> {
836 fn type_name(&self) -> &str {
837 "CharsetFormat0"
838 }
839 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
840 match idx {
841 0usize => Some(Field::new("format", self.format())),
842 1usize => Some(Field::new("glyph", self.glyph())),
843 _ => None,
844 }
845 }
846}
847
848#[cfg(feature = "experimental_traverse")]
849#[allow(clippy::needless_lifetimes)]
850impl<'a> std::fmt::Debug for CharsetFormat0<'a> {
851 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
852 (self as &dyn SomeTable<'a>).fmt(f)
853 }
854}
855
856impl Format<u8> for CharsetFormat1<'_> {
857 const FORMAT: u8 = 1;
858}
859
860impl<'a> MinByteRange<'a> for CharsetFormat1<'a> {
861 fn min_byte_range(&self) -> Range<usize> {
862 0..self.ranges_byte_range().end
863 }
864 fn min_table_bytes(&self) -> &'a [u8] {
865 let range = self.min_byte_range();
866 self.data.as_bytes().get(range).unwrap_or_default()
867 }
868}
869
870impl<'a> FontRead<'a> for CharsetFormat1<'a> {
871 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
872 #[allow(clippy::absurd_extreme_comparisons)]
873 if data.len() < Self::MIN_SIZE {
874 return Err(ReadError::OutOfBounds);
875 }
876 Ok(Self { data })
877 }
878}
879
880#[derive(Clone)]
882pub struct CharsetFormat1<'a> {
883 data: FontData<'a>,
884}
885
886#[allow(clippy::needless_lifetimes)]
887impl<'a> CharsetFormat1<'a> {
888 pub const MIN_SIZE: usize = u8::RAW_BYTE_LEN;
889 basic_table_impls!(impl_the_methods);
890
891 pub fn format(&self) -> u8 {
893 let range = self.format_byte_range();
894 self.data.read_at(range.start).ok().unwrap()
895 }
896
897 pub fn ranges(&self) -> &'a [CharsetRange1] {
899 let range = self.ranges_byte_range();
900 self.data.read_array(range).ok().unwrap_or_default()
901 }
902
903 pub fn format_byte_range(&self) -> Range<usize> {
904 let start = 0;
905 start..start + u8::RAW_BYTE_LEN
906 }
907
908 pub fn ranges_byte_range(&self) -> Range<usize> {
909 let start = self.format_byte_range().end;
910 start
911 ..start
912 + self.data.len().saturating_sub(start) / CharsetRange1::RAW_BYTE_LEN
913 * CharsetRange1::RAW_BYTE_LEN
914 }
915}
916
917#[cfg(feature = "experimental_traverse")]
918impl<'a> SomeTable<'a> for CharsetFormat1<'a> {
919 fn type_name(&self) -> &str {
920 "CharsetFormat1"
921 }
922 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
923 match idx {
924 0usize => Some(Field::new("format", self.format())),
925 1usize => Some(Field::new(
926 "ranges",
927 traversal::FieldType::array_of_records(
928 stringify!(CharsetRange1),
929 self.ranges(),
930 self.offset_data(),
931 ),
932 )),
933 _ => None,
934 }
935 }
936}
937
938#[cfg(feature = "experimental_traverse")]
939#[allow(clippy::needless_lifetimes)]
940impl<'a> std::fmt::Debug for CharsetFormat1<'a> {
941 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
942 (self as &dyn SomeTable<'a>).fmt(f)
943 }
944}
945
946#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
948#[repr(C)]
949#[repr(packed)]
950pub struct CharsetRange1 {
951 pub first: BigEndian<u16>,
953 pub n_left: u8,
955}
956
957impl CharsetRange1 {
958 pub fn first(&self) -> u16 {
960 self.first.get()
961 }
962
963 pub fn n_left(&self) -> u8 {
965 self.n_left
966 }
967}
968
969impl FixedSize for CharsetRange1 {
970 const RAW_BYTE_LEN: usize = u16::RAW_BYTE_LEN + u8::RAW_BYTE_LEN;
971}
972
973#[cfg(feature = "experimental_traverse")]
974impl<'a> SomeRecord<'a> for CharsetRange1 {
975 fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
976 RecordResolver {
977 name: "CharsetRange1",
978 get_field: Box::new(move |idx, _data| match idx {
979 0usize => Some(Field::new("first", self.first())),
980 1usize => Some(Field::new("n_left", self.n_left())),
981 _ => None,
982 }),
983 data,
984 }
985 }
986}
987
988impl Format<u8> for CharsetFormat2<'_> {
989 const FORMAT: u8 = 2;
990}
991
992impl<'a> MinByteRange<'a> for CharsetFormat2<'a> {
993 fn min_byte_range(&self) -> Range<usize> {
994 0..self.ranges_byte_range().end
995 }
996 fn min_table_bytes(&self) -> &'a [u8] {
997 let range = self.min_byte_range();
998 self.data.as_bytes().get(range).unwrap_or_default()
999 }
1000}
1001
1002impl<'a> FontRead<'a> for CharsetFormat2<'a> {
1003 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
1004 #[allow(clippy::absurd_extreme_comparisons)]
1005 if data.len() < Self::MIN_SIZE {
1006 return Err(ReadError::OutOfBounds);
1007 }
1008 Ok(Self { data })
1009 }
1010}
1011
1012#[derive(Clone)]
1014pub struct CharsetFormat2<'a> {
1015 data: FontData<'a>,
1016}
1017
1018#[allow(clippy::needless_lifetimes)]
1019impl<'a> CharsetFormat2<'a> {
1020 pub const MIN_SIZE: usize = u8::RAW_BYTE_LEN;
1021 basic_table_impls!(impl_the_methods);
1022
1023 pub fn format(&self) -> u8 {
1025 let range = self.format_byte_range();
1026 self.data.read_at(range.start).ok().unwrap()
1027 }
1028
1029 pub fn ranges(&self) -> &'a [CharsetRange2] {
1031 let range = self.ranges_byte_range();
1032 self.data.read_array(range).ok().unwrap_or_default()
1033 }
1034
1035 pub fn format_byte_range(&self) -> Range<usize> {
1036 let start = 0;
1037 start..start + u8::RAW_BYTE_LEN
1038 }
1039
1040 pub fn ranges_byte_range(&self) -> Range<usize> {
1041 let start = self.format_byte_range().end;
1042 start
1043 ..start
1044 + self.data.len().saturating_sub(start) / CharsetRange2::RAW_BYTE_LEN
1045 * CharsetRange2::RAW_BYTE_LEN
1046 }
1047}
1048
1049#[cfg(feature = "experimental_traverse")]
1050impl<'a> SomeTable<'a> for CharsetFormat2<'a> {
1051 fn type_name(&self) -> &str {
1052 "CharsetFormat2"
1053 }
1054 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
1055 match idx {
1056 0usize => Some(Field::new("format", self.format())),
1057 1usize => Some(Field::new(
1058 "ranges",
1059 traversal::FieldType::array_of_records(
1060 stringify!(CharsetRange2),
1061 self.ranges(),
1062 self.offset_data(),
1063 ),
1064 )),
1065 _ => None,
1066 }
1067 }
1068}
1069
1070#[cfg(feature = "experimental_traverse")]
1071#[allow(clippy::needless_lifetimes)]
1072impl<'a> std::fmt::Debug for CharsetFormat2<'a> {
1073 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1074 (self as &dyn SomeTable<'a>).fmt(f)
1075 }
1076}
1077
1078#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
1080#[repr(C)]
1081#[repr(packed)]
1082pub struct CharsetRange2 {
1083 pub first: BigEndian<u16>,
1085 pub n_left: BigEndian<u16>,
1087}
1088
1089impl CharsetRange2 {
1090 pub fn first(&self) -> u16 {
1092 self.first.get()
1093 }
1094
1095 pub fn n_left(&self) -> u16 {
1097 self.n_left.get()
1098 }
1099}
1100
1101impl FixedSize for CharsetRange2 {
1102 const RAW_BYTE_LEN: usize = u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN;
1103}
1104
1105#[cfg(feature = "experimental_traverse")]
1106impl<'a> SomeRecord<'a> for CharsetRange2 {
1107 fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
1108 RecordResolver {
1109 name: "CharsetRange2",
1110 get_field: Box::new(move |idx, _data| match idx {
1111 0usize => Some(Field::new("first", self.first())),
1112 1usize => Some(Field::new("n_left", self.n_left())),
1113 _ => None,
1114 }),
1115 data,
1116 }
1117 }
1118}