use crate::{
error::ResourceStorageError,
multiarrayview::MultiArrayView,
storage::ResourceHandle,
structs::{IndexStruct, VariadicRefFactory, VariadicStruct},
vector::ExternalVector,
};
use std::{borrow::BorrowMut, fmt, io, marker};
pub struct MultiVector<'a, Ts>
where
Ts: VariadicRefFactory,
{
index: ExternalVector<'a, Ts::Index>,
data: Vec<u8>,
data_handle: ResourceHandle<'a>,
size_flushed: usize,
_phantom: marker::PhantomData<Ts>,
}
impl<'a, Ts> MultiVector<'a, Ts>
where
Ts: VariadicRefFactory,
{
pub fn new(index: ExternalVector<'a, Ts::Index>, data_handle: ResourceHandle<'a>) -> Self {
Self {
index,
data: Vec::new(),
data_handle,
size_flushed: 0,
_phantom: marker::PhantomData,
}
}
pub fn grow(&mut self) -> io::Result<<Ts as VariadicStruct>::ItemMut> {
if self.data.len() > 1024 * 1024 * 32 {
self.flush()?;
}
self.add_to_index()?;
Ok(<Ts as VariadicStruct>::create_mut(&mut self.data))
}
fn flush(&mut self) -> io::Result<()> {
self.data_handle.borrow_mut().write(&self.data)?;
self.size_flushed += self.data.len();
self.data.clear();
Ok(())
}
fn add_to_index(&mut self) -> io::Result<()> {
let idx_mut = self.index.grow()?;
Ts::Index::set_index(idx_mut, self.size_flushed + self.data.len());
Ok(())
}
pub fn close(mut self) -> Result<MultiArrayView<'a, Ts>, ResourceStorageError> {
let name: String = self.data_handle.name().into();
let into_storage_error = |e| ResourceStorageError::from_io_error(e, name.clone());
self.add_to_index().map_err(into_storage_error)?; self.flush().map_err(into_storage_error)?;
let index_view = self.index.close()?;
let data = self.data_handle.close()?;
Ok(MultiArrayView::new(index_view, data))
}
}
impl<'a, Ts> fmt::Debug for MultiVector<'a, Ts>
where
Ts: VariadicRefFactory,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "MultiVector {{ len: {} }}", self.index.len())
}
}
#[cfg(test)]
#[allow(dead_code)]
mod tests {
use crate::{
memstorage::MemoryResourceStorage,
multiarrayview::MultiArrayView,
storage::{create_multi_vector, ResourceStorage},
test::{Ab, AbRef, _builtin::multivector::IndexType16},
};
#[test]
fn test_multi_vector() {
let storage = MemoryResourceStorage::new("/root/resources");
{
let mut mv = create_multi_vector::<Ab>(&*storage, "multivector", "Some schema")
.expect("failed to create MultiVector");
{
let mut item = mv.grow().expect("grow failed");
{
let a = item.add_a();
a.set_x(1);
a.set_y(2);
assert_eq!(a.x(), 1);
assert_eq!(a.y(), 2);
}
{
let b = item.add_a();
b.set_x(3);
b.set_y(4);
assert_eq!(b.x(), 3);
assert_eq!(b.y(), 4);
}
}
let view = mv.close().expect("close failed");
assert_eq!(view.len(), 1);
let mut item = view.at(0);
let a = item.next().unwrap();
match a {
AbRef::A(ref a) => {
assert_eq!(a.x(), 1);
assert_eq!(a.y(), 2);
}
AbRef::B(_) => panic!("unexpected variant B"),
}
}
let index_resource = storage
.read_and_check_schema("multivector_index", "index(Some schema)")
.expect("read_and_check_schema failed");
use crate::SliceExt;
let index = <&[IndexType16]>::from_bytes(&index_resource).expect("Corrupted data");
let resource = storage
.read_and_check_schema("multivector", "Some schema")
.expect("read_and_check_schema failed");
let mv: MultiArrayView<Ab> = MultiArrayView::new(index, &resource);
assert_eq!(mv.len(), 1);
let mut item = mv.at(0);
let a = item.next().unwrap();
match a {
AbRef::A(ref a) => {
assert_eq!(a.x(), 1);
assert_eq!(a.y(), 2);
}
AbRef::B(_) => panic!("unexpected variant B"),
}
let b = item.next().unwrap();
match b {
AbRef::A(ref a) => {
assert_eq!(a.x(), 3);
assert_eq!(a.y(), 4);
}
AbRef::B(_) => panic!("unexpected variant B"),
}
let x = {
let mv_copy = mv.clone();
mv_copy.at(0).next().unwrap()
};
match x {
AbRef::A(ref a) => {
assert_eq!(a.x(), 1);
assert_eq!(a.y(), 2);
}
AbRef::B(_) => panic!("unexpected variant B"),
}
let x = {
let mv_copy = mv.clone();
mv_copy.iter().next().unwrap().next().unwrap()
};
match x {
AbRef::A(ref a) => {
assert_eq!(a.x(), 1);
assert_eq!(a.y(), 2);
}
AbRef::B(_) => panic!("unexpected variant B"),
}
}
}