有没有办法在 Rust 库中包含二进制或文本文件?

Posted

技术标签:

【中文标题】有没有办法在 Rust 库中包含二进制或文本文件?【英文标题】:Is there any way to include binary or text files in a Rust library? 【发布时间】:2015-12-21 07:44:50 【问题描述】:

我正在尝试创建一个库,并且我想在其中包含一些二进制(或文本)文件,这些文件将包含将在运行时解析的数据。

我的目的是控制这些文件,不断更新它们,并在每次更新时更改库的版本。

这可以通过货物实现吗?如果是这样,我如何从我的库中访问这些文件?

我想到的一种解决方法是包含一些带有结构和/或常量的.rs 文件,例如&str,它将存储数据,但我觉得它有点难看。

编辑:

我已将接受的答案更改为更适合我情况的答案,但请查看Shepmaster's answer,因为这可能更适合您的情况。

【问题讨论】:

将在运行时解析 => 为什么?由于数据是静态的,将已经解析的数据存储在二进制文件中比在运行时解析它更有效。 Rust 在编译时可以表示的内容相当有限(很不幸),但是您提到维护一个 .rs 文件,因此在您的情况下似乎是可能的。如果是这种情况,那么我建议使用 build.rs 文件,这是 Rust 中的“构建脚本”,它允许您在构建“正确”之前解析源文件并生成 .rs 文件。 更准确地说,这些数据已经被解析并且需要移动到结构体中,比如HashMap,它不能被初始化(至少不使用lazy_static crate)。这就是为什么我需要在运行时“解析”它们。当我想更新数据时,将它们放在二进制(或文本)文件中可以更容易地只替换这个文件。然而,结合使用build.rslazy_static crate 听起来像是一个更好的选择,我会试一试。感谢您的建议! 【参考方案1】:

免责声明:我在评论中提到过,但让我在这里重申一下,因为它给了我更多阐述的空间。

正如 Shepmaster 所说,可以使用 include_bytes!include_str! 宏在 Rust 库/可执行文件中包含文本或二进制逐字记录。

但是,在你的情况下,我会避免它。通过将内容的解析推迟到运行时:

您允许构建有缺陷的工件。 您会产生(更多)运行时开销(解析时间)。 您会产生(更多)空间开销(解析代码)。

Rust 承认了这个问题,并提供了多种代码生成机制来克服这些限制:

宏:如果逻辑可以编码成宏,那么可以直接包含在源文件中 插件:已启动的宏,可以对任意逻辑进行编码并生成精细代码(参见regex!build.rs:在编译之前运行的独立“Rust 脚本”,其作用是生成 .rs 文件

在您的情况下,build.rs 脚​​本听起来很合适:

通过将解析代码移到那里,您可以交付更轻量级的工件 通过提前解析,您可以交付更快的工件 通过提前解析,您可以交付正确的工件

你的解析结果可以用不同的方式编码,从函数到静态(可能是lazy_static!),因为build.rs可以生成任何有效的Rust代码。

您可以在the Cargo Documentation中看到如何使用build.rs;您将在那里找到如何将其与 Cargo 集成以及如何创建文件(等等)。

【讨论】:

【参考方案2】:

include_bytes! 宏似乎与您想要的很接近。它只给你一个字节数组的引用,所以你必须从那个开始做任何解析:

static HOST_FILE: &'static [u8] = include_bytes!("/etc/hosts");

fn main() 
    let host_str = std::str::from_utf8(HOST_FILE).unwrap();

    println!("Hosts are:\n", &host_str[..42]);

如果你有 UTF-8 内容,你可以使用include_str!,正如Benjamin Lindley所指出的那样:

static HOST_FILE: &'static str = include_str!("/etc/hosts");

fn main() 
    println!("Hosts are:\n", &HOST_FILE[..42]);

【讨论】:

如果你想要文本(而不是二进制数据),并且它已经是utf8格式,你不能只使用include_str!,而不是使用include_bytes!然后转换它吗? -- let host_str = include_str!("/etc/hosts"); @BenjaminLindley 嗯,好点子!我看到include! 并意识到它不对但直接跳过include_str!

以上是关于有没有办法在 Rust 库中包含二进制或文本文件?的主要内容,如果未能解决你的问题,请参考以下文章

是否可以在 XML 属性中包含 HTML 文本或 CDATA?

有没有办法在咖啡脚本中包含文件?

在 Rust 中包含特定于 CPU 架构的源文件

在 Xcode 静态库中包含框架?

VS:在 build/exe 中包含资源文件

如何在 CMake 项目中包含外部库