use std::{
marker::PhantomData,
};
use crate::{
header::{Header, ProjectFrom, HasCol},
record::{Record, Col, ExternalRecord},
rename_col::RenameCol,
};
pub struct Rename<I,A,B> {
pub(crate) inner: I,
pub(crate) cols: PhantomData<(A,B)>
}
impl<I,A,B> Copy for Rename<I,A,B> where I:Copy {}
impl<I,A,B> Clone for Rename<I,A,B> where I:Clone {
fn clone(&self)->Self {
Rename { inner: self.inner.clone(), cols: PhantomData }
}
}
impl<I,A:Col,B:Col<Inner = A::Inner>> Rename<I,A,B> {
pub fn new(inner: I)->Self
where I: Clone + Record,
I::Cols: RenameCol<A,B>,
<I::Cols as RenameCol<A,B>>::Renamed: Header
{
Self { inner, cols: PhantomData }
}
}
impl<I,A,B> Record for Rename<I,A,B>
where I: Record,
A: Col, B:Col<Inner=A::Inner>,
I::Cols: RenameCol<A,B>,
<I::Cols as RenameCol<A,B>>::Renamed: Header
{
type Cols = <I::Cols as RenameCol<A,B>>::Renamed;
#[inline(always)]
fn col_opt<C:Col>(&self)->Option<&C> {
use std::any::{TypeId, Any};
if TypeId::of::<C>() == TypeId::of::<B>() {
self.inner.col_opt::<A>()
.and_then(|a| (a.rename_ref::<B>() as &dyn Any).downcast_ref())
}
else if Self::Cols::has_col::<C>() {
self.inner.col_opt()
} else {
None
}
}
}
impl<'a, I,A,B> ExternalRecord<'a> for Rename<I,A,B>
where I: ExternalRecord<'a>,
A: Col, B:Col<Inner=A::Inner>,
I::Cols: RenameCol<A,B>,
<I::Cols as RenameCol<A,B>>::Renamed: Header
{
#[inline(always)]
fn ext_col_opt<C:Col>(&self)->Option<&'a C> {
use std::any::{TypeId, Any};
if TypeId::of::<C>() == TypeId::of::<B>() {
self.inner.ext_col_opt::<A>()
.and_then(|a| (a.rename_ref::<B>() as &dyn Any).downcast_ref())
}
else if Self::Cols::has_col::<C>() {
self.inner.ext_col_opt()
} else {
None
}
}
}