#数据源 #嵌入 #构建

构建 uneval

Serde序列化器,将数据嵌入Rust代码

7个版本

0.2.4 2022年3月30日
0.2.3 2021年12月2日
0.2.2 2021年11月27日
0.2.1 2020年5月1日
0.1.1 2020年4月30日

#158 in 构建工具

Download history 214/week @ 2024-03-13 279/week @ 2024-03-20 376/week @ 2024-03-27 293/week @ 2024-04-03 258/week @ 2024-04-10 295/week @ 2024-04-17 286/week @ 2024-04-24 226/week @ 2024-05-01 304/week @ 2024-05-08 272/week @ 2024-05-15 274/week @ 2024-05-22 316/week @ 2024-05-29 265/week @ 2024-06-05 361/week @ 2024-06-12 249/week @ 2024-06-19 197/week @ 2024-06-26

1,142 每月下载次数
9 个crate中使用 (通过 pai)

MIT 许可证

31KB
466

uneval

Makes Serde serialize your data to the Rust source code.

为什么?

This crate was inspired by the Stack Overflow question. In short, if you want to make some data in the human-readable format, such as JSON, to be deserialized at compile-time and build into the binary, as if it was written by hand, then this crate can possibly help you.

如何使用?

This crate is intended to be used from the build script. It will serialize anything you provide to it to any path you provide (or to the arbitrary io::Write implementation, or into String, if you want to). Then, you'll include! the generated file wherever you want to use it.

它是如何工作的?

See the crate documentation for details. In short, we use information provided by Serde to emit the code, which, when assigned to the variable of correct type, will provide all necessary conversions by using Into and iterators.

它真的这么简单吗?

Well... not. There are several limitations.

  1. All the types used in the serialized struct must be in scope on the include site. Serde doesn't provide the qualified name (i.e. path) to the serializer, only the "last" name. The probably easiest way is to use the serialized data as following
let value: MainType = {
    use ::path::to::Type1;
    // ...and other types
    include!("path/to/file.rs")
}

or the similar construction using lazy_static.

  1. As a consequence, all the types used by the serialized one must have distinct names (or they'll clash with each other).
  2. Deserializer isn't implemented. This is intentional, since this crate isn't really intended for runtime usage. Well, in fact, the deserializer is implemented - it's just the Rust compiler itself.
  3. This serializer is intended for use with derived implementation. It may return bogus results when used with customized Serialize.
  4. 在模块外部定义的私有字段无法序列化结构体。实际上,为了能够序列化这种类型,您必须分发两个版本的crate,其中一个只导出具有派生SerializeSerialize定义,以在第二个版本的构建时由该crate使用。(这不是有点复杂吗?)

如果您发现其他任何不工作的情况,请随时提交问题——我们将修复代码或记录新发现的限制。

测试

该crate使用batch_run运行其测试。

测试用例的常见结构如下

  • 名为definition.rs的文件包含必要的类型。
  • 名为{test_name}-main.rs的文件将definition.rs作为模块包含在内。它包含一个main函数,该函数从definition.rs创建某种类型的实例,在generated.rs中生成相应的Rust代码,并通过batch_run启动{test_name}-user.rs
  • 名为{test_name}-user.rs的文件将definition.rs作为模块包含在内,并通过调用include!包含generated.rs。它检查生成的代码确实创建了与最初创建的数据相等的数据。

测试数据本身定义在test_fixtures/data.toml中,格式如下

  • TOML中的部分名称对应于测试用例的名称。请注意,这不是Cargo测试,而是batch_run批处理中的项目。
  • 字段main_type对应于正在测试其序列化的类型。
  • 如果有多个类型(例如,在嵌套结构中),除了主类型之外的所有其他类型都应该在support_types下以逗号分隔的列表中列出。这些类型与main_type一起将被包含在{test_name}-user.rs中作为导入。
  • 字段definition被直接复制到definition.rs中。由于这些特质在测试运行时使用,因此需要在该处对所有类型实现DebugSerializePartialEq
  • 字段value被直接复制到两个地方:首先是在生成代码的{test_name}-main.rs中;其次是在测试检查两个值是否相等的{test_name}-user.rs中。

许可证

MIT

依赖项

~0.4–1MB
~23K SLoC