use serde::Deserialize;
use std::sync::OnceLock;
const EMBEDDED_JSON: &str = include_str!("../../data/obis_medien.json");
#[derive(Debug, Clone, Deserialize)]
pub struct Obis {
pub obis: String,
pub name: String,
pub chapter: String,
pub pids: Vec<String>,
}
#[derive(Debug, Clone, Deserialize)]
pub struct Medium {
pub code: String,
pub name: String,
pub pids: Vec<String>,
}
#[derive(Debug, Deserialize)]
struct Table {
obis: Vec<Obis>,
medien: Vec<Medium>,
}
fn table() -> &'static Table {
static TABLE: OnceLock<Table> = OnceLock::new();
TABLE.get_or_init(|| serde_json::from_str(EMBEDDED_JSON).expect("embedded obis_medien.json"))
}
pub fn obis_for_pid(pid: &str) -> impl Iterator<Item = &'static Obis> + '_ {
table()
.obis
.iter()
.filter(move |o| o.pids.iter().any(|p| p == pid))
}
pub fn medien_for_pid(pid: &str) -> impl Iterator<Item = &'static Medium> + '_ {
table()
.medien
.iter()
.filter(move |m| m.pids.iter().any(|p| p == pid))
}
pub fn concrete(obis: &str) -> String {
obis.replace(['b', 'e'], "0")
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn mscons_pids_get_their_values() {
let allokation: Vec<_> = obis_for_pid("13013").map(|o| o.obis.as_str()).collect();
assert_eq!(allokation, ["7-b:9.98.0"]);
let menge: Vec<_> = obis_for_pid("13014").map(|o| o.obis.as_str()).collect();
assert_eq!(menge, ["1-b:1.98.0", "7-b:9.98.1"]);
let ausfall: Vec<_> = medien_for_pid("13020").map(|m| m.code.as_str()).collect();
assert_eq!(ausfall, ["AUA"]);
let wetter: Vec<_> = medien_for_pid("13021").map(|m| m.code.as_str()).collect();
assert_eq!(wetter, ["SOL", "WID"]);
assert_eq!(medien_for_pid("13002").count(), 0);
}
#[test]
fn placeholders_become_digits() {
assert_eq!(concrete("7-b:9.98.0"), "7-0:9.98.0");
assert_eq!(concrete("7-b:99.45.e1"), "7-0:99.45.01");
}
}