Dynamic Dispatch With Trait Objects

Store heterogeneous implementations behind a Box dyn trait to select behaviour at runtime, trading monomorphisation for flexibility.

RustConfig Management

Code

snippet
trait Exporter {
    fn name(&self) -> &str;
    fn export(&self, rows: &[String]) -> String;
}

struct CsvExporter;
struct JsonExporter;

impl Exporter for CsvExporter {
    fn name(&self) -> &str {
        "csv"
    }

    fn export(&self, rows: &[String]) -> String {
        rows.join("\n")
    }
}

impl Exporter for JsonExporter {
    fn name(&self) -> &str {
        "json"
    }

    fn export(&self, rows: &[String]) -> String {
        let items: Vec<String> = rows.iter().map(|r| format!("\"{r}\"")).collect();
        format!("[{}]", items.join(","))
    }
}

fn select(name: &str) -> Option<Box<dyn Exporter>> {
    match name {
        "csv" => Some(Box::new(CsvExporter)),
        "json" => Some(Box::new(JsonExporter)),
        _ => None,
    }
}