use crate::archive::{IndexStruct, VariadicRef, VariadicStruct};
use crate::error::ResourceStorageError;
use crate::memory;
use crate::multiarrayview::MultiArrayView;
use crate::storage::ResourceHandle;
use crate::vector::ExternalVector;
use std::borrow::BorrowMut;
use std::fmt;
use std::io;
use std::marker;
pub struct MultiVector<'a, Idx, Ts> {
index: ExternalVector<'a, Idx>,
data: Vec<u8>,
data_handle: ResourceHandle<'a>,
size_flushed: usize,
_phantom: marker::PhantomData<Ts>,
}
impl<'a, Idx, Ts> MultiVector<'a, Idx, Ts>
where
Idx: for<'b> IndexStruct<'b>,
Ts: for<'b> VariadicStruct<'b>,
{
pub fn new(index: ExternalVector<'a, Idx>, data_handle: ResourceHandle<'a>) -> Self {
Self {
index,
data: vec![0; memory::PADDING_SIZE],
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.data.len() - memory::PADDING_SIZE])?;
self.size_flushed += self.data.len() - memory::PADDING_SIZE;
self.data.clear();
self.data.resize(memory::PADDING_SIZE, 0);
Ok(())
}
fn add_to_index(&mut self) -> io::Result<()> {
let idx_mut = self.index.grow()?;
<Idx as IndexStruct>::set_index(
idx_mut,
self.size_flushed + self.data.len() - memory::PADDING_SIZE,
);
Ok(())
}
pub fn close(mut self) -> Result<MultiArrayView<'a, Idx, 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, Idx, Ts: VariadicRef> fmt::Debug for MultiVector<'a, Idx, Ts>
where
Idx: for<'b> IndexStruct<'b>,
Ts: for<'b> VariadicStruct<'b>,
{
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::arrayview::ArrayView;
use crate::memstorage::MemoryResourceStorage;
use crate::multiarrayview::MultiArrayView;
use crate::storage::create_multi_vector;
use crate::storage::ResourceStorage;
define_index!(Idx, RefIdx, RefMutIdx, "some_idx_schema", 4, 32);
define_struct!(
A,
RefA,
RefMutA,
"no_schema",
4,
(x, set_x, u32, 0, 16),
(y, set_y, u32, 16, 16)
);
define_variadic_struct!(Variant, RefVariant, BuilderVariant, Idx, 0 => (A, add_a) );
#[test]
fn test_multi_vector() {
let storage = MemoryResourceStorage::new("/root/resources");
{
let mut mv =
create_multi_vector::<Idx, Variant>(&*storage, "multivector", "Some schema")
.expect("failed to create MultiVector");
{
let mut item = mv.grow().expect("grow failed");
{
let mut a = item.add_a();
a.set_x(1);
a.set_y(2);
assert_eq!(a.x(), 1);
assert_eq!(a.y(), 2);
}
{
let mut 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 {
RefVariant::A(ref a) => {
assert_eq!(a.x(), 1);
assert_eq!(a.y(), 2);
}
}
}
let index_resource = storage
.read_and_check_schema("multivector_index", "index(Some schema)")
.expect("read_and_check_schema failed");
let index: ArrayView<Idx> = ArrayView::new(&index_resource);
let resource = storage
.read_and_check_schema("multivector", "Some schema")
.expect("read_and_check_schema failed");
let mv: MultiArrayView<Idx, Variant> = MultiArrayView::new(index, &resource);
assert_eq!(mv.len(), 1);
let mut item = mv.at(0);
let a = item.next().unwrap();
match a {
RefVariant::A(ref a) => {
assert_eq!(a.x(), 1);
assert_eq!(a.y(), 2);
}
}
let b = item.next().unwrap();
match b {
RefVariant::A(ref a) => {
assert_eq!(a.x(), 3);
assert_eq!(a.y(), 4);
}
}
let x = {
let mv_copy = mv.clone();
mv_copy.at(0).next().unwrap()
};
match x {
RefVariant::A(ref a) => {
assert_eq!(a.x(), 1);
assert_eq!(a.y(), 2);
}
}
let x = {
let mv_copy = mv.clone();
mv_copy.iter().next().unwrap().next().unwrap()
};
match x {
RefVariant::A(ref a) => {
assert_eq!(a.x(), 1);
assert_eq!(a.y(), 2);
}
}
}
}