1 //! Generic traversal of font tables. 2 //! 3 //! This module defines functionality that allows untyped access to font table 4 //! data. This is used as the basis for things like debug printing. 5 //! 6 //! The basis of traversal is the [`SomeTable`] trait, which is implemented for 7 //! all font tables. This trait provides the table's name, as well as ordered access 8 //! to the table's fields. Using this, it is possible to iterate through a table 9 //! and its subtables, records, and values. 10 11 use std::{fmt::Debug, ops::Deref}; 12 13 use types::{ 14 BigEndian, F2Dot14, FWord, Fixed, GlyphId, LongDateTime, MajorMinor, NameId, Nullable, 15 Offset16, Offset24, Offset32, Scalar, Tag, UfWord, Uint24, Version16Dot16, 16 }; 17 18 use crate::{ 19 array::{ComputedArray, VarLenArray}, 20 read::{ComputeSize, ReadArgs}, 21 FontData, FontRead, FontReadWithArgs, ReadError, VarSize, 22 }; 23 24 /// Types of fields in font tables. 25 /// 26 /// Fields can either be scalars, offsets to tables, or arrays. 27 pub enum FieldType<'a> { 28 I8(i8), 29 U8(u8), 30 I16(i16), 31 U16(u16), 32 I32(i32), 33 U32(u32), 34 U24(Uint24), 35 Tag(Tag), 36 FWord(FWord), 37 UfWord(UfWord), 38 MajorMinor(MajorMinor), 39 Version16Dot16(Version16Dot16), 40 F2Dot14(F2Dot14), 41 Fixed(Fixed), 42 LongDateTime(LongDateTime), 43 GlyphId(GlyphId), 44 NameId(NameId), 45 BareOffset(OffsetType), 46 ResolvedOffset(ResolvedOffset<'a>), 47 /// Used in tables like name/post so we can actually print the strings 48 StringOffset(StringOffset<'a>), 49 /// Used in COLR/CPAL 50 ArrayOffset(ArrayOffset<'a>), 51 Record(RecordResolver<'a>), 52 Array(Box<dyn SomeArray<'a> + 'a>), 53 Unknown, 54 } 55 56 /// Any offset type. 57 #[derive(Clone, Copy)] 58 pub enum OffsetType { 59 Offset16(u16), 60 Offset24(Uint24), 61 Offset32(u32), 62 } 63 64 impl OffsetType { 65 /// Return this offset as a u32. to_u32(self) -> u3266 pub fn to_u32(self) -> u32 { 67 match self { 68 Self::Offset16(val) => val.into(), 69 Self::Offset24(val) => val.into(), 70 Self::Offset32(val) => val, 71 } 72 } 73 } 74 75 /// An offset, as well as the table it references. 76 pub struct ResolvedOffset<'a> { 77 /// The raw offset 78 pub offset: OffsetType, 79 /// The parsed table pointed to by this offset, or an error if parsing fails. 80 pub target: Result<Box<dyn SomeTable<'a> + 'a>, ReadError>, 81 } 82 83 /// An offset to string data. 84 /// 85 /// This is a special case for the name table (and maybe elsewhere?) 86 pub struct StringOffset<'a> { 87 pub offset: OffsetType, 88 pub target: Result<Box<dyn SomeString<'a> + 'a>, ReadError>, 89 } 90 91 /// An offset to an array. 92 pub struct ArrayOffset<'a> { 93 pub offset: OffsetType, 94 pub target: Result<Box<dyn SomeArray<'a> + 'a>, ReadError>, 95 } 96 97 pub(crate) struct ArrayOfOffsets<'a, O> { 98 type_name: &'static str, 99 offsets: &'a [O], 100 resolver: Box<dyn Fn(&O) -> FieldType<'a> + 'a>, 101 } 102 103 impl<'a, O> SomeArray<'a> for ArrayOfOffsets<'a, O> { type_name(&self) -> &str104 fn type_name(&self) -> &str { 105 self.type_name 106 } 107 len(&self) -> usize108 fn len(&self) -> usize { 109 self.offsets.len() 110 } 111 get(&self, idx: usize) -> Option<FieldType<'a>>112 fn get(&self, idx: usize) -> Option<FieldType<'a>> { 113 let off = self.offsets.get(idx)?; 114 let target = (self.resolver)(off); 115 Some(target) 116 } 117 } 118 119 impl<'a> FieldType<'a> { 120 /// makes a field, handling the case where this array may not be present in 121 /// all versions array_of_records<T>( type_name: &'static str, records: &'a [T], data: FontData<'a>, ) -> FieldType<'a> where T: Clone + SomeRecord<'a> + 'a,122 pub fn array_of_records<T>( 123 type_name: &'static str, 124 records: &'a [T], 125 data: FontData<'a>, 126 ) -> FieldType<'a> 127 where 128 T: Clone + SomeRecord<'a> + 'a, 129 { 130 ArrayOfRecords { 131 type_name, 132 data, 133 records, 134 } 135 .into() 136 } 137 138 // Convenience method for handling computed arrays computed_array<T>( type_name: &'static str, array: ComputedArray<'a, T>, data: FontData<'a>, ) -> FieldType<'a> where T: FontReadWithArgs<'a> + ComputeSize + SomeRecord<'a> + 'a, T::Args: Copy + 'static,139 pub fn computed_array<T>( 140 type_name: &'static str, 141 array: ComputedArray<'a, T>, 142 data: FontData<'a>, 143 ) -> FieldType<'a> 144 where 145 T: FontReadWithArgs<'a> + ComputeSize + SomeRecord<'a> + 'a, 146 T::Args: Copy + 'static, 147 { 148 ComputedArrayOfRecords { 149 type_name, 150 data, 151 array, 152 } 153 .into() 154 } 155 156 // Convenience method for handling VarLenArrays var_array<T>( type_name: &'static str, array: VarLenArray<'a, T>, data: FontData<'a>, ) -> FieldType<'a> where T: FontRead<'a> + VarSize + SomeRecord<'a> + 'a,157 pub fn var_array<T>( 158 type_name: &'static str, 159 array: VarLenArray<'a, T>, 160 data: FontData<'a>, 161 ) -> FieldType<'a> 162 where 163 T: FontRead<'a> + VarSize + SomeRecord<'a> + 'a, 164 { 165 VarLenArrayOfRecords { 166 type_name, 167 data, 168 array, 169 } 170 .into() 171 } 172 173 /// Convenience method for creating a `FieldType` from an array of offsets. 174 /// 175 /// The `resolver` argument is a function that takes an offset and resolves 176 /// it. array_of_offsets<O>( type_name: &'static str, offsets: &'a [O], resolver: impl Fn(&O) -> FieldType<'a> + 'a, ) -> Self where177 pub fn array_of_offsets<O>( 178 type_name: &'static str, 179 offsets: &'a [O], 180 resolver: impl Fn(&O) -> FieldType<'a> + 'a, 181 ) -> Self 182 where { 183 FieldType::Array(Box::new(ArrayOfOffsets { 184 type_name, 185 offsets, 186 resolver: Box::new(resolver), 187 })) 188 } 189 190 /// Convenience method for creating a `FieldType` from an offset to an array. offset_to_array_of_scalars<T: SomeArray<'a> + 'a>( offset: impl Into<OffsetType>, result: impl Into<Option<Result<T, ReadError>>>, ) -> Self191 pub fn offset_to_array_of_scalars<T: SomeArray<'a> + 'a>( 192 offset: impl Into<OffsetType>, 193 result: impl Into<Option<Result<T, ReadError>>>, 194 ) -> Self { 195 let offset = offset.into(); 196 match result.into() { 197 Some(target) => FieldType::ArrayOffset(ArrayOffset { 198 offset, 199 target: target.map(|x| Box::new(x) as Box<dyn SomeArray>), 200 }), 201 None => FieldType::BareOffset(offset), 202 } 203 } 204 205 /// Convenience method for creating a `FieldType` from an offset to an array. offset_to_array_of_records<T: Clone + SomeRecord<'a> + 'a>( offset: impl Into<OffsetType>, result: impl Into<Option<Result<&'a [T], ReadError>>>, type_name: &'static str, data: FontData<'a>, ) -> Self206 pub fn offset_to_array_of_records<T: Clone + SomeRecord<'a> + 'a>( 207 offset: impl Into<OffsetType>, 208 result: impl Into<Option<Result<&'a [T], ReadError>>>, 209 type_name: &'static str, 210 data: FontData<'a>, 211 ) -> Self { 212 let offset = offset.into(); 213 match result.into() { 214 Some(target) => { 215 let target = target.map(|records| { 216 Box::new(ArrayOfRecords { 217 type_name, 218 data, 219 records, 220 }) as Box<dyn SomeArray> 221 }); 222 FieldType::ArrayOffset(ArrayOffset { offset, target }) 223 } 224 None => FieldType::BareOffset(offset), 225 } 226 } 227 228 //FIXME: I bet this is generating a *lot* of code 229 /// Convenience method for creating a `FieldType` for a resolved offset. 230 /// 231 /// This handles cases where offsets are nullable, in which case the `result` 232 /// argument may be `None`. offset<T: SomeTable<'a> + 'a>( offset: impl Into<OffsetType>, result: impl Into<Option<Result<T, ReadError>>>, ) -> Self233 pub fn offset<T: SomeTable<'a> + 'a>( 234 offset: impl Into<OffsetType>, 235 result: impl Into<Option<Result<T, ReadError>>>, 236 ) -> Self { 237 let offset = offset.into(); 238 match result.into() { 239 Some(target) => FieldType::ResolvedOffset(ResolvedOffset { 240 offset, 241 target: target.map(|x| Box::new(x) as Box<dyn SomeTable>), 242 }), 243 None => FieldType::BareOffset(offset), 244 } 245 } 246 247 /// Convenience method for creating a `FieldType` from an unknown offset. unknown_offset(offset: impl Into<OffsetType>) -> Self248 pub fn unknown_offset(offset: impl Into<OffsetType>) -> Self { 249 Self::BareOffset(offset.into()) 250 } 251 } 252 253 /// A generic field in a font table. 254 pub struct Field<'a> { 255 /// The field's name. 256 pub name: &'static str, 257 /// The field's value. 258 pub value: FieldType<'a>, 259 } 260 261 /// A generic table type. 262 /// 263 /// This is intended to be used as a trait object, and is a way of generically 264 /// representing any table, providing ordered access to that table's fields. 265 pub trait SomeTable<'a> { 266 /// The name of this table type_name(&self) -> &str267 fn type_name(&self) -> &str; 268 /// Access this table's fields, in declaration order. get_field(&self, idx: usize) -> Option<Field<'a>>269 fn get_field(&self, idx: usize) -> Option<Field<'a>>; 270 } 271 272 impl<'a> dyn SomeTable<'a> + 'a { 273 /// Returns an iterator over this table's fields. iter(&self) -> impl Iterator<Item = Field<'a>> + '_274 pub fn iter(&self) -> impl Iterator<Item = Field<'a>> + '_ { 275 FieldIter { 276 table: self, 277 idx: 0, 278 } 279 } 280 } 281 282 struct FieldIter<'a, 'b> { 283 table: &'b dyn SomeTable<'a>, 284 idx: usize, 285 } 286 287 impl<'a, 'b> Iterator for FieldIter<'a, 'b> { 288 type Item = Field<'a>; 289 next(&mut self) -> Option<Self::Item>290 fn next(&mut self) -> Option<Self::Item> { 291 let this = self.idx; 292 self.idx += 1; 293 self.table.get_field(this) 294 } 295 } 296 297 impl<'a> SomeTable<'a> for Box<dyn SomeTable<'a> + 'a> { type_name(&self) -> &str298 fn type_name(&self) -> &str { 299 self.deref().type_name() 300 } 301 get_field(&self, idx: usize) -> Option<Field<'a>>302 fn get_field(&self, idx: usize) -> Option<Field<'a>> { 303 self.deref().get_field(idx) 304 } 305 } 306 307 /// A generic trait for records, which need to be passed in data 308 /// in order to fully resolve themselves. 309 pub trait SomeRecord<'a> { traverse(self, data: FontData<'a>) -> RecordResolver<'a>310 fn traverse(self, data: FontData<'a>) -> RecordResolver<'a>; 311 } 312 313 /// A struct created from a record and the data it needs to resolve any 314 /// contained offsets. 315 pub struct RecordResolver<'a> { 316 pub(crate) name: &'static str, 317 pub(crate) get_field: Box<dyn Fn(usize, FontData<'a>) -> Option<Field<'a>> + 'a>, 318 pub(crate) data: FontData<'a>, 319 } 320 321 /// A generic trait for arrays. 322 pub trait SomeArray<'a> { 323 /// The name of this type. For an array of u16s, this is `[u16]`. type_name(&self) -> &str324 fn type_name(&self) -> &str; 325 326 /// The length of the array. len(&self) -> usize327 fn len(&self) -> usize; 328 329 /// Returns `true` if this array is empty. is_empty(&self) -> bool330 fn is_empty(&self) -> bool { 331 self.len() == 0 332 } 333 334 /// Return the item at `idx`, or `None` if `idx` is out of bounds. get(&self, idx: usize) -> Option<FieldType<'a>>335 fn get(&self, idx: usize) -> Option<FieldType<'a>>; 336 } 337 338 impl<'a> dyn SomeArray<'a> + 'a { 339 /// Return an iterator over the contents of this array. iter(&self) -> impl Iterator<Item = FieldType<'a>> + '_340 pub fn iter(&self) -> impl Iterator<Item = FieldType<'a>> + '_ { 341 ArrayIter { 342 array: self, 343 idx: 0, 344 } 345 } 346 } 347 348 struct ArrayIter<'a, 'b> { 349 array: &'b dyn SomeArray<'a>, 350 idx: usize, 351 } 352 353 impl<'a, 'b> Iterator for ArrayIter<'a, 'b> { 354 type Item = FieldType<'a>; 355 next(&mut self) -> Option<Self::Item>356 fn next(&mut self) -> Option<Self::Item> { 357 let this = self.idx; 358 self.idx += 1; 359 self.array.get(this) 360 } 361 } 362 363 impl<'a, T: Scalar + Into<FieldType<'a>>> SomeArray<'a> for &'a [BigEndian<T>] 364 where 365 BigEndian<T>: Copy, // i don't know why i need this?? 366 { len(&self) -> usize367 fn len(&self) -> usize { 368 (*self).len() 369 } 370 get(&self, idx: usize) -> Option<FieldType<'a>>371 fn get(&self, idx: usize) -> Option<FieldType<'a>> { 372 (*self).get(idx).map(|val| val.get().into()) 373 } 374 type_name(&self) -> &str375 fn type_name(&self) -> &str { 376 let full_name = std::any::type_name::<T>(); 377 full_name.split("::").last().unwrap_or(full_name) 378 } 379 } 380 381 impl<'a> SomeArray<'a> for &'a [u8] { type_name(&self) -> &str382 fn type_name(&self) -> &str { 383 "u8" 384 } 385 len(&self) -> usize386 fn len(&self) -> usize { 387 (*self).len() 388 } 389 get(&self, idx: usize) -> Option<FieldType<'a>>390 fn get(&self, idx: usize) -> Option<FieldType<'a>> { 391 (*self).get(idx).copied().map(Into::into) 392 } 393 } 394 395 impl<'a> SomeArray<'a> for Box<dyn SomeArray<'a> + 'a> { type_name(&self) -> &str396 fn type_name(&self) -> &str { 397 self.deref().type_name() 398 } 399 len(&self) -> usize400 fn len(&self) -> usize { 401 self.deref().len() 402 } 403 get(&self, idx: usize) -> Option<FieldType<'a>>404 fn get(&self, idx: usize) -> Option<FieldType<'a>> { 405 self.deref().get(idx) 406 } 407 } 408 409 pub trait SomeString<'a> { iter_chars(&self) -> Box<dyn Iterator<Item = char> + 'a>410 fn iter_chars(&self) -> Box<dyn Iterator<Item = char> + 'a>; 411 } 412 413 impl<'a> SomeString<'a> for Box<dyn SomeString<'a> + 'a> { iter_chars(&self) -> Box<dyn Iterator<Item = char> + 'a>414 fn iter_chars(&self) -> Box<dyn Iterator<Item = char> + 'a> { 415 self.deref().iter_chars() 416 } 417 } 418 419 // only used as Box<dyn SomeArray<'a>> 420 struct ArrayOfRecords<'a, T> { 421 pub(crate) type_name: &'static str, 422 pub(crate) data: FontData<'a>, 423 pub(crate) records: &'a [T], 424 } 425 426 // only used as Box<dyn SomeArray<'a>> 427 struct ComputedArrayOfRecords<'a, T: ReadArgs> { 428 pub(crate) type_name: &'static str, 429 pub(crate) data: FontData<'a>, 430 pub(crate) array: ComputedArray<'a, T>, 431 } 432 433 struct VarLenArrayOfRecords<'a, T> { 434 pub(crate) type_name: &'static str, 435 pub(crate) data: FontData<'a>, 436 pub(crate) array: VarLenArray<'a, T>, 437 } 438 439 impl<'a, T> SomeArray<'a> for ComputedArrayOfRecords<'a, T> 440 where 441 T: FontReadWithArgs<'a> + ComputeSize + SomeRecord<'a> + 'a, 442 T::Args: Copy + 'static, 443 Self: 'a, 444 { len(&self) -> usize445 fn len(&self) -> usize { 446 self.array.len() 447 } 448 get(&self, idx: usize) -> Option<FieldType<'a>>449 fn get(&self, idx: usize) -> Option<FieldType<'a>> { 450 self.array 451 .get(idx) 452 .ok() 453 .map(|record| record.traverse(self.data).into()) 454 } 455 type_name(&self) -> &str456 fn type_name(&self) -> &str { 457 self.type_name 458 } 459 } 460 461 impl<'a, T: SomeRecord<'a> + Clone> SomeArray<'a> for ArrayOfRecords<'a, T> { type_name(&self) -> &str462 fn type_name(&self) -> &str { 463 self.type_name 464 } 465 len(&self) -> usize466 fn len(&self) -> usize { 467 self.records.len() 468 } 469 get(&self, idx: usize) -> Option<FieldType<'a>>470 fn get(&self, idx: usize) -> Option<FieldType<'a>> { 471 self.records 472 .get(idx) 473 .map(|record| record.clone().traverse(self.data).into()) 474 } 475 } 476 477 impl<'a, T> SomeArray<'a> for VarLenArrayOfRecords<'a, T> 478 where 479 T: FontRead<'a> + VarSize + SomeRecord<'a> + 'a, 480 Self: 'a, 481 { len(&self) -> usize482 fn len(&self) -> usize { 483 self.array.iter().count() 484 } 485 get(&self, idx: usize) -> Option<FieldType<'a>>486 fn get(&self, idx: usize) -> Option<FieldType<'a>> { 487 self.array 488 .get(idx)? 489 .ok() 490 .map(|record| record.traverse(self.data).into()) 491 } 492 type_name(&self) -> &str493 fn type_name(&self) -> &str { 494 self.type_name 495 } 496 } 497 498 impl<'a> Field<'a> { 499 /// Create a new field with the given name and value. new(name: &'static str, value: impl Into<FieldType<'a>>) -> Self500 pub fn new(name: &'static str, value: impl Into<FieldType<'a>>) -> Self { 501 Field { 502 name, 503 value: value.into(), 504 } 505 } 506 } 507 508 /// A wrapper type that implements `Debug` for any table. 509 struct DebugPrintTable<'a, 'b>(pub &'b (dyn SomeTable<'a> + 'a)); 510 511 /// A wrapper type that implements `Debug` for any array. 512 struct DebugPrintArray<'a, 'b>(pub &'b (dyn SomeArray<'a> + 'a)); 513 514 impl<'a> Debug for FieldType<'a> { fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result515 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 516 match self { 517 Self::I8(arg0) => arg0.fmt(f), 518 Self::U8(arg0) => arg0.fmt(f), 519 Self::I16(arg0) => arg0.fmt(f), 520 Self::U16(arg0) => arg0.fmt(f), 521 Self::I32(arg0) => arg0.fmt(f), 522 Self::U32(arg0) => arg0.fmt(f), 523 Self::U24(arg0) => arg0.fmt(f), 524 Self::Tag(arg0) => arg0.fmt(f), 525 Self::FWord(arg0) => arg0.to_i16().fmt(f), 526 Self::UfWord(arg0) => arg0.to_u16().fmt(f), 527 Self::MajorMinor(arg0) => write!(f, "{}.{}", arg0.major, arg0.minor), 528 Self::Version16Dot16(arg0) => arg0.fmt(f), 529 Self::F2Dot14(arg0) => arg0.fmt(f), 530 Self::Fixed(arg0) => arg0.fmt(f), 531 Self::LongDateTime(arg0) => arg0.as_secs().fmt(f), 532 Self::GlyphId(arg0) => { 533 write!(f, "g")?; 534 arg0.to_u16().fmt(f) 535 } 536 Self::NameId(arg0) => arg0.fmt(f), 537 Self::StringOffset(string) => match &string.target { 538 Ok(arg0) => arg0.as_ref().fmt(f), 539 Err(_) => string.target.fmt(f), 540 }, 541 Self::ArrayOffset(array) => match &array.target { 542 Ok(arg0) => arg0.as_ref().fmt(f), 543 Err(_) => array.target.fmt(f), 544 }, 545 Self::BareOffset(arg0) => write!(f, "0x{:04X}", arg0.to_u32()), 546 Self::ResolvedOffset(ResolvedOffset { 547 target: Ok(arg0), .. 548 }) => arg0.fmt(f), 549 Self::ResolvedOffset(arg0) => arg0.target.fmt(f), 550 Self::Record(arg0) => (arg0 as &(dyn SomeTable<'a> + 'a)).fmt(f), 551 Self::Array(arg0) => arg0.fmt(f), 552 Self::Unknown => write!(f, "no repr available"), 553 } 554 } 555 } 556 557 impl<'a, 'b> std::fmt::Debug for DebugPrintTable<'a, 'b> { fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result558 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { 559 let mut debug_struct = f.debug_struct(self.0.type_name()); 560 for field in self.0.iter() { 561 debug_struct.field(field.name, &field.value); 562 } 563 debug_struct.finish() 564 } 565 } 566 567 impl<'a> Debug for dyn SomeTable<'a> + 'a { fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result568 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 569 DebugPrintTable(self).fmt(f) 570 } 571 } 572 573 impl<'a> Debug for dyn SomeString<'a> + 'a { fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result574 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { 575 write!(f, "\"")?; 576 for c in self.iter_chars() { 577 write!(f, "{c}")? 578 } 579 write!(f, "\"") 580 } 581 } 582 583 impl<'a, 'b> std::fmt::Debug for DebugPrintArray<'a, 'b> { fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result584 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { 585 let mut debug_list = f.debug_list(); 586 let mut idx = 0; 587 while let Some(item) = self.0.get(idx) { 588 idx += 1; 589 debug_list.entry(&item); 590 } 591 debug_list.finish() 592 } 593 } 594 595 impl<'a> Debug for dyn SomeArray<'a> + 'a { fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result596 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 597 DebugPrintArray(self).fmt(f) 598 } 599 } 600 601 impl std::fmt::Display for OffsetType { fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result602 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { 603 write!(f, "{:+}", self.to_u32()) 604 } 605 } 606 607 // used to give us an auto-impl of Debug 608 impl<'a> SomeTable<'a> for RecordResolver<'a> { type_name(&self) -> &str609 fn type_name(&self) -> &str { 610 self.name 611 } 612 get_field(&self, idx: usize) -> Option<Field<'a>>613 fn get_field(&self, idx: usize) -> Option<Field<'a>> { 614 (self.get_field)(idx, self.data) 615 } 616 } 617 618 impl<'a> From<u8> for FieldType<'a> { from(src: u8) -> FieldType<'a>619 fn from(src: u8) -> FieldType<'a> { 620 FieldType::U8(src) 621 } 622 } 623 624 impl<'a> From<i8> for FieldType<'a> { from(src: i8) -> FieldType<'a>625 fn from(src: i8) -> FieldType<'a> { 626 FieldType::I8(src) 627 } 628 } 629 630 impl<'a> From<u16> for FieldType<'a> { from(src: u16) -> FieldType<'a>631 fn from(src: u16) -> FieldType<'a> { 632 FieldType::U16(src) 633 } 634 } 635 636 impl<'a> From<i16> for FieldType<'a> { from(src: i16) -> FieldType<'a>637 fn from(src: i16) -> FieldType<'a> { 638 FieldType::I16(src) 639 } 640 } 641 642 impl<'a> From<u32> for FieldType<'a> { from(src: u32) -> FieldType<'a>643 fn from(src: u32) -> FieldType<'a> { 644 FieldType::U32(src) 645 } 646 } 647 648 impl<'a> From<i32> for FieldType<'a> { from(src: i32) -> FieldType<'a>649 fn from(src: i32) -> FieldType<'a> { 650 FieldType::I32(src) 651 } 652 } 653 654 impl<'a> From<Uint24> for FieldType<'a> { from(src: Uint24) -> FieldType<'a>655 fn from(src: Uint24) -> FieldType<'a> { 656 FieldType::U24(src) 657 } 658 } 659 660 impl<'a> From<Tag> for FieldType<'a> { from(src: Tag) -> FieldType<'a>661 fn from(src: Tag) -> FieldType<'a> { 662 FieldType::Tag(src) 663 } 664 } 665 666 impl<'a> From<FWord> for FieldType<'a> { from(src: FWord) -> FieldType<'a>667 fn from(src: FWord) -> FieldType<'a> { 668 FieldType::FWord(src) 669 } 670 } 671 672 impl<'a> From<UfWord> for FieldType<'a> { from(src: UfWord) -> FieldType<'a>673 fn from(src: UfWord) -> FieldType<'a> { 674 FieldType::UfWord(src) 675 } 676 } 677 678 impl<'a> From<Fixed> for FieldType<'a> { from(src: Fixed) -> FieldType<'a>679 fn from(src: Fixed) -> FieldType<'a> { 680 FieldType::Fixed(src) 681 } 682 } 683 684 impl<'a> From<F2Dot14> for FieldType<'a> { from(src: F2Dot14) -> FieldType<'a>685 fn from(src: F2Dot14) -> FieldType<'a> { 686 FieldType::F2Dot14(src) 687 } 688 } 689 690 impl<'a> From<LongDateTime> for FieldType<'a> { from(src: LongDateTime) -> FieldType<'a>691 fn from(src: LongDateTime) -> FieldType<'a> { 692 FieldType::LongDateTime(src) 693 } 694 } 695 696 impl<'a> From<MajorMinor> for FieldType<'a> { from(src: MajorMinor) -> FieldType<'a>697 fn from(src: MajorMinor) -> FieldType<'a> { 698 FieldType::MajorMinor(src) 699 } 700 } 701 702 impl<'a> From<Version16Dot16> for FieldType<'a> { from(src: Version16Dot16) -> FieldType<'a>703 fn from(src: Version16Dot16) -> FieldType<'a> { 704 FieldType::Version16Dot16(src) 705 } 706 } 707 708 impl<'a> From<GlyphId> for FieldType<'a> { from(src: GlyphId) -> FieldType<'a>709 fn from(src: GlyphId) -> FieldType<'a> { 710 FieldType::GlyphId(src) 711 } 712 } 713 714 impl<'a> From<NameId> for FieldType<'a> { from(src: NameId) -> FieldType<'a>715 fn from(src: NameId) -> FieldType<'a> { 716 FieldType::NameId(src) 717 } 718 } 719 720 impl<'a> From<RecordResolver<'a>> for FieldType<'a> { from(src: RecordResolver<'a>) -> Self721 fn from(src: RecordResolver<'a>) -> Self { 722 FieldType::Record(src) 723 } 724 } 725 726 impl<'a, T: SomeArray<'a> + 'a> From<T> for FieldType<'a> { from(src: T) -> Self727 fn from(src: T) -> Self { 728 FieldType::Array(Box::new(src)) 729 } 730 } 731 732 impl From<Offset16> for OffsetType { from(src: Offset16) -> OffsetType733 fn from(src: Offset16) -> OffsetType { 734 OffsetType::Offset16(src.to_u32() as u16) 735 } 736 } 737 738 impl From<Offset24> for OffsetType { from(src: Offset24) -> OffsetType739 fn from(src: Offset24) -> OffsetType { 740 OffsetType::Offset24(Uint24::new(src.to_u32())) 741 } 742 } 743 744 impl From<Offset32> for OffsetType { from(src: Offset32) -> OffsetType745 fn from(src: Offset32) -> OffsetType { 746 OffsetType::Offset32(src.to_u32()) 747 } 748 } 749 750 impl<'a> From<Offset16> for FieldType<'a> { from(src: Offset16) -> FieldType<'a>751 fn from(src: Offset16) -> FieldType<'a> { 752 FieldType::BareOffset(src.into()) 753 } 754 } 755 756 impl<'a> From<Offset24> for FieldType<'a> { from(src: Offset24) -> FieldType<'a>757 fn from(src: Offset24) -> FieldType<'a> { 758 FieldType::BareOffset(src.into()) 759 } 760 } 761 762 impl<'a> From<Offset32> for FieldType<'a> { from(src: Offset32) -> FieldType<'a>763 fn from(src: Offset32) -> FieldType<'a> { 764 FieldType::BareOffset(src.into()) 765 } 766 } 767 768 impl<T: Into<OffsetType> + Clone> From<Nullable<T>> for OffsetType { from(src: Nullable<T>) -> Self769 fn from(src: Nullable<T>) -> Self { 770 src.offset().clone().into() 771 } 772 } 773