115 lines
3.0 KiB
Rust
Executable File
115 lines
3.0 KiB
Rust
Executable File
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<T: Clone> {
|
|
extern_ref: VecExternRef<T>,
|
|
resource_type: PhantomData<T>,
|
|
values: spin::RwLock<Vec<Option<Option<T>>>>,
|
|
}
|
|
|
|
#[derive(Clone)]
|
|
#[cfg(not(feature = "mock_data"))]
|
|
pub struct ImmutableList<T>
|
|
where
|
|
T: Clone,
|
|
T: ExternalReferenceType,
|
|
{
|
|
inner: *const ImmutableListInner<T>,
|
|
}
|
|
|
|
#[cfg(not(feature = "mock_data"))]
|
|
impl<T> ImmutableList<T>
|
|
where
|
|
T: Clone,
|
|
T: ExternalReferenceType,
|
|
{
|
|
fn new(extern_ref: VecExternRef<T>) -> 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<T>,
|
|
}
|
|
}
|
|
|
|
pub(crate) fn from_ref(extern_ref: VecExternRef<T>) -> 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<T>;
|
|
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<T> {
|
|
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<T> {
|
|
values: Vec<T>,
|
|
}
|
|
|
|
#[cfg(feature = "mock_data")]
|
|
#[derive(Clone)]
|
|
pub struct ImmutableList<T> {
|
|
inner: Rc<ImmutableListInner<T>>,
|
|
}
|
|
|
|
#[cfg(feature = "mock_data")]
|
|
impl<T> ImmutableList<T>
|
|
where
|
|
T: Clone,
|
|
{
|
|
pub fn mock(values: Vec<T>) -> Self {
|
|
Self {
|
|
inner: Rc::new(ImmutableListInner { values }),
|
|
}
|
|
}
|
|
|
|
pub fn get(&self, index: u32) -> Option<T> {
|
|
self.inner.values.get(index as usize).cloned()
|
|
}
|
|
}
|
|
|
|
static mut CACHE: Option<hashbrown::HashMap<u32, *const u8>> = None;
|