Search code examples
rustrust-cargo

Is there any way to include data files in a Rust library?


I am trying to create a library and I want to include some binary (or text) files in it that will have data which will be parsed at runtime. My intention is to have control over these files, update them constantly, and change the version of the library in each update.

Is this possible via cargo? If so, how can I access these files from my library?

A workaround I thought of is to include some .rs files with structs and/or constants like &str which will store the data but I find it kind of ugly.


AUTHOR'S NOTE: I have changed the accepted answer to the one that fits more my case, however take a look at Shepmaster's answer as this can be more suitable in your case.


Solution

  • Disclaimer: I mentioned it in a comment, but let me re-iterate here, as it gives me more space to elaborate.

    As Shepmaster said, it is possible to include text or binary verbatim in a Rust library/executable using the include_bytes! and include_str! macros.

    In your case, however, I would avoid it. By deferring the parsing of the content to run-time:

    • you allow building a flawed artifact.
    • you incur (more) run-time overhead (parsing time).
    • you incur (more) space overhead (parsing code).

    Rust acknowledges this issue, and offers multiple mechanisms for code generation destined to overcome those limitations:

    • macros: if the logic can be encoded into a macro, then it can be included in a source file directly
    • plugins: powered up macros, which can encode any arbitrary logic and generate elaborate code (see regex!)
    • build.rs: an independent "Rust script" running ahead of the compilation proper whose role is to generate .rs files

    In your case, the build.rs script sounds like a good fit:

    • by moving the parsing code there, you deliver a lighter artifact
    • by parsing ahead of time, you deliver a faster artifact
    • by parsing ahead of time, you deliver a correct artifact

    The result of your parsing can be encoded in different ways, from functions to statics (possibly lazy_static!), as build.rs can generate any valid Rust code.

    You can see how to use build.rs in the Cargo Documentation; you'll find there how to integrate it with Cargo and how to create files (and more).