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

Oto*_*obo 9 binaryfiles libraries rust rust-cargo

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

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

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

我想到的一个解决方法是包含一些.rs带有结构和/或常量的文件,这些文件&str会存储数据,但我觉得它很难看.

编辑:

我已经将接受的答案更改为更适合我的案例,但请查看Shepmaster的答案,因为这可能更适合您的情况.

Mat*_* M. 12

免责声明:我在评论中提到过,但让我在这里重复一遍,因为它给了我更多的篇幅.

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

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

  • 你允许建造一个有缺陷的神器.
  • 你会产生(更多)运行时开销(解析时间).
  • 你会产生(更多)空间开销(解析代码).

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

  • 宏:如果逻辑可以编码为宏,那么它可以直接包含在源文件中
  • 插件:上电宏,可以编码任意逻辑并生成精细的代码(请参阅参考资料regex!)
  • build.rs:一个独立的"Rust脚本",在编译之前运行,其作用是生成.rs文件

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

  • 通过在那里移动解析代码,您可以提供更轻的工件
  • 通过提前解析,您可以提供更快的工件
  • 通过提前解析,您可以提供正确的工件

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

您可以build.rs货物文档中看到如何使用; 你会发现如何将它与Cargo集成以及如何创建文件(以及更多).


She*_*ter 10

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]);
}
Run Code Online (Sandbox Code Playgroud)

如果您有UTF-8内容,您可以使用Benjamin Lindleyinclude_str!所指出的:

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

fn main() {
    println!("Hosts are:\n{}", &HOST_FILE[..42]);
}
Run Code Online (Sandbox Code Playgroud)

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