有没有办法在 Rust 库中包含二进制文件或文本文件?
Is there any way to include binary or text files in a Rust library?
我正在尝试创建一个库,我想在其中包含一些二进制(或文本)文件,这些文件将包含将在运行时解析的数据。
我的意图是控制这些文件,不断更新它们并在每次更新时更改库的版本。
这可以通过货物运输吗?如果是这样,我如何从我的图书馆访问这些文件?
我想到的一个解决方法是包含一些 .rs
带有结构 and/or 常量的文件,例如 &str
,它将存储数据,但我发现它有点难看。
编辑:
我已将已接受的答案更改为更适合我的情况,但请查看 ,因为这可能更适合您的情况。
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!
, as pointed out by :
static HOST_FILE: &'static str = include_str!("/etc/hosts");
fn main() {
println!("Hosts are:\n{}", &HOST_FILE[..42]);
}
免责声明:我在评论中提到了它,但让我在这里重申一下,因为它让我有更多 space 来详细说明。
正如 Shepmaster 所说,可以使用 include_bytes!
和 include_str!
宏在 Rust library/executable 中逐字包含文本或二进制文件。
但是,对于你的情况,我会避免它。通过将内容的解析延迟到 运行-time:
- 您允许构建有缺陷的工件。
- 你招致(更多)运行-时间开销(解析时间)。
- 你招致(更多)space 开销(解析代码)。
Rust 承认这个问题,并提供多种代码生成机制来克服这些限制:
- 宏:如果逻辑可以编码成宏,那么可以直接包含在源文件中
- 插件:启动宏,可以对任意逻辑进行编码并生成复杂的代码(参见
regex!
)
build.rs
: 一个独立的 "Rust script" 运行ning 提前编译本身其作用是生成 .rs
文件
对于您的情况,build.rs
脚本听起来很合适:
- 通过将解析代码移到那里,您交付了一个更轻的工件
- 通过提前解析,您可以更快地交付工件
- 通过提前解析,您交付了正确的工件
解析的结果可以用不同的方式编码,从函数到静态(可能 lazy_static!
),因为 build.rs
可以生成任何有效的 Rust 代码。
您可以在the Cargo Documentation中查看如何使用build.rs
;您会在那里找到如何将它与 Cargo 集成以及如何创建文件(以及更多)。
我正在尝试创建一个库,我想在其中包含一些二进制(或文本)文件,这些文件将包含将在运行时解析的数据。
我的意图是控制这些文件,不断更新它们并在每次更新时更改库的版本。
这可以通过货物运输吗?如果是这样,我如何从我的图书馆访问这些文件?
我想到的一个解决方法是包含一些 .rs
带有结构 and/or 常量的文件,例如 &str
,它将存储数据,但我发现它有点难看。
编辑:
我已将已接受的答案更改为更适合我的情况,但请查看
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!
, as pointed out by
static HOST_FILE: &'static str = include_str!("/etc/hosts");
fn main() {
println!("Hosts are:\n{}", &HOST_FILE[..42]);
}
免责声明:我在评论中提到了它,但让我在这里重申一下,因为它让我有更多 space 来详细说明。
正如 Shepmaster 所说,可以使用 include_bytes!
和 include_str!
宏在 Rust library/executable 中逐字包含文本或二进制文件。
但是,对于你的情况,我会避免它。通过将内容的解析延迟到 运行-time:
- 您允许构建有缺陷的工件。
- 你招致(更多)运行-时间开销(解析时间)。
- 你招致(更多)space 开销(解析代码)。
Rust 承认这个问题,并提供多种代码生成机制来克服这些限制:
- 宏:如果逻辑可以编码成宏,那么可以直接包含在源文件中
- 插件:启动宏,可以对任意逻辑进行编码并生成复杂的代码(参见
regex!
) build.rs
: 一个独立的 "Rust script" 运行ning 提前编译本身其作用是生成.rs
文件
对于您的情况,build.rs
脚本听起来很合适:
- 通过将解析代码移到那里,您交付了一个更轻的工件
- 通过提前解析,您可以更快地交付工件
- 通过提前解析,您交付了正确的工件
解析的结果可以用不同的方式编码,从函数到静态(可能 lazy_static!
),因为 build.rs
可以生成任何有效的 Rust 代码。
您可以在the Cargo Documentation中查看如何使用build.rs
;您会在那里找到如何将它与 Cargo 集成以及如何创建文件(以及更多)。