1#[allow(unused_imports)]
6use crate::codegen_prelude::*;
7
8impl<'a> MinByteRange<'a> for CffHeader<'a> {
9 fn min_byte_range(&self) -> Range<usize> {
10 0..self.trailing_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 CffHeader<'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 CffHeader<'a> {
31 data: FontData<'a>,
32}
33
34#[allow(clippy::needless_lifetimes)]
35impl<'a> CffHeader<'a> {
36 pub const MIN_SIZE: usize =
37 (u8::RAW_BYTE_LEN + u8::RAW_BYTE_LEN + u8::RAW_BYTE_LEN + u8::RAW_BYTE_LEN);
38 basic_table_impls!(impl_the_methods);
39
40 pub fn major(&self) -> u8 {
42 let range = self.major_byte_range();
43 self.data.read_at(range.start).ok().unwrap()
44 }
45
46 pub fn minor(&self) -> u8 {
48 let range = self.minor_byte_range();
49 self.data.read_at(range.start).ok().unwrap()
50 }
51
52 pub fn hdr_size(&self) -> u8 {
54 let range = self.hdr_size_byte_range();
55 self.data.read_at(range.start).ok().unwrap()
56 }
57
58 pub fn off_size(&self) -> u8 {
60 let range = self.off_size_byte_range();
61 self.data.read_at(range.start).ok().unwrap()
62 }
63
64 pub fn _padding(&self) -> &'a [u8] {
66 let range = self._padding_byte_range();
67 self.data.read_array(range).ok().unwrap_or_default()
68 }
69
70 pub fn trailing_data(&self) -> &'a [u8] {
72 let range = self.trailing_data_byte_range();
73 self.data.read_array(range).ok().unwrap_or_default()
74 }
75
76 pub fn major_byte_range(&self) -> Range<usize> {
77 let start = 0;
78 start..start + u8::RAW_BYTE_LEN
79 }
80
81 pub fn minor_byte_range(&self) -> Range<usize> {
82 let start = self.major_byte_range().end;
83 start..start + u8::RAW_BYTE_LEN
84 }
85
86 pub fn hdr_size_byte_range(&self) -> Range<usize> {
87 let start = self.minor_byte_range().end;
88 start..start + u8::RAW_BYTE_LEN
89 }
90
91 pub fn off_size_byte_range(&self) -> Range<usize> {
92 let start = self.hdr_size_byte_range().end;
93 start..start + u8::RAW_BYTE_LEN
94 }
95
96 pub fn _padding_byte_range(&self) -> Range<usize> {
97 let hdr_size = self.hdr_size();
98 let start = self.off_size_byte_range().end;
99 start..start + (transforms::subtract(hdr_size, 4_usize)).saturating_mul(u8::RAW_BYTE_LEN)
100 }
101
102 pub fn trailing_data_byte_range(&self) -> Range<usize> {
103 let start = self._padding_byte_range().end;
104 start..start + self.data.len().saturating_sub(start) / u8::RAW_BYTE_LEN * u8::RAW_BYTE_LEN
105 }
106}
107
108const _: () = assert!(FontData::default_data_long_enough(CffHeader::MIN_SIZE));
109
110impl Default for CffHeader<'_> {
111 fn default() -> Self {
112 Self {
113 data: FontData::default_table_data(),
114 }
115 }
116}
117
118#[cfg(feature = "experimental_traverse")]
119impl<'a> SomeTable<'a> for CffHeader<'a> {
120 fn type_name(&self) -> &str {
121 "CffHeader"
122 }
123 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
124 match idx {
125 0usize => Some(Field::new("major", self.major())),
126 1usize => Some(Field::new("minor", self.minor())),
127 2usize => Some(Field::new("hdr_size", self.hdr_size())),
128 3usize => Some(Field::new("off_size", self.off_size())),
129 4usize => Some(Field::new("_padding", self._padding())),
130 5usize => Some(Field::new("trailing_data", self.trailing_data())),
131 _ => None,
132 }
133 }
134}
135
136#[cfg(feature = "experimental_traverse")]
137#[allow(clippy::needless_lifetimes)]
138impl<'a> std::fmt::Debug for CffHeader<'a> {
139 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
140 (self as &dyn SomeTable<'a>).fmt(f)
141 }
142}
143
144impl<'a> MinByteRange<'a> for Index<'a> {
145 fn min_byte_range(&self) -> Range<usize> {
146 0..self.data_byte_range().end
147 }
148 fn min_table_bytes(&self) -> &'a [u8] {
149 let range = self.min_byte_range();
150 self.data.as_bytes().get(range).unwrap_or_default()
151 }
152}
153
154impl<'a> FontRead<'a> for Index<'a> {
155 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
156 #[allow(clippy::absurd_extreme_comparisons)]
157 if data.len() < Self::MIN_SIZE {
158 return Err(ReadError::OutOfBounds);
159 }
160 Ok(Self { data })
161 }
162}
163
164#[derive(Clone)]
166pub struct Index<'a> {
167 data: FontData<'a>,
168}
169
170#[allow(clippy::needless_lifetimes)]
171impl<'a> Index<'a> {
172 pub const MIN_SIZE: usize = (u16::RAW_BYTE_LEN + u8::RAW_BYTE_LEN);
173 basic_table_impls!(impl_the_methods);
174
175 pub fn count(&self) -> u16 {
177 let range = self.count_byte_range();
178 self.data.read_at(range.start).ok().unwrap()
179 }
180
181 pub fn off_size(&self) -> u8 {
183 let range = self.off_size_byte_range();
184 self.data.read_at(range.start).ok().unwrap()
185 }
186
187 pub fn offsets(&self) -> &'a [u8] {
189 let range = self.offsets_byte_range();
190 self.data.read_array(range).ok().unwrap_or_default()
191 }
192
193 pub fn data(&self) -> &'a [u8] {
195 let range = self.data_byte_range();
196 self.data.read_array(range).ok().unwrap_or_default()
197 }
198
199 pub fn count_byte_range(&self) -> Range<usize> {
200 let start = 0;
201 start..start + u16::RAW_BYTE_LEN
202 }
203
204 pub fn off_size_byte_range(&self) -> Range<usize> {
205 let start = self.count_byte_range().end;
206 start..start + u8::RAW_BYTE_LEN
207 }
208
209 pub fn offsets_byte_range(&self) -> Range<usize> {
210 let count = self.count();
211 let off_size = self.off_size();
212 let start = self.off_size_byte_range().end;
213 start
214 ..start
215 + (transforms::add_multiply(count, 1_usize, off_size))
216 .saturating_mul(u8::RAW_BYTE_LEN)
217 }
218
219 pub fn data_byte_range(&self) -> Range<usize> {
220 let start = self.offsets_byte_range().end;
221 start..start + self.data.len().saturating_sub(start) / u8::RAW_BYTE_LEN * u8::RAW_BYTE_LEN
222 }
223}
224
225const _: () = assert!(FontData::default_data_long_enough(Index::MIN_SIZE));
226
227impl Default for Index<'_> {
228 fn default() -> Self {
229 Self {
230 data: FontData::default_table_data(),
231 }
232 }
233}
234
235#[cfg(feature = "experimental_traverse")]
236impl<'a> SomeTable<'a> for Index<'a> {
237 fn type_name(&self) -> &str {
238 "Index"
239 }
240 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
241 match idx {
242 0usize => Some(Field::new("count", self.count())),
243 1usize => Some(Field::new("off_size", self.off_size())),
244 2usize => Some(Field::new("offsets", self.offsets())),
245 3usize => Some(Field::new("data", self.data())),
246 _ => None,
247 }
248 }
249}
250
251#[cfg(feature = "experimental_traverse")]
252#[allow(clippy::needless_lifetimes)]
253impl<'a> std::fmt::Debug for Index<'a> {
254 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
255 (self as &dyn SomeTable<'a>).fmt(f)
256 }
257}
258
259#[derive(Clone)]
261pub enum FdSelect<'a> {
262 Format0(FdSelectFormat0<'a>),
263 Format3(FdSelectFormat3<'a>),
264 Format4(FdSelectFormat4<'a>),
265}
266
267impl Default for FdSelect<'_> {
268 fn default() -> Self {
269 Self::Format0(Default::default())
270 }
271}
272
273impl<'a> FdSelect<'a> {
274 pub fn offset_data(&self) -> FontData<'a> {
276 match self {
277 Self::Format0(item) => item.offset_data(),
278 Self::Format3(item) => item.offset_data(),
279 Self::Format4(item) => item.offset_data(),
280 }
281 }
282
283 pub fn format(&self) -> u8 {
285 match self {
286 Self::Format0(item) => item.format(),
287 Self::Format3(item) => item.format(),
288 Self::Format4(item) => item.format(),
289 }
290 }
291}
292
293impl<'a> FontRead<'a> for FdSelect<'a> {
294 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
295 let format: u8 = data.read_at(0usize)?;
296 match format {
297 FdSelectFormat0::FORMAT => Ok(Self::Format0(FontRead::read(data)?)),
298 FdSelectFormat3::FORMAT => Ok(Self::Format3(FontRead::read(data)?)),
299 FdSelectFormat4::FORMAT => Ok(Self::Format4(FontRead::read(data)?)),
300 other => Err(ReadError::InvalidFormat(other.into())),
301 }
302 }
303}
304
305impl<'a> MinByteRange<'a> for FdSelect<'a> {
306 fn min_byte_range(&self) -> Range<usize> {
307 match self {
308 Self::Format0(item) => item.min_byte_range(),
309 Self::Format3(item) => item.min_byte_range(),
310 Self::Format4(item) => item.min_byte_range(),
311 }
312 }
313 fn min_table_bytes(&self) -> &'a [u8] {
314 match self {
315 Self::Format0(item) => item.min_table_bytes(),
316 Self::Format3(item) => item.min_table_bytes(),
317 Self::Format4(item) => item.min_table_bytes(),
318 }
319 }
320}
321
322#[cfg(feature = "experimental_traverse")]
323impl<'a> FdSelect<'a> {
324 fn dyn_inner<'b>(&'b self) -> &'b dyn SomeTable<'a> {
325 match self {
326 Self::Format0(table) => table,
327 Self::Format3(table) => table,
328 Self::Format4(table) => table,
329 }
330 }
331}
332
333#[cfg(feature = "experimental_traverse")]
334impl std::fmt::Debug for FdSelect<'_> {
335 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
336 self.dyn_inner().fmt(f)
337 }
338}
339
340#[cfg(feature = "experimental_traverse")]
341impl<'a> SomeTable<'a> for FdSelect<'a> {
342 fn type_name(&self) -> &str {
343 self.dyn_inner().type_name()
344 }
345 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
346 self.dyn_inner().get_field(idx)
347 }
348}
349
350impl Format<u8> for FdSelectFormat0<'_> {
351 const FORMAT: u8 = 0;
352}
353
354impl<'a> MinByteRange<'a> for FdSelectFormat0<'a> {
355 fn min_byte_range(&self) -> Range<usize> {
356 0..self.fds_byte_range().end
357 }
358 fn min_table_bytes(&self) -> &'a [u8] {
359 let range = self.min_byte_range();
360 self.data.as_bytes().get(range).unwrap_or_default()
361 }
362}
363
364impl<'a> FontRead<'a> for FdSelectFormat0<'a> {
365 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
366 #[allow(clippy::absurd_extreme_comparisons)]
367 if data.len() < Self::MIN_SIZE {
368 return Err(ReadError::OutOfBounds);
369 }
370 Ok(Self { data })
371 }
372}
373
374#[derive(Clone)]
376pub struct FdSelectFormat0<'a> {
377 data: FontData<'a>,
378}
379
380#[allow(clippy::needless_lifetimes)]
381impl<'a> FdSelectFormat0<'a> {
382 pub const MIN_SIZE: usize = u8::RAW_BYTE_LEN;
383 basic_table_impls!(impl_the_methods);
384
385 pub fn format(&self) -> u8 {
387 let range = self.format_byte_range();
388 self.data.read_at(range.start).ok().unwrap()
389 }
390
391 pub fn fds(&self) -> &'a [u8] {
393 let range = self.fds_byte_range();
394 self.data.read_array(range).ok().unwrap_or_default()
395 }
396
397 pub fn format_byte_range(&self) -> Range<usize> {
398 let start = 0;
399 start..start + u8::RAW_BYTE_LEN
400 }
401
402 pub fn fds_byte_range(&self) -> Range<usize> {
403 let start = self.format_byte_range().end;
404 start..start + self.data.len().saturating_sub(start) / u8::RAW_BYTE_LEN * u8::RAW_BYTE_LEN
405 }
406}
407
408const _: () = assert!(FontData::default_data_long_enough(
409 FdSelectFormat0::MIN_SIZE
410));
411
412impl Default for FdSelectFormat0<'_> {
413 fn default() -> Self {
414 Self {
415 data: FontData::default_table_data(),
416 }
417 }
418}
419
420#[cfg(feature = "experimental_traverse")]
421impl<'a> SomeTable<'a> for FdSelectFormat0<'a> {
422 fn type_name(&self) -> &str {
423 "FdSelectFormat0"
424 }
425 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
426 match idx {
427 0usize => Some(Field::new("format", self.format())),
428 1usize => Some(Field::new("fds", self.fds())),
429 _ => None,
430 }
431 }
432}
433
434#[cfg(feature = "experimental_traverse")]
435#[allow(clippy::needless_lifetimes)]
436impl<'a> std::fmt::Debug for FdSelectFormat0<'a> {
437 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
438 (self as &dyn SomeTable<'a>).fmt(f)
439 }
440}
441
442impl Format<u8> for FdSelectFormat3<'_> {
443 const FORMAT: u8 = 3;
444}
445
446impl<'a> MinByteRange<'a> for FdSelectFormat3<'a> {
447 fn min_byte_range(&self) -> Range<usize> {
448 0..self.sentinel_byte_range().end
449 }
450 fn min_table_bytes(&self) -> &'a [u8] {
451 let range = self.min_byte_range();
452 self.data.as_bytes().get(range).unwrap_or_default()
453 }
454}
455
456impl<'a> FontRead<'a> for FdSelectFormat3<'a> {
457 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
458 #[allow(clippy::absurd_extreme_comparisons)]
459 if data.len() < Self::MIN_SIZE {
460 return Err(ReadError::OutOfBounds);
461 }
462 Ok(Self { data })
463 }
464}
465
466#[derive(Clone)]
468pub struct FdSelectFormat3<'a> {
469 data: FontData<'a>,
470}
471
472#[allow(clippy::needless_lifetimes)]
473impl<'a> FdSelectFormat3<'a> {
474 pub const MIN_SIZE: usize = (u8::RAW_BYTE_LEN + u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN);
475 basic_table_impls!(impl_the_methods);
476
477 pub fn format(&self) -> u8 {
479 let range = self.format_byte_range();
480 self.data.read_at(range.start).ok().unwrap()
481 }
482
483 pub fn n_ranges(&self) -> u16 {
485 let range = self.n_ranges_byte_range();
486 self.data.read_at(range.start).ok().unwrap()
487 }
488
489 pub fn ranges(&self) -> &'a [FdSelectRange3] {
491 let range = self.ranges_byte_range();
492 self.data.read_array(range).ok().unwrap_or_default()
493 }
494
495 pub fn sentinel(&self) -> u16 {
497 let range = self.sentinel_byte_range();
498 self.data.read_at(range.start).ok().unwrap_or_default()
499 }
500
501 pub fn format_byte_range(&self) -> Range<usize> {
502 let start = 0;
503 start..start + u8::RAW_BYTE_LEN
504 }
505
506 pub fn n_ranges_byte_range(&self) -> Range<usize> {
507 let start = self.format_byte_range().end;
508 start..start + u16::RAW_BYTE_LEN
509 }
510
511 pub fn ranges_byte_range(&self) -> Range<usize> {
512 let n_ranges = self.n_ranges();
513 let start = self.n_ranges_byte_range().end;
514 start..start + (transforms::to_usize(n_ranges)).saturating_mul(FdSelectRange3::RAW_BYTE_LEN)
515 }
516
517 pub fn sentinel_byte_range(&self) -> Range<usize> {
518 let start = self.ranges_byte_range().end;
519 start..start + u16::RAW_BYTE_LEN
520 }
521}
522
523#[cfg(feature = "experimental_traverse")]
524impl<'a> SomeTable<'a> for FdSelectFormat3<'a> {
525 fn type_name(&self) -> &str {
526 "FdSelectFormat3"
527 }
528 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
529 match idx {
530 0usize => Some(Field::new("format", self.format())),
531 1usize => Some(Field::new("n_ranges", self.n_ranges())),
532 2usize => Some(Field::new(
533 "ranges",
534 traversal::FieldType::array_of_records(
535 stringify!(FdSelectRange3),
536 self.ranges(),
537 self.offset_data(),
538 ),
539 )),
540 3usize => Some(Field::new("sentinel", self.sentinel())),
541 _ => None,
542 }
543 }
544}
545
546#[cfg(feature = "experimental_traverse")]
547#[allow(clippy::needless_lifetimes)]
548impl<'a> std::fmt::Debug for FdSelectFormat3<'a> {
549 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
550 (self as &dyn SomeTable<'a>).fmt(f)
551 }
552}
553
554#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
556#[repr(C)]
557#[repr(packed)]
558pub struct FdSelectRange3 {
559 pub first: BigEndian<u16>,
561 pub fd: u8,
563}
564
565impl FdSelectRange3 {
566 pub fn first(&self) -> u16 {
568 self.first.get()
569 }
570
571 pub fn fd(&self) -> u8 {
573 self.fd
574 }
575}
576
577impl FixedSize for FdSelectRange3 {
578 const RAW_BYTE_LEN: usize = u16::RAW_BYTE_LEN + u8::RAW_BYTE_LEN;
579}
580
581#[cfg(feature = "experimental_traverse")]
582impl<'a> SomeRecord<'a> for FdSelectRange3 {
583 fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
584 RecordResolver {
585 name: "FdSelectRange3",
586 get_field: Box::new(move |idx, _data| match idx {
587 0usize => Some(Field::new("first", self.first())),
588 1usize => Some(Field::new("fd", self.fd())),
589 _ => None,
590 }),
591 data,
592 }
593 }
594}
595
596impl Format<u8> for FdSelectFormat4<'_> {
597 const FORMAT: u8 = 4;
598}
599
600impl<'a> MinByteRange<'a> for FdSelectFormat4<'a> {
601 fn min_byte_range(&self) -> Range<usize> {
602 0..self.sentinel_byte_range().end
603 }
604 fn min_table_bytes(&self) -> &'a [u8] {
605 let range = self.min_byte_range();
606 self.data.as_bytes().get(range).unwrap_or_default()
607 }
608}
609
610impl<'a> FontRead<'a> for FdSelectFormat4<'a> {
611 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
612 #[allow(clippy::absurd_extreme_comparisons)]
613 if data.len() < Self::MIN_SIZE {
614 return Err(ReadError::OutOfBounds);
615 }
616 Ok(Self { data })
617 }
618}
619
620#[derive(Clone)]
622pub struct FdSelectFormat4<'a> {
623 data: FontData<'a>,
624}
625
626#[allow(clippy::needless_lifetimes)]
627impl<'a> FdSelectFormat4<'a> {
628 pub const MIN_SIZE: usize = (u8::RAW_BYTE_LEN + u32::RAW_BYTE_LEN + u32::RAW_BYTE_LEN);
629 basic_table_impls!(impl_the_methods);
630
631 pub fn format(&self) -> u8 {
633 let range = self.format_byte_range();
634 self.data.read_at(range.start).ok().unwrap()
635 }
636
637 pub fn n_ranges(&self) -> u32 {
639 let range = self.n_ranges_byte_range();
640 self.data.read_at(range.start).ok().unwrap()
641 }
642
643 pub fn ranges(&self) -> &'a [FdSelectRange4] {
645 let range = self.ranges_byte_range();
646 self.data.read_array(range).ok().unwrap_or_default()
647 }
648
649 pub fn sentinel(&self) -> u32 {
651 let range = self.sentinel_byte_range();
652 self.data.read_at(range.start).ok().unwrap_or_default()
653 }
654
655 pub fn format_byte_range(&self) -> Range<usize> {
656 let start = 0;
657 start..start + u8::RAW_BYTE_LEN
658 }
659
660 pub fn n_ranges_byte_range(&self) -> Range<usize> {
661 let start = self.format_byte_range().end;
662 start..start + u32::RAW_BYTE_LEN
663 }
664
665 pub fn ranges_byte_range(&self) -> Range<usize> {
666 let n_ranges = self.n_ranges();
667 let start = self.n_ranges_byte_range().end;
668 start..start + (transforms::to_usize(n_ranges)).saturating_mul(FdSelectRange4::RAW_BYTE_LEN)
669 }
670
671 pub fn sentinel_byte_range(&self) -> Range<usize> {
672 let start = self.ranges_byte_range().end;
673 start..start + u32::RAW_BYTE_LEN
674 }
675}
676
677#[cfg(feature = "experimental_traverse")]
678impl<'a> SomeTable<'a> for FdSelectFormat4<'a> {
679 fn type_name(&self) -> &str {
680 "FdSelectFormat4"
681 }
682 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
683 match idx {
684 0usize => Some(Field::new("format", self.format())),
685 1usize => Some(Field::new("n_ranges", self.n_ranges())),
686 2usize => Some(Field::new(
687 "ranges",
688 traversal::FieldType::array_of_records(
689 stringify!(FdSelectRange4),
690 self.ranges(),
691 self.offset_data(),
692 ),
693 )),
694 3usize => Some(Field::new("sentinel", self.sentinel())),
695 _ => None,
696 }
697 }
698}
699
700#[cfg(feature = "experimental_traverse")]
701#[allow(clippy::needless_lifetimes)]
702impl<'a> std::fmt::Debug for FdSelectFormat4<'a> {
703 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
704 (self as &dyn SomeTable<'a>).fmt(f)
705 }
706}
707
708#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
710#[repr(C)]
711#[repr(packed)]
712pub struct FdSelectRange4 {
713 pub first: BigEndian<u32>,
715 pub fd: BigEndian<u16>,
717}
718
719impl FdSelectRange4 {
720 pub fn first(&self) -> u32 {
722 self.first.get()
723 }
724
725 pub fn fd(&self) -> u16 {
727 self.fd.get()
728 }
729}
730
731impl FixedSize for FdSelectRange4 {
732 const RAW_BYTE_LEN: usize = u32::RAW_BYTE_LEN + u16::RAW_BYTE_LEN;
733}
734
735#[cfg(feature = "experimental_traverse")]
736impl<'a> SomeRecord<'a> for FdSelectRange4 {
737 fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
738 RecordResolver {
739 name: "FdSelectRange4",
740 get_field: Box::new(move |idx, _data| match idx {
741 0usize => Some(Field::new("first", self.first())),
742 1usize => Some(Field::new("fd", self.fd())),
743 _ => None,
744 }),
745 data,
746 }
747 }
748}
749
750#[derive(Clone)]
752pub enum CustomCharset<'a> {
753 Format0(CharsetFormat0<'a>),
754 Format1(CharsetFormat1<'a>),
755 Format2(CharsetFormat2<'a>),
756}
757
758impl Default for CustomCharset<'_> {
759 fn default() -> Self {
760 Self::Format0(Default::default())
761 }
762}
763
764impl<'a> CustomCharset<'a> {
765 pub fn offset_data(&self) -> FontData<'a> {
767 match self {
768 Self::Format0(item) => item.offset_data(),
769 Self::Format1(item) => item.offset_data(),
770 Self::Format2(item) => item.offset_data(),
771 }
772 }
773
774 pub fn format(&self) -> u8 {
776 match self {
777 Self::Format0(item) => item.format(),
778 Self::Format1(item) => item.format(),
779 Self::Format2(item) => item.format(),
780 }
781 }
782}
783
784impl<'a> FontRead<'a> for CustomCharset<'a> {
785 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
786 let format: u8 = data.read_at(0usize)?;
787 match format {
788 CharsetFormat0::FORMAT => Ok(Self::Format0(FontRead::read(data)?)),
789 CharsetFormat1::FORMAT => Ok(Self::Format1(FontRead::read(data)?)),
790 CharsetFormat2::FORMAT => Ok(Self::Format2(FontRead::read(data)?)),
791 other => Err(ReadError::InvalidFormat(other.into())),
792 }
793 }
794}
795
796impl<'a> MinByteRange<'a> for CustomCharset<'a> {
797 fn min_byte_range(&self) -> Range<usize> {
798 match self {
799 Self::Format0(item) => item.min_byte_range(),
800 Self::Format1(item) => item.min_byte_range(),
801 Self::Format2(item) => item.min_byte_range(),
802 }
803 }
804 fn min_table_bytes(&self) -> &'a [u8] {
805 match self {
806 Self::Format0(item) => item.min_table_bytes(),
807 Self::Format1(item) => item.min_table_bytes(),
808 Self::Format2(item) => item.min_table_bytes(),
809 }
810 }
811}
812
813#[cfg(feature = "experimental_traverse")]
814impl<'a> CustomCharset<'a> {
815 fn dyn_inner<'b>(&'b self) -> &'b dyn SomeTable<'a> {
816 match self {
817 Self::Format0(table) => table,
818 Self::Format1(table) => table,
819 Self::Format2(table) => table,
820 }
821 }
822}
823
824#[cfg(feature = "experimental_traverse")]
825impl std::fmt::Debug for CustomCharset<'_> {
826 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
827 self.dyn_inner().fmt(f)
828 }
829}
830
831#[cfg(feature = "experimental_traverse")]
832impl<'a> SomeTable<'a> for CustomCharset<'a> {
833 fn type_name(&self) -> &str {
834 self.dyn_inner().type_name()
835 }
836 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
837 self.dyn_inner().get_field(idx)
838 }
839}
840
841impl Format<u8> for CharsetFormat0<'_> {
842 const FORMAT: u8 = 0;
843}
844
845impl<'a> MinByteRange<'a> for CharsetFormat0<'a> {
846 fn min_byte_range(&self) -> Range<usize> {
847 0..self.glyph_byte_range().end
848 }
849 fn min_table_bytes(&self) -> &'a [u8] {
850 let range = self.min_byte_range();
851 self.data.as_bytes().get(range).unwrap_or_default()
852 }
853}
854
855impl<'a> FontRead<'a> for CharsetFormat0<'a> {
856 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
857 #[allow(clippy::absurd_extreme_comparisons)]
858 if data.len() < Self::MIN_SIZE {
859 return Err(ReadError::OutOfBounds);
860 }
861 Ok(Self { data })
862 }
863}
864
865#[derive(Clone)]
867pub struct CharsetFormat0<'a> {
868 data: FontData<'a>,
869}
870
871#[allow(clippy::needless_lifetimes)]
872impl<'a> CharsetFormat0<'a> {
873 pub const MIN_SIZE: usize = u8::RAW_BYTE_LEN;
874 basic_table_impls!(impl_the_methods);
875
876 pub fn format(&self) -> u8 {
878 let range = self.format_byte_range();
879 self.data.read_at(range.start).ok().unwrap()
880 }
881
882 pub fn glyph(&self) -> &'a [BigEndian<u16>] {
884 let range = self.glyph_byte_range();
885 self.data.read_array(range).ok().unwrap_or_default()
886 }
887
888 pub fn format_byte_range(&self) -> Range<usize> {
889 let start = 0;
890 start..start + u8::RAW_BYTE_LEN
891 }
892
893 pub fn glyph_byte_range(&self) -> Range<usize> {
894 let start = self.format_byte_range().end;
895 start..start + self.data.len().saturating_sub(start) / u16::RAW_BYTE_LEN * u16::RAW_BYTE_LEN
896 }
897}
898
899const _: () = assert!(FontData::default_data_long_enough(CharsetFormat0::MIN_SIZE));
900
901impl Default for CharsetFormat0<'_> {
902 fn default() -> Self {
903 Self {
904 data: FontData::default_table_data(),
905 }
906 }
907}
908
909#[cfg(feature = "experimental_traverse")]
910impl<'a> SomeTable<'a> for CharsetFormat0<'a> {
911 fn type_name(&self) -> &str {
912 "CharsetFormat0"
913 }
914 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
915 match idx {
916 0usize => Some(Field::new("format", self.format())),
917 1usize => Some(Field::new("glyph", self.glyph())),
918 _ => None,
919 }
920 }
921}
922
923#[cfg(feature = "experimental_traverse")]
924#[allow(clippy::needless_lifetimes)]
925impl<'a> std::fmt::Debug for CharsetFormat0<'a> {
926 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
927 (self as &dyn SomeTable<'a>).fmt(f)
928 }
929}
930
931impl Format<u8> for CharsetFormat1<'_> {
932 const FORMAT: u8 = 1;
933}
934
935impl<'a> MinByteRange<'a> for CharsetFormat1<'a> {
936 fn min_byte_range(&self) -> Range<usize> {
937 0..self.ranges_byte_range().end
938 }
939 fn min_table_bytes(&self) -> &'a [u8] {
940 let range = self.min_byte_range();
941 self.data.as_bytes().get(range).unwrap_or_default()
942 }
943}
944
945impl<'a> FontRead<'a> for CharsetFormat1<'a> {
946 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
947 #[allow(clippy::absurd_extreme_comparisons)]
948 if data.len() < Self::MIN_SIZE {
949 return Err(ReadError::OutOfBounds);
950 }
951 Ok(Self { data })
952 }
953}
954
955#[derive(Clone)]
957pub struct CharsetFormat1<'a> {
958 data: FontData<'a>,
959}
960
961#[allow(clippy::needless_lifetimes)]
962impl<'a> CharsetFormat1<'a> {
963 pub const MIN_SIZE: usize = u8::RAW_BYTE_LEN;
964 basic_table_impls!(impl_the_methods);
965
966 pub fn format(&self) -> u8 {
968 let range = self.format_byte_range();
969 self.data.read_at(range.start).ok().unwrap()
970 }
971
972 pub fn ranges(&self) -> &'a [CharsetRange1] {
974 let range = self.ranges_byte_range();
975 self.data.read_array(range).ok().unwrap_or_default()
976 }
977
978 pub fn format_byte_range(&self) -> Range<usize> {
979 let start = 0;
980 start..start + u8::RAW_BYTE_LEN
981 }
982
983 pub fn ranges_byte_range(&self) -> Range<usize> {
984 let start = self.format_byte_range().end;
985 start
986 ..start
987 + self.data.len().saturating_sub(start) / CharsetRange1::RAW_BYTE_LEN
988 * CharsetRange1::RAW_BYTE_LEN
989 }
990}
991
992const _: () = assert!(FontData::default_data_long_enough(CharsetFormat1::MIN_SIZE));
993
994impl Default for CharsetFormat1<'_> {
995 fn default() -> Self {
996 Self {
997 data: FontData::default_format_1_u8_table_data(),
998 }
999 }
1000}
1001
1002#[cfg(feature = "experimental_traverse")]
1003impl<'a> SomeTable<'a> for CharsetFormat1<'a> {
1004 fn type_name(&self) -> &str {
1005 "CharsetFormat1"
1006 }
1007 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
1008 match idx {
1009 0usize => Some(Field::new("format", self.format())),
1010 1usize => Some(Field::new(
1011 "ranges",
1012 traversal::FieldType::array_of_records(
1013 stringify!(CharsetRange1),
1014 self.ranges(),
1015 self.offset_data(),
1016 ),
1017 )),
1018 _ => None,
1019 }
1020 }
1021}
1022
1023#[cfg(feature = "experimental_traverse")]
1024#[allow(clippy::needless_lifetimes)]
1025impl<'a> std::fmt::Debug for CharsetFormat1<'a> {
1026 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1027 (self as &dyn SomeTable<'a>).fmt(f)
1028 }
1029}
1030
1031#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
1033#[repr(C)]
1034#[repr(packed)]
1035pub struct CharsetRange1 {
1036 pub first: BigEndian<u16>,
1038 pub n_left: u8,
1040}
1041
1042impl CharsetRange1 {
1043 pub fn first(&self) -> u16 {
1045 self.first.get()
1046 }
1047
1048 pub fn n_left(&self) -> u8 {
1050 self.n_left
1051 }
1052}
1053
1054impl FixedSize for CharsetRange1 {
1055 const RAW_BYTE_LEN: usize = u16::RAW_BYTE_LEN + u8::RAW_BYTE_LEN;
1056}
1057
1058#[cfg(feature = "experimental_traverse")]
1059impl<'a> SomeRecord<'a> for CharsetRange1 {
1060 fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
1061 RecordResolver {
1062 name: "CharsetRange1",
1063 get_field: Box::new(move |idx, _data| match idx {
1064 0usize => Some(Field::new("first", self.first())),
1065 1usize => Some(Field::new("n_left", self.n_left())),
1066 _ => None,
1067 }),
1068 data,
1069 }
1070 }
1071}
1072
1073impl Format<u8> for CharsetFormat2<'_> {
1074 const FORMAT: u8 = 2;
1075}
1076
1077impl<'a> MinByteRange<'a> for CharsetFormat2<'a> {
1078 fn min_byte_range(&self) -> Range<usize> {
1079 0..self.ranges_byte_range().end
1080 }
1081 fn min_table_bytes(&self) -> &'a [u8] {
1082 let range = self.min_byte_range();
1083 self.data.as_bytes().get(range).unwrap_or_default()
1084 }
1085}
1086
1087impl<'a> FontRead<'a> for CharsetFormat2<'a> {
1088 fn read(data: FontData<'a>) -> Result<Self, ReadError> {
1089 #[allow(clippy::absurd_extreme_comparisons)]
1090 if data.len() < Self::MIN_SIZE {
1091 return Err(ReadError::OutOfBounds);
1092 }
1093 Ok(Self { data })
1094 }
1095}
1096
1097#[derive(Clone)]
1099pub struct CharsetFormat2<'a> {
1100 data: FontData<'a>,
1101}
1102
1103#[allow(clippy::needless_lifetimes)]
1104impl<'a> CharsetFormat2<'a> {
1105 pub const MIN_SIZE: usize = u8::RAW_BYTE_LEN;
1106 basic_table_impls!(impl_the_methods);
1107
1108 pub fn format(&self) -> u8 {
1110 let range = self.format_byte_range();
1111 self.data.read_at(range.start).ok().unwrap()
1112 }
1113
1114 pub fn ranges(&self) -> &'a [CharsetRange2] {
1116 let range = self.ranges_byte_range();
1117 self.data.read_array(range).ok().unwrap_or_default()
1118 }
1119
1120 pub fn format_byte_range(&self) -> Range<usize> {
1121 let start = 0;
1122 start..start + u8::RAW_BYTE_LEN
1123 }
1124
1125 pub fn ranges_byte_range(&self) -> Range<usize> {
1126 let start = self.format_byte_range().end;
1127 start
1128 ..start
1129 + self.data.len().saturating_sub(start) / CharsetRange2::RAW_BYTE_LEN
1130 * CharsetRange2::RAW_BYTE_LEN
1131 }
1132}
1133
1134#[cfg(feature = "experimental_traverse")]
1135impl<'a> SomeTable<'a> for CharsetFormat2<'a> {
1136 fn type_name(&self) -> &str {
1137 "CharsetFormat2"
1138 }
1139 fn get_field(&self, idx: usize) -> Option<Field<'a>> {
1140 match idx {
1141 0usize => Some(Field::new("format", self.format())),
1142 1usize => Some(Field::new(
1143 "ranges",
1144 traversal::FieldType::array_of_records(
1145 stringify!(CharsetRange2),
1146 self.ranges(),
1147 self.offset_data(),
1148 ),
1149 )),
1150 _ => None,
1151 }
1152 }
1153}
1154
1155#[cfg(feature = "experimental_traverse")]
1156#[allow(clippy::needless_lifetimes)]
1157impl<'a> std::fmt::Debug for CharsetFormat2<'a> {
1158 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1159 (self as &dyn SomeTable<'a>).fmt(f)
1160 }
1161}
1162
1163#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
1165#[repr(C)]
1166#[repr(packed)]
1167pub struct CharsetRange2 {
1168 pub first: BigEndian<u16>,
1170 pub n_left: BigEndian<u16>,
1172}
1173
1174impl CharsetRange2 {
1175 pub fn first(&self) -> u16 {
1177 self.first.get()
1178 }
1179
1180 pub fn n_left(&self) -> u16 {
1182 self.n_left.get()
1183 }
1184}
1185
1186impl FixedSize for CharsetRange2 {
1187 const RAW_BYTE_LEN: usize = u16::RAW_BYTE_LEN + u16::RAW_BYTE_LEN;
1188}
1189
1190#[cfg(feature = "experimental_traverse")]
1191impl<'a> SomeRecord<'a> for CharsetRange2 {
1192 fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
1193 RecordResolver {
1194 name: "CharsetRange2",
1195 get_field: Box::new(move |idx, _data| match idx {
1196 0usize => Some(Field::new("first", self.first())),
1197 1usize => Some(Field::new("n_left", self.n_left())),
1198 _ => None,
1199 }),
1200 data,
1201 }
1202 }
1203}
1204
1205#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
1207#[repr(C)]
1208#[repr(packed)]
1209pub struct EncodingRange1 {
1210 pub first: u8,
1212 pub n_left: u8,
1214}
1215
1216impl EncodingRange1 {
1217 pub fn first(&self) -> u8 {
1219 self.first
1220 }
1221
1222 pub fn n_left(&self) -> u8 {
1224 self.n_left
1225 }
1226}
1227
1228impl FixedSize for EncodingRange1 {
1229 const RAW_BYTE_LEN: usize = u8::RAW_BYTE_LEN + u8::RAW_BYTE_LEN;
1230}
1231
1232#[cfg(feature = "experimental_traverse")]
1233impl<'a> SomeRecord<'a> for EncodingRange1 {
1234 fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
1235 RecordResolver {
1236 name: "EncodingRange1",
1237 get_field: Box::new(move |idx, _data| match idx {
1238 0usize => Some(Field::new("first", self.first())),
1239 1usize => Some(Field::new("n_left", self.n_left())),
1240 _ => None,
1241 }),
1242 data,
1243 }
1244 }
1245}
1246
1247#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, bytemuck :: AnyBitPattern)]
1249#[repr(C)]
1250#[repr(packed)]
1251pub struct EncodingSupplement {
1252 pub code: u8,
1254 pub glyph: BigEndian<u16>,
1256}
1257
1258impl EncodingSupplement {
1259 pub fn code(&self) -> u8 {
1261 self.code
1262 }
1263
1264 pub fn glyph(&self) -> u16 {
1266 self.glyph.get()
1267 }
1268}
1269
1270impl FixedSize for EncodingSupplement {
1271 const RAW_BYTE_LEN: usize = u8::RAW_BYTE_LEN + u16::RAW_BYTE_LEN;
1272}
1273
1274#[cfg(feature = "experimental_traverse")]
1275impl<'a> SomeRecord<'a> for EncodingSupplement {
1276 fn traverse(self, data: FontData<'a>) -> RecordResolver<'a> {
1277 RecordResolver {
1278 name: "EncodingSupplement",
1279 get_field: Box::new(move |idx, _data| match idx {
1280 0usize => Some(Field::new("code", self.code())),
1281 1usize => Some(Field::new("glyph", self.glyph())),
1282 _ => None,
1283 }),
1284 data,
1285 }
1286 }
1287}