# read-fonts This crate handles parsing and reading of OpenType fonts. It is intended to be a high performance implementation suitable for tasks such as [shaping][], while still providing a convenient, high-level API. ## Safety Unsafe code is forbidden by a `#![forbid(unsafe_code)]` attribute in the root of the library. ## codegen Much of the code in this crate is generated automatically. This generated code lives in the `generated` directory. Each file in this directory is included in a module in the `src` directory, using Rust's [`include!`] macro. This allows us to separate the generated code from any custom implementation code, while allowing them to exist in the same module. ### what we generate With certain exceptions that require manual handling, we generate code for each *table*, *record*, *enum*, and *flags* type for each portion of the spec that we cover. ## tables All tables are newtype structs wrapping what is essentially a byte slice. When a table is parsed, we perform _minimal validation_: that is, we ensure that the provided data is at least long enough to contain all of the required, non-version-dependent fields. All other validation occurs at runtime. If table data is malformed, and a field cannot be read, we will always return a default value. In the case of a versioned field, this will always be `None`; for a field that is expected to always be present, it will be the default value for the type in question, usually either `0` or an empty array. ### variable length and version-dependent fields **n.b**: *the design described below has not been benchmarked against the alternatives, and may change* For fields that have variable length, or which only exist in certain table versions, the marker struct has a corresponding field where that length or offset is stored. This means that at runtime there is no need to double check a version or length. ## records Unlike tables, which are essentially a set of methods for reading into a byte slice, *records* are **in general** represented as simple packed structs containing scalar types in big-endian encodings. This means that, in general, records are zerocopy types that can be cast from raw bytes. The exception to this is when a record has variable length; in this case the record is still a simple struct, but cannot be cast from raw bytes, and must be copied. ## flags and enums For flags, we generate a type modeled on those generated by the [`bitflags!` macro][bitflags]. For enums, we generate a raw Rust enum. [shaping]: https://fonts.google.com/knowledge/glossary/shaping [`include!`]: http://doc.rust-lang.org/1.63.0/std/macro.include.html [gdef-marker]: https://github.com/googlefonts/fontations/blob/main/read-fonts/generated/generated_gdef.rs#L11 [Gdef]: https://github.com/googlefonts/fontations/blob/main/read-fonts/generated/generated_gdef.rs#L77 [bitflags]: https://docs.rs/bitflags/latest/bitflags/