use std::collections::HashMap;
use crate::datatype::DataType;
use crate::error::{Result, SparkplugError};
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub enum MetricKey {
Name(String),
Alias(u64),
}
#[derive(Clone, Debug, Default)]
pub struct AliasRegistry {
name_to_alias: HashMap<String, u64>,
alias_to_name: HashMap<u64, String>,
dt_by_name: HashMap<String, DataType>,
dt_by_alias: HashMap<u64, DataType>,
}
impl AliasRegistry {
#[must_use]
pub fn new() -> Self {
Self::default()
}
pub fn bind(&mut self, name: &str, alias: Option<u64>, datatype: DataType) {
self.dt_by_name.insert(name.to_owned(), datatype);
if let Some(alias) = alias {
self.name_to_alias.insert(name.to_owned(), alias);
self.alias_to_name.insert(alias, name.to_owned());
self.dt_by_alias.insert(alias, datatype);
}
}
pub fn try_bind(&mut self, name: &str, alias: Option<u64>, datatype: DataType) -> Result<()> {
if let Some(alias) = alias
&& let Some(existing) = self.alias_to_name.get(&alias)
&& existing != name
{
return Err(SparkplugError::InvalidId(format!(
"alias {alias} already bound to {existing:?}, cannot rebind to {name:?}"
)));
}
self.bind(name, alias, datatype);
Ok(())
}
#[must_use]
pub fn datatype_for_name(&self, name: &str) -> Option<DataType> {
self.dt_by_name.get(name).copied()
}
#[must_use]
pub fn datatype_for_alias(&self, alias: u64) -> Option<DataType> {
self.dt_by_alias.get(&alias).copied()
}
#[must_use]
pub fn datatype_for(&self, key: &MetricKey) -> Option<DataType> {
match key {
MetricKey::Name(n) => self.datatype_for_name(n),
MetricKey::Alias(a) => self.datatype_for_alias(*a),
}
}
#[must_use]
pub fn name_for_alias(&self, alias: u64) -> Option<&str> {
self.alias_to_name.get(&alias).map(String::as_str)
}
#[must_use]
pub fn alias_for_name(&self, name: &str) -> Option<u64> {
self.name_to_alias.get(name).copied()
}
#[must_use]
pub fn alias_exists(&self, alias: u64) -> bool {
self.alias_to_name.contains_key(&alias)
}
pub fn clear(&mut self) {
self.name_to_alias.clear();
self.alias_to_name.clear();
self.dt_by_name.clear();
self.dt_by_alias.clear();
}
}