use std::sync::Arc;
use std::time::SystemTime;
use crate::error::{Error, Result};
use crate::representation::Representation;
#[derive(Clone, Debug, PartialEq)]
pub struct PackedDocuments {
vectors: Vec<f32>,
lengths: Vec<usize>,
dimension: usize,
}
impl PackedDocuments {
pub fn new(vectors: Vec<f32>, lengths: Vec<usize>, dimension: usize) -> Result<Self> {
if dimension == 0 {
return Err(Error::invalid("packed documents need a positive dimension"));
}
if lengths.contains(&0) {
return Err(Error::invalid("document lengths must be positive"));
}
let tokens = lengths
.iter()
.try_fold(0usize, |total, &length| total.checked_add(length))
.ok_or_else(|| Error::invalid("document lengths overflow usize"))?;
if tokens.checked_mul(dimension) != Some(vectors.len()) {
return Err(Error::invalid(format!(
"document lengths sum to {tokens}, but {} values form {} rows of dimension {dimension}",
vectors.len(),
vectors.len() / dimension
)));
}
Ok(Self {
vectors,
lengths,
dimension,
})
}
pub fn vectors(&self) -> &[f32] {
&self.vectors
}
pub fn lengths(&self) -> &[usize] {
&self.lengths
}
pub fn dimension(&self) -> usize {
self.dimension
}
}
pub trait MultiVectorSource: Send + Sync {
fn corpus(&self) -> &str;
fn representation(&self) -> &Representation;
fn score_semantics(&self) -> &str;
fn view(&self) -> Result<Arc<dyn VectorView>>;
}
pub trait VectorView: Send + Sync {
fn as_of(&self) -> SystemTime;
fn document_lengths(&self, document_ids: &[&str]) -> Result<Vec<Option<usize>>>;
fn fetch(&self, document_ids: &[&str], threads: Option<usize>) -> Result<PackedDocuments>;
}