Cached dispatch table

cached HashMap Dispatch

We have lots of functions handling various cases. These are divided into multiple modules based on the types of the cases.

The nice thing seem to be is creating a dispatch table mapping strings to functions.

Each module is responsible for returning a DispatchTable. There is a central function that combines them.

We could generate this up-front and then pass the DispatchTable to each function but it seemed better to get the DispatchTable internally.

If we do that we'll recreate the DispatchTable in every call. Using the cached crate allows us to eliminate all the calls but the first one.

examples/cache-dispatch-table/src/main.rs

use cached::macros::cached;

mod locations;
mod other;
mod types;

use crate::types::DispatchTable;

fn main() {
    for name in &["city", "state", "country", "language"] {
        process(name);
    }
}

fn process(name: &str) {
    let dispatch = get_dispatch();

    println!("Processing: {name}");
    if let Some(process_fn) = dispatch.get(name) {
        let result = process_fn();
        println!("{}", result);
    }
    println!();
}

#[cached]
fn get_dispatch() -> DispatchTable {
    println!("get_dispatch called");

    let mut config = DispatchTable::new();

    let cfg = crate::locations::get_dispatch();
    for (key, value) in cfg {
        config.insert(key, value);
    }

    let cfg = crate::other::get_dispatch();
    for (key, value) in cfg {
        config.insert(key, value);
    }

    config
}

examples/cache-dispatch-table/src/locations.rs

use crate::types::DispatchTable;

fn process_city() -> &'static str {
    "Processing city of Seoul"
}

fn process_country() -> &'static str {
    "Processing country of Korea"
}

pub(crate) fn get_dispatch() -> DispatchTable {
    println!("get_dispatch for locations called");

    let mut config = DispatchTable::new();
    config.insert("city", process_city);
    config.insert("country", process_country);
    config
}

examples/cache-dispatch-table/src/other.rs

use crate::types::DispatchTable;

fn process_language() -> &'static str {
    "Processing the Korean language"
}

pub(crate) fn get_dispatch() -> DispatchTable {
    println!("get_dispatch for locations called");

    let mut config = DispatchTable::new();
    config.insert("language", process_language);
    config
}

examples/cache-dispatch-table/src/types.rs

use std::collections::HashMap;

pub(crate) type Handler = fn() -> &'static str;
pub(crate) type DispatchTable = HashMap<&'static str, Handler>;

examples/cache-dispatch-table/out.txt

get_dispatch called
get_dispatch for locations called
get_dispatch for locations called
Processing: city
Processing city of Seoul

Processing: state

Processing: country
Processing country of Korea

Processing: language
Processing the Korean language


examples/cache-dispatch-table/Cargo.toml

[package]
name = "cache-dispatch-table"
version = "0.1.0"
edition = "2024"

[dependencies]
cached = "2.0.2"

Author

Gabor Szabo (szabgab)

Gabor Szabo, the author of the Rust Maven web site maintains several Open source projects in Rust and while he still feels he has tons of new things to learn about Rust he already offers training courses in Rust and still teaches Python, Perl, git, GitHub, GitLab, CI, and testing.

Gabor Szabo