Jimmy Chu
Jimmy Chu

Reputation: 992

How to create a byte slice constant with specific value?

How do I create a byte slice constant in rust, something as follows?

// This does not compile, but just to show my intention.
pub const MyConst: &'static [u8; 256] = b"abcdef" + [0u8; 250];

// Basically, the value is b"abcdef00000...", the `000...` appended at the end 
// are a series of byte 0, not character 0.

Upvotes: 3

Views: 3697

Answers (3)

loops
loops

Reputation: 5715

On recent nightly compilers, you can now use the unstable concat_bytes! macro to do this:

#![feature(concat_bytes)]
pub const MY_CONST: &[u8; 256] = concat_bytes!(b"abcdef", [0; 250]);

Upvotes: 2

mcarton
mcarton

Reputation: 30101

You can use a const fn to create your array:

const fn foo() -> [u8; 256] {
    let mut a = [0; 256];
    a[0] = b'a';
    a[1] = b'b';
    a[2] = b'c';
    a[3] = b'd';
    a[4] = b'e';
    a[5] = b'f';
    a
}

const FOO: [u8; 256] = foo();

fn main() {
    println!("{:?}", &FOO[0..10]);
}

Note that const fn are still pretty limited, so to my knowledge, you can't do any better than the sequence of a[i] = b at the moment.

Upvotes: 5

E_net4
E_net4

Reputation: 30052

There currently isn't a feature in the language nor in the standard library for combining multiple byte arrays together into a single slice at compile time. There happens to be a pending RFC proposing an extension to the concat! macro, which currently only works for string literals. There are no guarantees that it will ever be approved, though.

A few alternative solutions follow.

  1. Make a UTF-8 string and call as_bytes(). As a string slice however, it won't be possible to include certain character combinations or write a compact representation of [0u8; 250].
pub const BYTES: &[u8] = concat!("abcdef", "\0\0\0\0\0\0\0\0\0\0").as_bytes();
  1. Some crates may claim to provide the solution that you are looking for. See proc_concat_bytes, for example:
use proc_concat_bytes::concat_bytes;
let c_str  = &concat_bytes!(b"Hello World!", b'\0')[..]).unwrap();
  1. Write the bytes to a file, then use include_bytes!.
const BYTES: &[u8; 258] = include_bytes!("bytes.bin");
  1. Enter before-main land and construct a static vector with lazy_static!. We would then have a vector constructed by the program, but should fulfil the intended requirements once built.
use lazy_static::lazy_static;

lazy_static! {
    static ref BYTES: Vec<u8> = {
        let mut data = b"abcdefg".to_vec();
        data.extend(&[0u8; 250][..]);
        data
    };
}

See also:

Upvotes: 5

Related Questions