use crate::strided_array_file::{ArrayProxy, Error, StridedArrayFile, TypedArray};
use std::{fmt::Debug, sync::Arc};
pub(super) trait Resource: Debug + Send + Sync {
fn is_parent_of(&self, proxy: ArrayProxy<'_>) -> Result<bool, Error>;
}
pub(super) trait View<'a>: Debug + Send + Sync {
fn proxy(&self) -> Result<ArrayProxy<'a>, Error>;
fn resource(&self) -> Arc<dyn Resource + 'a>;
}
pub(super) trait FileResource<'a> {
fn create_view(&self, array_index: usize) -> Arc<FileView<'a>>;
}
impl<'a> FileResource<'a> for Arc<StridedArrayFile<'a>> {
fn create_view(&self, array_index: usize) -> Arc<FileView<'a>> {
Arc::new(FileView {
array_index,
file: self.clone(),
})
}
}
#[derive(Debug)]
pub(super) struct FileView<'a> {
array_index: usize,
file: Arc<StridedArrayFile<'a>>,
}
pub(super) fn create_new_array<'a>(array: TypedArray) -> Result<Arc<dyn View<'a> + 'a>, Error> {
let proxy = unsafe { std::mem::transmute::<ArrayProxy<'_>, ArrayProxy<'a>>(array.proxy()?) };
let resource = Arc::new(array);
Ok(Arc::new(ResourceView { proxy, resource }))
}
pub(super) fn create_view<'a>(
proxy: ArrayProxy<'a>,
resource: Arc<dyn Resource + 'a>,
) -> Result<Arc<dyn View<'a> + 'a>, Error> {
if !resource.is_parent_of(proxy.clone())? {
Err("Inconsistent caching data".into())
} else {
Ok(Arc::new(ResourceView { proxy, resource }))
}
}
impl Resource for TypedArray {
fn is_parent_of(&self, proxy: ArrayProxy<'_>) -> Result<bool, Error> {
self.proxy()?.contains(proxy)
}
}
impl Resource for StridedArrayFile<'_> {
fn is_parent_of(&self, proxy: ArrayProxy<'_>) -> Result<bool, Error> {
if !self.is_open() {
return Ok(false);
}
for i in 0..self.count()? {
if self.try_get(i)?.contains(proxy.clone())? {
return Ok(true);
}
}
Ok(false)
}
}
impl<'a> View<'a> for FileView<'a> {
fn proxy(&self) -> Result<ArrayProxy<'a>, Error> {
self.file.try_get(self.array_index)
}
fn resource(&self) -> Arc<dyn Resource + 'a> {
self.file.clone()
}
}
#[derive(Debug)]
struct ResourceView<'a> {
proxy: ArrayProxy<'a>,
resource: Arc<dyn Resource + 'a>,
}
impl<'a> View<'a> for ResourceView<'a> {
fn proxy(&self) -> Result<ArrayProxy<'a>, Error> {
Ok(self.proxy.clone())
}
fn resource(&self) -> Arc<dyn Resource + 'a> {
self.resource.clone()
}
}
#[test]
fn is_parent_of() {
use ndarray::{Array1, SliceInfoElem};
use std::path::Path;
let array = {
let array = Array1::from_vec(vec![1u8, 2, 3]);
TypedArray::from_array(array.into_dyn()).unwrap()
};
let slice_info = vec![SliceInfoElem::Slice {
start: 1,
end: None,
step: 1,
}];
let slice = array.slice(slice_info.clone()).unwrap();
assert_ne!(
array.proxy().unwrap().try_as::<u8>().unwrap().as_ptr(),
slice.try_as::<u8>().unwrap().as_ptr(),
);
assert!(array.is_parent_of(slice).unwrap());
assert!(array.is_parent_of(array.proxy().unwrap()).unwrap());
let other_array = {
let array = Array1::from_vec(vec![1u8, 2, 3]);
TypedArray::from_array(array.into_dyn()).unwrap()
};
assert!(!array.is_parent_of(other_array.proxy().unwrap()).unwrap());
let file_path = Path::new("is_parent_of.star");
StridedArrayFile::write(
file_path,
&[array.proxy().unwrap(), other_array.proxy().unwrap()],
)
.unwrap();
let file = StridedArrayFile::new(file_path.to_path_buf());
let slice = file.get(1).slice(slice_info).unwrap();
assert!(file.is_parent_of(slice).unwrap());
assert!(file.is_parent_of(file.get(1)).unwrap());
assert!(!file.is_parent_of(array.proxy().unwrap()).unwrap());
}