use crate::{ExternalReferenceType, VecExternRef}; use alloc::boxed::Box; #[cfg(feature = "mock_data")] use alloc::rc::Rc; use alloc::vec::Vec; use core::marker::PhantomData; #[cfg(not(feature = "mock_data"))] struct ImmutableListInner { extern_ref: VecExternRef, resource_type: PhantomData, values: spin::RwLock>>>, } #[derive(Clone)] #[cfg(not(feature = "mock_data"))] pub struct ImmutableList where T: Clone, T: ExternalReferenceType, { inner: *const ImmutableListInner, } #[cfg(not(feature = "mock_data"))] impl ImmutableList where T: Clone, T: ExternalReferenceType, { fn new(extern_ref: VecExternRef) -> Self { let mut values = Vec::new(); values.resize(extern_ref.len() as usize, None); let inner = Box::new(ImmutableListInner { extern_ref, resource_type: Default::default(), values: spin::RwLock::new(values), }); let inner_ptr = Box::into_raw(inner); ImmutableList { inner: inner_ptr as *const ImmutableListInner, } } pub(crate) fn from_ref(extern_ref: VecExternRef) -> Self { unsafe { if let None = CACHE { CACHE = Some(hashbrown::HashMap::new()); } let existing = CACHE .as_ref() .unwrap() .get(&extern_ref.get_internal_index()); if let Some(v) = existing { let inner = *v as *const ImmutableListInner; ImmutableList { inner } } else { let v = Self::new(extern_ref); CACHE .as_mut() .unwrap() .insert(extern_ref.get_internal_index(), v.inner as *const u8); v } } } pub fn get(&self, index: u32) -> Option { unsafe { let inner = self.inner.as_ref().unwrap(); { let rg = inner.values.read(); let v = rg.get(index as usize).unwrap(); if let Some(v) = v { return v.clone(); } } let r = inner.extern_ref.at(index); let value = r.get_value(); let mut wg = inner.values.write(); wg[index as usize] = Some(value); wg[index as usize].as_ref().unwrap().clone() } } } #[cfg(feature = "mock_data")] pub struct ImmutableListInner { values: Vec, } #[cfg(feature = "mock_data")] #[derive(Clone)] pub struct ImmutableList { inner: Rc>, } #[cfg(feature = "mock_data")] impl ImmutableList where T: Clone, { pub fn mock(values: Vec) -> Self { Self { inner: Rc::new(ImmutableListInner { values }), } } pub fn get(&self, index: u32) -> Option { self.inner.values.get(index as usize).cloned() } } static mut CACHE: Option> = None;