As part of an IRC server I'm working on, I am trying to construct a constant &'static str
using other constant strings in an effort to have one source of truth, and I'm having problems because stable const functions for manipulating not only strings, but also Options/Results are lacking. So far I have:
use crate::data::modes::membership_modes::{Item, CONSTS};
const PREFIX: &'static str = unsafe { std::str::from_utf8_unchecked(&assemble_prefix()) };
// ^ The value I'm actually trying to construct
const NUM_PREFIXES: usize = CONSTS.len();
const PREFIX_LENGTH: usize = 2 * NUM_PREFIXES + 2;
const fn assemble_prefix() -> [u8; PREFIX_LENGTH] {
let mut prefix_bytes = [65u8; PREFIX_LENGTH];
prefix_bytes[0] = b'(';
prefix_bytes[NUM_PREFIXES + 1] = b')';
let mut counter = 0;
while counter < NUM_PREFIXES {
let Item::StrRefStrRef((mode, prefix_symbol)) = CONSTS[counter].1;
prefix_bytes[1 + counter] = mode.as_bytes()[0];
prefix_bytes[2 + NUM_PREFIXES + counter] = prefix_symbol.as_bytes()[0];
counter += 1;
}
prefix_bytes
}
(For context, CONSTS
is a const &[(&'static str, Item)]
and Item::StrRefStrRef
, the only variant, contains a (&'static str, &'static str)
- both of these are generated by a macro. The end result I need is a string of a '('
followed by all of the mode
characters, a ')'
and then all of the prefix_symbol
characters.)
Needing unsafe
bothers me, because the only reason I can't use the standard from_utf8
is because I can't unwrap
it while still being const. (And I managed to avoid needing any other unsafe so far) Slightly less bothersome but still annoying is having to declare the length of the array upfront and then cherry-pick characters into the right places rather than building it up. There doesn't seem to be any way to construct it directly as a &str
either.
Is there any way to improve this on stable or make it more idiomatic?