use std::collections::HashSet;
use std::sync::{Arc, OnceLock};
use crate::OpDefRegistration;
use vyre_foundation::ir::OpId;
#[must_use]
pub fn dialect_and_language_supported_ops() -> &'static HashSet<OpId> {
static OPS: OnceLock<HashSet<OpId>> = OnceLock::new();
OPS.get_or_init(|| {
let language_ops = super::validation::default_supported_ops();
let registrations = inventory::iter::<OpDefRegistration>.into_iter();
let inventory_bound = registrations
.size_hint()
.1
.unwrap_or_else(|| registrations.size_hint().0);
let reserve = language_ops
.len()
.checked_add(inventory_bound)
.unwrap_or_else(|| {
panic!(
"Vyre dialect support set size overflowed while reserving {} language op(s) plus {inventory_bound} dialect op(s). Fix: split support-set construction.",
language_ops.len()
)
});
let mut set = HashSet::new();
set.try_reserve(reserve).unwrap_or_else(|error| {
panic!(
"Vyre dialect support set could not reserve {reserve} op slot(s): {error}. Fix: reduce linked dialect inventory or split support-set construction."
)
});
set.extend(language_ops.iter().cloned());
for reg in registrations {
let def = (reg.op)();
set.insert(Arc::<str>::from(def.id));
}
set
})
}
#[must_use]
pub fn dialect_only_supported_ops() -> &'static HashSet<OpId> {
static OPS: OnceLock<HashSet<OpId>> = OnceLock::new();
OPS.get_or_init(|| {
let registrations = inventory::iter::<OpDefRegistration>.into_iter();
let reserve = registrations
.size_hint()
.1
.unwrap_or_else(|| registrations.size_hint().0);
let mut set = HashSet::new();
set.try_reserve(reserve).unwrap_or_else(|error| {
panic!(
"Vyre dialect support set could not reserve {reserve} dialect-only op slot(s): {error}. Fix: reduce linked dialect inventory or split support-set construction."
)
});
for reg in registrations {
let def = (reg.op)();
set.insert(Arc::<str>::from(def.id));
}
set
})
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn dialect_set_contains_io_ops() {
let ops = dialect_only_supported_ops();
for op in [
"io.dma_from_nvme",
"io.write_back_to_nvme",
"mem.zerocopy_map",
"mem.unmap",
] {
assert!(
ops.iter().any(|o| o.as_ref() == op),
"dialect set missing {op}; saw {:?}",
ops.iter().map(|o| o.as_ref()).collect::<Vec<_>>().len()
);
}
}
#[test]
fn union_includes_both_sources() {
let union = dialect_and_language_supported_ops();
assert!(union.iter().any(|o| o.as_ref() == "vyre.node.store"));
assert!(union.iter().any(|o| o.as_ref() == "io.dma_from_nvme"));
}
#[test]
fn union_size_exceeds_language_alone() {
let lang = super::super::validation::default_supported_ops().len();
let union = dialect_and_language_supported_ops().len();
assert!(union > lang);
}
}