use std::sync::{Arc, RwLock};
use crate::error::Result;
use crate::plugin::ComponentRegistry;
use crate::App;
#[derive(Clone)]
pub struct LazyComponent<T: Clone + Send + Sync + 'static> {
component: Arc<RwLock<Option<T>>>,
}
impl<T: Clone + Send + Sync + 'static> Default for LazyComponent<T> {
fn default() -> Self {
Self::new()
}
}
impl<T: Clone + Send + Sync + 'static> LazyComponent<T> {
pub fn new() -> Self {
Self {
component: Arc::new(RwLock::new(None)),
}
}
pub fn get(&self) -> Result<T> {
{
let guard = self.component.read().unwrap();
if let Some(component) = guard.as_ref() {
return Ok(component.clone());
}
}
let mut guard = self.component.write().unwrap();
if let Some(component) = guard.as_ref() {
return Ok(component.clone());
}
let component = App::global().try_get_component::<T>()?;
*guard = Some(component.clone());
Ok(component)
}
pub fn get_if_initialized(&self) -> Option<T> {
self.component.read().unwrap().clone()
}
}
impl<T: Clone + Send + Sync + 'static> std::ops::Deref for LazyComponent<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
panic!("LazyComponent cannot be dereferenced directly. Use .get() method instead.")
}
}
impl<T: Clone + Send + Sync + 'static> std::fmt::Debug for LazyComponent<T> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("LazyComponent")
.field("initialized", &self.component.read().unwrap().is_some())
.finish()
}
}