use std::fmt::Debug;
use std::marker::PhantomData;
use std::rc::Rc;
use error::*;
use field::Value;
use frame::Framed;
pub trait DataIndex: Debug {
type DType;
fn get_datum(&self, idx: usize) -> Result<Value<&Self::DType>>;
fn len(&self) -> usize;
fn is_empty(&self) -> bool {
self.len() == 0
}
fn iter(&self) -> DataIterator<Self::DType>
where
Self: Sized,
{
DataIterator::new(self)
}
fn permute(self, permutation: &[usize]) -> Framed<Self::DType, Self>
where
Self: Sized,
{
Framed::new(Rc::new(permutation.to_vec().into()), self)
}
fn to_vec(&self) -> Vec<Self::DType>
where
Self: Sized,
Self::DType: Clone,
{
self.iter()
.filter_map(|value| match value {
Value::Exists(value) => Some(value.clone()),
Value::Na => None,
})
.collect()
}
fn to_value_vec(&self) -> Vec<Value<Self::DType>>
where
Self: Sized,
Self::DType: Clone,
{
self.iter().map(|value| value.cloned()).collect()
}
}
pub trait DataIndexMut: DataIndex {
fn push(&mut self, value: Value<Self::DType>);
fn take_datum(&mut self, idx: usize) -> Result<Value<Self::DType>>
where
Self::DType: Default;
fn drain(&mut self) -> DrainIterator<Self::DType>
where
Self: Sized,
{
DrainIterator::new(self)
}
}
pub struct DataIterator<'a, T>
where
T: 'a,
{
data: &'a dyn DataIndex<DType = T>,
cur_idx: usize,
phantom: PhantomData<T>,
}
impl<'a, T> DataIterator<'a, T>
where
T: 'a,
{
pub fn new(data: &'a dyn DataIndex<DType = T>) -> DataIterator<'a, T> {
DataIterator {
data,
cur_idx: 0,
phantom: PhantomData,
}
}
pub fn map_existing<B, F>(self, f: F) -> ValueMap<'a, T, Self, F>
where
Self: Iterator<Item = Value<&'a T>>,
F: FnMut(&'a T) -> B,
{
ValueMap {
iter: self,
f,
_t: PhantomData,
}
}
}
impl<'a, T> Iterator for DataIterator<'a, T>
where
T: 'a,
{
type Item = Value<&'a T>;
fn next(&mut self) -> Option<Value<&'a T>> {
if self.cur_idx < self.data.len() {
let out = Some(self.data.get_datum(self.cur_idx).unwrap());
self.cur_idx += 1;
out
} else {
None
}
}
}
#[derive(Clone)]
pub struct ValueMap<'a, T, I, F> {
iter: I,
f: F,
_t: PhantomData<&'a T>,
}
impl<'a, B, T, I, F> Iterator for ValueMap<'a, T, I, F>
where
I: Iterator<Item = Value<&'a T>>,
F: FnMut(&'a T) -> B,
{
type Item = Value<B>;
#[inline]
fn next(&mut self) -> Option<Value<B>> {
self.iter.next().map(|value| value.map(&mut self.f))
}
}
pub struct DrainIterator<'a, T>
where
T: 'a,
{
data: &'a mut dyn DataIndexMut<DType = T>,
cur_idx: usize,
phantom: PhantomData<T>,
}
impl<'a, T> DrainIterator<'a, T>
where
T: 'a,
{
pub fn new(data: &'a mut dyn DataIndexMut<DType = T>) -> DrainIterator<'a, T> {
DrainIterator {
data,
cur_idx: 0,
phantom: PhantomData,
}
}
}
impl<'a, T> Iterator for DrainIterator<'a, T>
where
T: 'a + Default,
{
type Item = Value<T>;
fn next(&mut self) -> Option<Value<T>> {
if self.cur_idx < self.data.len() {
let out = Some(self.data.take_datum(self.cur_idx).unwrap());
self.cur_idx += 1;
out
} else {
None
}
}
}
pub trait NRows {
fn nrows(&self) -> usize;
}
impl<DI> NRows for DI
where
DI: DataIndex,
{
fn nrows(&self) -> usize {
self.len()
}
}
#[cfg(test)]
mod tests {
use super::*;
use field::FieldData;
#[test]
fn convert() {
let field_data = FieldData::from_field_vec(vec![
Value::Exists(2u64),
Value::Exists(5),
Value::Na,
Value::Exists(1),
Value::Exists(8),
]);
let new_field_data = field_data
.iter()
.map_existing(|u| *u as i64)
.collect::<FieldData<i64>>();
assert_eq!(
new_field_data.to_value_vec(),
vec![
Value::Exists(2i64),
Value::Exists(5),
Value::Na,
Value::Exists(1),
Value::Exists(8),
]
);
}
}