44 个版本 (21 个重大更改)

0.21.0 2024年8月16日
0.20.0 2024年7月25日
0.19.3 2024年5月30日
0.18.0 2024年3月20日
0.0.2 2022年10月14日

#53解析器实现

Download history 16986/week @ 2024-05-03 14838/week @ 2024-05-10 13852/week @ 2024-05-17 14838/week @ 2024-05-24 16148/week @ 2024-05-31 12831/week @ 2024-06-07 16007/week @ 2024-06-14 15259/week @ 2024-06-21 15614/week @ 2024-06-28 22715/week @ 2024-07-05 28583/week @ 2024-07-12 27955/week @ 2024-07-19 24025/week @ 2024-07-26 23248/week @ 2024-08-02 27038/week @ 2024-08-09 16680/week @ 2024-08-16

每月94,855 次下载
139 crate 中使用 (3 个直接使用)

MIT/Apache

2.5MB
54K SLoC

read-fonts

这个crate负责解析和读取OpenType字体。它旨在是一个高性能实现,适用于诸如 形状 等任务,同时仍然提供一个方便的高级API。

安全性

通过库根部的 #![forbid(unsafe_code)] 属性禁止不安全代码。

代码生成

这个crate中的大部分代码都是自动生成的。这些生成的代码位于 generated 目录中。该目录中的每个文件都通过Rust的 include! 宏包含在 src 目录中的一个模块中。这使我们能够将生成的代码与任何自定义实现代码分离,同时允许它们存在于同一个模块中。

我们生成的代码

除了需要手动处理的某些异常之外,我们对每个我们覆盖的规范部分中的每个 tablerecordenumflags 类型生成代码。

表格

所有表都是类型为 TableRef<Marker> 的别名,其中 Marker 是一个结构体,用于指示表的类型。例如,GDEF 表 被定义为 TableRef<GdefMarker>TableRef 本身是字节数组切片的包装器,其中 marker 类型提供了对这些字节的类型化访问。

标记类型只能从特定的字节数组创建,并且始终与该数组相关联。它是通过一个 parse 方法创建的,该方法执行一次验证切片,确保所有预期的字段都存在。这包括检查数组的界限,以及确保存在依赖于表版本的字段。

可变长度和版本相关字段

注意:以下描述的设计尚未与替代方案进行基准测试,可能会更改

对于具有可变长度或仅在某些表版本中存在的字段,标记结构体有一个相应的字段,其中存储了该长度或偏移量。这意味着在运行时不需要再次检查版本或长度。

TableRef 方法

对于每个表,我们在类型 TableRef<Marker> 上定义方法,以提供对该表字段的访问。这些方法使用标记类型来确定给定字段的字节数据范围,然后解释这些字节为适当的类型。

记录

与表不同,表本质上是一组读取到字节数组的方法的集合,而 记录 通常表示为包含大端编码标量类型的简单打包结构体。这意味着,通常,记录是零拷贝类型,可以转换为原始字节。

这种情况的例外是,当一个记录具有可变长度时;在这种情况下,记录仍然是一个简单的结构体,但不能从原始字节转换,必须进行复制。

标志和枚举

对于标志,我们生成一个基于 bitflags! 生成的类型的类型。对于枚举,我们生成一个原始 Rust 枚举。

依赖关系

~0.4–1MB
~22K SLoC