Hew v0.5 — redis-like KV store (in-process actor + ask, RESP-style protocol)
// In-process redis-like KV store (v0.5 Hew).
//
// The actor + HashMap + ask CORE a networked redis server is built on. The TCP
// front-end is currently blocked by the D10 module-qualified-type-in-Result
// codegen gap (`import std::net`), so this drives the store with a scripted client
// session instead of over a socket.
//
// The actor receives ONE command-line string and returns a RESP-style reply
// string (+OK / +value / -NOT_FOUND / :count). A single string arg keeps within
// the current "one argument per receive" limit, and parsing the command line in
// the actor is how a real redis server works anyway.
actor Store {
    let data: HashMap<string, string>;
    receive fn exec(line: string) -> string {
        let cmd = line.trim();
        if cmd == "PING" {
            "+PONG"
        } else if cmd == "DBSIZE" {
            let n = data.len();
            f":{n}"
        } else if cmd.starts_with("SET ") {
            let rest = cmd.slice(4, cmd.len());
            let sp = rest.find(" ");
            if sp < 0 {
                "-ERR usage: SET key value"
            } else {
                let key = rest.slice(0, sp);
                let value = rest.slice(sp + 1, rest.len());
                data.insert(key, value);
                "+OK"
            }
        } else if cmd.starts_with("GET ") {
            let key = cmd.slice(4, cmd.len());
            match data.get(key) {
                Some(val) => f"+{val}",
                None => "-NOT_FOUND",
            }
        } else if cmd.starts_with("DEL ") {
            let key = cmd.slice(4, cmd.len());
            if data.contains_key(key) {
                data.remove(key);
                "+OK"
            } else {
                "-NOT_FOUND"
            }
        } else {
            "-ERR unknown command"
        }
    }
}

fn call(store: LocalPid<Store>, line: string) -> string {
    match await store.exec(line) {
        Ok(reply) => reply,
        Err(_) => "-ASK_FAILED",
    }
}

fn main() -> i64 {
    let data: HashMap<string, string> = HashMap::new();
    let store = spawn Store(data: data);
    var ok = true;
    let r1 = call(store, "PING");
    println(f"PING            -> {r1}");
    if r1 != "+PONG" {
        ok = false;
    }
    let r2 = call(store, "SET foo bar");
    println(f"SET foo bar     -> {r2}");
    if r2 != "+OK" {
        ok = false;
    }
    let r3 = call(store, "GET foo");
    println(f"GET foo         -> {r3}");
    if r3 != "+bar" {
        ok = false;
    }
    let r4 = call(store, "DBSIZE");
    println(f"DBSIZE          -> {r4}");
    if r4 != ":1" {
        ok = false;
    }
    let r5 = call(store, "DEL foo");
    println(f"DEL foo         -> {r5}");
    if r5 != "+OK" {
        ok = false;
    }
    let r6 = call(store, "GET foo");
    println(f"GET foo (gone)  -> {r6}");
    if r6 != "-NOT_FOUND" {
        ok = false;
    }
    if ok {
        0
    } else {
        1
    }
}