use std::sync::OnceLock;
use crate::hton::Handlerton;
#[non_exhaustive]
pub(crate) struct HandlertonRegistry {
handlerton: OnceLock<Box<dyn Handlerton>>,
}
impl HandlertonRegistry {
pub(crate) const fn new() -> Self {
Self {
handlerton: OnceLock::new(),
}
}
pub(crate) fn register(&self, handlerton: Box<dyn Handlerton>) {
match self.handlerton.set(handlerton) {
Ok(()) => {}
Err(_) => {
tracing::debug!("handlerton already registered; ignoring duplicate registration");
}
}
}
pub(crate) fn get(&self) -> Option<&dyn Handlerton> {
self.handlerton.get().map(|h| &**h)
}
}
impl Default for HandlertonRegistry {
fn default() -> Self {
Self::new()
}
}
impl core::fmt::Debug for HandlertonRegistry {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("HandlertonRegistry")
.field("registered", &self.handlerton.get().is_some())
.finish()
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::hton::{HtonCapabilities, HtonFlags};
struct MockHandlerton;
impl Handlerton for MockHandlerton {
fn capabilities(&self) -> HtonCapabilities {
HtonCapabilities::TRANSACTIONS
}
fn flags(&self) -> HtonFlags {
HtonFlags::NONE
}
}
#[test]
fn get_is_none_before_register() {
let registry = HandlertonRegistry::new();
assert!(registry.get().is_none());
}
#[test]
fn register_then_get_yields_handlerton() {
let registry = HandlertonRegistry::new();
registry.register(Box::new(MockHandlerton));
let h = registry
.get()
.expect("registered handlerton is retrievable");
assert!(h.capabilities().contains(HtonCapabilities::TRANSACTIONS));
assert_eq!(h.flags(), HtonFlags::NONE);
}
#[test]
fn duplicate_register_keeps_first() {
let registry = HandlertonRegistry::new();
registry.register(Box::new(MockHandlerton));
registry.register(Box::new(MockHandlerton));
assert!(registry.get().is_some());
}
}