Skip to main content

oxa_modelmap/
lib.rs

1//! The single, optional model-renaming injection point defined by spec/03.
2//! oxa libraries carry no built-in model knowledge; callers may supply a
3//! [`Table`], and the table is applied to the model value on both conversion
4//! directions. The model string is otherwise opaque and passes through
5//! verbatim.
6
7use std::collections::BTreeMap;
8
9/// Maps model names to model names. Lookup is exact-match on the keys; on a
10/// miss (or with an empty table) the identity fallback applies and the value
11/// is returned unchanged. No table installed is exactly an empty table.
12#[derive(Clone, Debug, Default, PartialEq, Eq)]
13pub struct Table {
14    entries: BTreeMap<String, String>,
15}
16
17impl Table {
18    pub fn new() -> Self {
19        Self::default()
20    }
21
22    /// Installs one exact-match mapping.
23    pub fn insert(&mut self, from: impl Into<String>, to: impl Into<String>) {
24        self.entries.insert(from.into(), to.into());
25    }
26
27    /// Returns the table entry for `model`, or `model` unchanged when there
28    /// is none.
29    pub fn map(&self, model: &str) -> String {
30        self.entries
31            .get(model)
32            .cloned()
33            .unwrap_or_else(|| model.to_string())
34    }
35}
36
37#[cfg(test)]
38mod tests {
39    use super::*;
40
41    #[test]
42    fn empty_table_is_the_identity() {
43        let table = Table::new();
44        assert_eq!(table.map("gpt-4o-mini"), "gpt-4o-mini");
45    }
46
47    #[test]
48    fn exact_matches_are_rewritten() {
49        let mut table = Table::new();
50        table.insert("gpt-4o-mini", "claude-haiku-4-5");
51        assert_eq!(table.map("gpt-4o-mini"), "claude-haiku-4-5");
52    }
53
54    #[test]
55    fn misses_fall_back_to_identity() {
56        let mut table = Table::new();
57        table.insert("gpt-4o-mini", "claude-haiku-4-5");
58        assert_eq!(table.map("gpt-4o"), "gpt-4o");
59    }
60}