Today in #iocaine plans: I realized I don't need a YAML->Roto thing to allow declarative rule configuration. I can bake that into Nam-Shub of Enki. I can teach iocaine to allow loading arbitrary YAML (like it can load arbitrary JSON), and add a few helper functions here and there to allow walking it.

That in turn would allow Nam-Shub of Enki to load its configuration from a YAML declaration. Thus, one would get the benefit of a battle tested configuration, and would be able to tweak it without a single line of Roto.

Okay, lets continue today's thread! Although I kind of get mixed up, and continuity gets broken here and there and... yeah, well, threading on Fedi is a mess. So is my mind.

But! On topic of iocaine.

How about this?

fn decide(request: Request) -> Outcome? {
let m = matchers.get("foo")?;
if m.matches(request.header("user-agent")?) {
return Outcome.garbage()
}

return Outcome.not_for_us()
}

I'm having fun with the new ? operator, and am implementing questionable methods (and am loving that phrase, "questionable methods").

Mind you, I will be moving away from Outcome, but first things first. Eventually, I hope this will look something like the following:

fn main(request: Request) -> Response? {
if FOO.matches(request.user_agent()?) {
return Response.from_template(request, "garbage")
}
return Response.not_for_us()
}

This is exciting. The downside is that... it's really hard to do this step by step. The temptation to just... Replace All The Things™ in one fell swoop is high.

About that HashMap lookup vs Constant performance...

Timer precision: 20 ns
handler fastest │ slowest │ median │ mean │ samples │ iters
├─ request_handler_language_roto_constant 15.07 µs │ 346.8 µs │ 15.71 µs │ 16.06 µs │ 250757 │ 250757
╰─ request_handler_language_roto_hashmap 22.21 µs │ 404.5 µs │ 22.95 µs │ 23.59 µs │ 196716 │ 196716

This is a very simple and naive benchmark:

if iocaine_regexes.get("foo")
.is_match(request.header("user-agent")) {
accept Outcome.challenge()
}

vs

if TEST_REGEX
.is_match(request.header("user-agent")) {
accept Outcome.garbage()
}

With each lookup done ten times per benchmark iteration. There's about ~20-25 such lookups currently in Nam-Shub of Enki, so this appears to be a significant win.

But I'll benchmark with the full Nam-Shub later, once the iocaine side is complete, and once I ported it over.