stringrustconstants

What is the idiomatic way to build hierarchical const &str values?


I would like to define a const &str that uses the value of another const &str. What is the standard way to do this in Rust?

const FOO: &str = "foo";
const FOOBAR: &str = FOO + "bar"; // "foobar"

fn main() {
    println!("{}{}", "fee", FOOBAR); // "feefoobar"
}

Solution

  • With a dependency, const_format is just few lines of code away:

    const FOOBAR: &str = const_format::concatcp!(FOO, "bar"); // "foobar"
    

    Without dependency this is a bit longer:

    macro_rules! concat_const_str {
        ($a:expr, $b:expr $(,)?) => {{
            const __CONCAT_A: &str = $a;
            const __CONCAT_B: &str = $b;
            const __CONCAT_LEN: usize = __CONCAT_A.len() + __CONCAT_B.len();
            const __CONCAT_STORAGE: [u8; __CONCAT_LEN] = {
                let mut storage = [0; __CONCAT_LEN];
                let a = __CONCAT_A.as_bytes();
                let mut i = 0;
                while i < a.len() {
                    storage[i] = a[i];
                    i += 1;
                }
                let b = __CONCAT_B.as_bytes();
                let mut j = 0;
                while j < b.len() {
                    storage[i] = b[j];
                    j += 1;
                    i += 1;
                }
                storage
            };
            match ::std::str::from_utf8(&__CONCAT_STORAGE) {
                Ok(s) => s,
                Err(_) => unreachable!(),
            }
        }};
    }
    
    const FOO: &str = "foo";
    const FOOBAR: &str = concat_const_str!(FOO, "bar"); // "foobar"