use alloc::collections::BTreeMap;
use alloc::string::{String, ToString};
use crate::profile::{PrimitiveKind, PrimitiveOpcode, PrimitiveSpec};
#[derive(Clone, Debug, Default, PartialEq, Eq)]
pub struct PrimitiveRegistry {
entries: BTreeMap<String, PrimitiveEntry>,
}
impl PrimitiveRegistry {
pub fn from_specs(specs: &[PrimitiveSpec]) -> Result<Self, PrimitiveRegistryError> {
let mut registry = Self::default();
for spec in specs {
registry.insert(spec)?;
}
Ok(registry)
}
pub fn insert(&mut self, spec: &PrimitiveSpec) -> Result<(), PrimitiveRegistryError> {
let entry = PrimitiveEntry {
name: spec.name.to_string(),
opcode: spec.opcode,
kind: spec.kind,
};
if self.entries.contains_key(&entry.name) {
return Err(PrimitiveRegistryError::DuplicateName { name: entry.name });
}
self.entries.insert(entry.name.clone(), entry);
Ok(())
}
#[must_use]
pub fn get(&self, name: &str) -> Option<&PrimitiveEntry> {
self.entries.get(name)
}
#[must_use]
pub fn len(&self) -> usize {
self.entries.len()
}
#[must_use]
pub fn is_empty(&self) -> bool {
self.entries.is_empty()
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct PrimitiveEntry {
pub name: String,
pub opcode: PrimitiveOpcode,
pub kind: PrimitiveKind,
}
#[derive(Clone, Debug, PartialEq, Eq)]
#[non_exhaustive]
pub enum PrimitiveRegistryError {
DuplicateName {
name: String,
},
}
#[cfg(test)]
mod tests {
use alloc::borrow::Cow;
use super::*;
#[test]
fn registry_rejects_duplicate_names() {
let error = PrimitiveRegistry::from_specs(&[
PrimitiveSpec {
name: Cow::Borrowed("input"),
opcode: PrimitiveOpcode(1),
kind: PrimitiveKind::Resource,
},
PrimitiveSpec {
name: Cow::Borrowed("input"),
opcode: PrimitiveOpcode(2),
kind: PrimitiveKind::Resource,
},
])
.expect_err("duplicate names should fail");
assert_eq!(
error,
PrimitiveRegistryError::DuplicateName {
name: "input".to_string(),
}
);
}
}