use std::cell::OnceCell;
pub struct LazySchema<T> {
cell: OnceCell<T>,
factory: fn() -> T,
}
impl<T> LazySchema<T> {
pub const fn new(factory: fn() -> T) -> Self {
Self {
cell: OnceCell::new(),
factory,
}
}
pub fn get(&self) -> &T {
self.cell.get_or_init(self.factory)
}
}
impl<T> Default for LazySchema<T>
where
T: Default,
{
fn default() -> Self {
Self {
cell: OnceCell::new(),
factory: T::default,
}
}
}
pub fn lazy_schema<T>(factory: fn() -> T) -> LazySchema<T> {
LazySchema::new(factory)
}
#[cfg(test)]
mod tests {
use super::*;
use std::sync::atomic::{AtomicUsize, Ordering};
#[test]
fn test_lazy_schema() {
static CALL_COUNT: AtomicUsize = AtomicUsize::new(0);
fn factory() -> usize {
CALL_COUNT.fetch_add(1, Ordering::SeqCst);
42
}
let schema = lazy_schema(factory);
assert_eq!(schema.get(), &42);
assert_eq!(CALL_COUNT.load(Ordering::SeqCst), 1);
assert_eq!(schema.get(), &42);
assert_eq!(CALL_COUNT.load(Ordering::SeqCst), 1);
}
}