use std::ops::Index;
use distances::{number::UInt, Number};
use crate::{Dataset, Instance, VecDataset};
#[allow(clippy::module_name_repetitions)]
pub trait SquishyDataset<I: Instance, U: Number>: Dataset<I, U> {
fn encode_instance(&self, reference: &I, target: &I) -> Box<[u8]>;
fn decode_instance(&self, reference: &I, encoding: &[u8]) -> I;
fn bytes_per_unit_distance(&self) -> u64;
fn save(&self, path: &std::path::Path) -> Result<(), String>;
fn load(
path: &std::path::Path,
metric: fn(&String, &String) -> U,
is_expensive: bool,
encoder: fn(&String, &String) -> Box<[u8]>,
decoder: fn(&String, &[u8]) -> String,
) -> Result<Self, String>
where
Self: Sized;
}
#[derive(Debug)]
#[allow(clippy::module_name_repetitions)]
pub struct GenomicDataset<U: UInt> {
base_data: VecDataset<String, U, String>,
bytes_per_unit_distance: u64,
encoder: fn(&String, &String) -> Box<[u8]>,
decoder: fn(&String, &[u8]) -> String,
}
impl<U: UInt> SquishyDataset<String, U> for GenomicDataset<U> {
fn encode_instance(&self, reference: &String, target: &String) -> Box<[u8]> {
(self.encoder)(reference, target)
}
fn decode_instance(&self, reference: &String, encoding: &[u8]) -> String {
(self.decoder)(reference, encoding)
}
fn bytes_per_unit_distance(&self) -> u64 {
self.bytes_per_unit_distance
}
#[allow(unused_variables)]
fn save(&self, path: &std::path::Path) -> Result<(), String> {
todo!()
}
#[allow(unused_variables)]
fn load(
path: &std::path::Path,
metric: fn(&String, &String) -> U,
is_expensive: bool,
encoder: fn(&String, &String) -> Box<[u8]>,
decoder: fn(&String, &[u8]) -> String,
) -> Result<Self, String>
where
Self: Sized,
{
todo!()
}
}
impl<U: UInt> Dataset<String, U> for GenomicDataset<U> {
fn type_name() -> String {
format!("GenomicDataset<{}>", U::type_name())
}
fn name(&self) -> &str {
self.base_data.name()
}
fn cardinality(&self) -> usize {
self.base_data.cardinality()
}
fn is_metric_expensive(&self) -> bool {
self.base_data.is_metric_expensive()
}
fn metric(&self) -> fn(&String, &String) -> U {
self.base_data.metric()
}
fn set_permuted_indices(&mut self, indices: Option<&[usize]>) {
self.base_data.set_permuted_indices(indices);
}
fn swap(&mut self, left: usize, right: usize) -> Result<(), String> {
self.base_data.swap(left, right)
}
fn permuted_indices(&self) -> Option<&[usize]> {
self.base_data.permuted_indices()
}
fn make_shards(self, max_cardinality: usize) -> Vec<Self>
where
Self: Sized,
{
let base_shards = self.base_data.make_shards(max_cardinality);
base_shards
.into_iter()
.map(|base_data| Self {
base_data,
bytes_per_unit_distance: self.bytes_per_unit_distance,
encoder: self.encoder,
decoder: self.decoder,
})
.collect()
}
#[allow(unused_variables)]
fn save(&self, path: &std::path::Path) -> Result<(), String> {
Err("Use `SqishyDataset::save` instead".to_string())
}
#[allow(unused_variables)]
fn load(path: &std::path::Path, metric: fn(&String, &String) -> U, is_expensive: bool) -> Result<Self, String>
where
Self: Sized,
{
Err("Use `SqishyDataset::load` instead".to_string())
}
}
impl<U: UInt> Index<usize> for GenomicDataset<U> {
type Output = String;
fn index(&self, index: usize) -> &Self::Output {
&self.base_data[index]
}
}