Crate include_data

source ·
Expand description

include_data - Include typed data directly in your executable

The primary API is provided by two macros:

  • include_data - include static data as any plain-old-data type
  • include_slice - include static data as &'static [T] slice for any plain-old-data T

Soundness of types for this purpose is guaranteed via the AnyBitPattern trait from the bytemuck crate. This trait can be implemented on any type and so long as that implementation is sound, then these macros are also sound. As the name suggests, this is true exactly when the type can contain any bit pattern of the correct size.

So for core library types, the following works out of the box:

static MY_INTEGER: i32 = include_data!("../tests/test_data/file_exactly_4_bytes_long");
static SOME_TEXT: &[u32] = include_slice!(u32, "../tests/test_data/some_utf-32_file");
const FOUR_BYTES: [u8; 4] = include_data!("../tests/test_data/file_exactly_4_bytes_long");

Note that include_data works with const, while include_slice only supports static.

For custom types:

#[repr(C)]
#[derive(Copy, Clone)]
struct Foo {
    integer: u16,
    pair: [u8; 2],
}

// Safety: the type `Foo` has been checked to satisfy all requirements of
// `AnyBitPattern`.
unsafe impl bytemuck::Zeroable for Foo {}
unsafe impl bytemuck::AnyBitPattern for Foo {}

static FOO_DATA: Foo = include_data!("../tests/test_data/file_exactly_4_bytes_long");

If necessary, this crate also provides the include_unsafe macro, which is sound if and only if the included file is a valid bit pattern for the target type, but this is not checked. This should be avoided unless absolutely necessary, since it is very unsafe and its soundness is fragile (in some cases, soundness may be broken by a compiler update). See the macro docs for more details.

#[repr(C)]
struct StructWithPadding {
    byte: u8,
    two_bytes: u16,
}

// Safety: we guarantee that the included file contains bytes which are
// a valid bit-pattern for our struct, when compiled on this host.
static BAR_DATA: StructWithPadding = unsafe { include_unsafe!("../tests/test_data/file_exactly_4_bytes_long") };

Platform-specific behaviour

The interpretation of multi-byte sequences depends on a machine’s endianness. In the case of these macros, multi-byte sequences will be interpreted into types according to the endianness of the compilation target, not the compilation host machine.

The interpreation of paths passed to these macros is host-platform specific and identical to that of core::include_bytes.

Macros