mathtex_engine/
primitive.rs1use alloc::collections::BTreeMap;
2use alloc::string::{String, ToString};
3
4use crate::profile::{PrimitiveKind, PrimitiveOpcode, PrimitiveSpec};
5
6#[derive(Clone, Debug, Default, PartialEq, Eq)]
8pub struct PrimitiveRegistry {
9 entries: BTreeMap<String, PrimitiveEntry>,
10}
11
12impl PrimitiveRegistry {
13 pub fn from_specs(specs: &[PrimitiveSpec]) -> Result<Self, PrimitiveRegistryError> {
15 let mut registry = Self::default();
16 for spec in specs {
17 registry.insert(spec)?;
18 }
19 Ok(registry)
20 }
21
22 pub fn insert(&mut self, spec: &PrimitiveSpec) -> Result<(), PrimitiveRegistryError> {
24 let entry = PrimitiveEntry {
25 name: spec.name.to_string(),
26 opcode: spec.opcode,
27 kind: spec.kind,
28 };
29
30 if self.entries.contains_key(&entry.name) {
31 return Err(PrimitiveRegistryError::DuplicateName { name: entry.name });
32 }
33
34 self.entries.insert(entry.name.clone(), entry);
35 Ok(())
36 }
37
38 #[must_use]
40 pub fn get(&self, name: &str) -> Option<&PrimitiveEntry> {
41 self.entries.get(name)
42 }
43
44 #[must_use]
46 pub fn len(&self) -> usize {
47 self.entries.len()
48 }
49
50 #[must_use]
52 pub fn is_empty(&self) -> bool {
53 self.entries.is_empty()
54 }
55}
56
57#[derive(Clone, Debug, PartialEq, Eq)]
59pub struct PrimitiveEntry {
60 pub name: String,
62 pub opcode: PrimitiveOpcode,
64 pub kind: PrimitiveKind,
66}
67
68#[derive(Clone, Debug, PartialEq, Eq)]
70#[non_exhaustive]
71pub enum PrimitiveRegistryError {
72 DuplicateName {
74 name: String,
76 },
77}
78
79#[cfg(test)]
80mod tests {
81 use alloc::borrow::Cow;
82
83 use super::*;
84
85 #[test]
86 fn registry_rejects_duplicate_names() {
87 let error = PrimitiveRegistry::from_specs(&[
88 PrimitiveSpec {
89 name: Cow::Borrowed("input"),
90 opcode: PrimitiveOpcode(1),
91 kind: PrimitiveKind::Resource,
92 },
93 PrimitiveSpec {
94 name: Cow::Borrowed("input"),
95 opcode: PrimitiveOpcode(2),
96 kind: PrimitiveKind::Resource,
97 },
98 ])
99 .expect_err("duplicate names should fail");
100
101 assert_eq!(
102 error,
103 PrimitiveRegistryError::DuplicateName {
104 name: "input".to_string(),
105 }
106 );
107 }
108}