Unhinged compile time parsing in rust (without macros)

62 points wyvernbw 27 comments

Did you know that, on nightly, with some unfinished features enabled and some dubious string parsing code, you can parse strings at compile time without proc macros? Heres an example of parsing a keybind (like what you might use for an application to check for input):

#![feature(generic_const_exprs)]
#![feature(const_cmp)]
#![feature(const_index)]
#![feature(const_trait_impl)]
#![feature(unsized_const_params)]
#![feature(adt_const_params)]

struct Hi<const S: &'static str>;

impl<const S: &'static str> Hi<S> {
    fn hello(&self) {
        println!("{S}");
    }
} 

struct Split<const A: &'static str, const DELIM: &'static str>;

impl<const A: &'static str, const DELIM: &'static str> Split<A, DELIM> {
    const LEFT: &'static str = Self::split().0;
    const RIGHT: &'static str = Self::split().1;
    
    const fn split() -> (&'static str, &'static str) {
        let mut i = 0;
        let delim_len = DELIM.len();
        while i < A.len() {
            if &A[i..i+delim_len] == DELIM {
                return (&A[..i], &A[i+delim_len..])
            }
            i += 1;
        }
        ("", &A)
    }
}

struct Literal<const S: &'static str>;

struct Boolean<const B: bool>;

trait IsTrue {}
trait IsFalse {}

impl IsTrue for Boolean<true> {}
impl IsFalse for Boolean<false> {}

impl<const S: &'static str> Literal<S> {
    // std `is_alphanumeric` is not const
    const fn is_alphanumeric() -> bool {
        // we expect a one byte string that is an ascii character
        if S.len() > 1 {
            return false;
        }
        let byte = S.as_bytes()[0] as u32;
        let c = char::from_u32(byte).expect("not a valid char!");
        // yes i realize this is wrong, it should be >=, im stupid 
        (c > 'a' && c <= 'z') || (c > 'A' && c <= 'Z') || (c > '0' && c <= '9')
    }
}

trait Key {}
trait Modifier {}

impl Modifier for Literal<"shift"> {}
impl Modifier for Literal<"ctrl"> {}

trait Alphanumeric {}

impl<const S: &'static str> Alphanumeric for Literal<S> 
where
    Boolean<{Self::is_alphanumeric()}>: IsTrue {}

const fn check_keybind<const K: &'static str>() -> &'static str
where 
    Literal<{Split::<K, "+">::LEFT}>: Modifier,
    Literal<{Split::<K, "+">::RIGHT}>: Alphanumeric,
{
    "valid"
}

fn main() {
    Hi::<{check_keybind::<"ctrl+c">()}>.hello();
    Hi::<{check_keybind::<"does not compile. comment me out">()}>.hello();
}

This fails to compile because of the second line in main, throwing some absolutely indecipherable error, and if you comment it out, the program prints "valid".

link to playground: https://play.rust-lang.org/?version=nightly&mode=debug&edition=2024&gist=c0f411a90bc5aef5147c25d9c6efb60f