use std::convert::Infallible;
use super::legacy::LegacyRow;
use super::modern::ModernRow;
use super::private::{ColumnSerialize, LabelMap, Table};
use super::util::CompatIter;
use crate::{
BdatResult, Cell, CellAccessor, ColumnMap, Label, LegacyColumn, LegacyFlag, LegacyTable,
ModernColumn, ModernTable, RowId, RowRef, Utf, ValueType,
};
#[derive(Debug, Clone, PartialEq)]
pub enum CompatTable<'b> {
Modern(ModernTable<'b>),
Legacy(LegacyTable<'b>),
}
pub enum CompatRow<'buf> {
Modern(ModernRow<'buf>),
Legacy(LegacyRow<'buf>),
}
#[derive(Clone, Copy)]
pub enum CompatRef<'t, 'buf> {
Modern(&'t ModernRow<'buf>),
Legacy(&'t LegacyRow<'buf>),
}
#[derive(Clone, PartialEq, Eq)]
pub enum CompatColumn<'buf> {
Modern(ModernColumn<'buf>),
Legacy(LegacyColumn<'buf>),
}
#[derive(Clone, Copy)]
pub enum CompatColumnRef<'t, 'buf> {
Modern(&'t ModernColumn<'buf>),
Legacy(&'t LegacyColumn<'buf>),
}
#[derive(Clone, Copy)]
pub enum CompatColumnMap<'t, 'buf> {
Modern(&'t ColumnMap<ModernColumn<'buf>, Label<'buf>>),
Legacy(&'t ColumnMap<LegacyColumn<'buf>, Utf<'buf>>),
}
pub type CompatRowRef<'t, 'buf> = RowRef<CompatRef<'t, 'buf>, CompatColumnMap<'t, 'buf>>;
macro_rules! versioned {
($var:expr, $name:ident) => {
match $var {
Self::Modern(m) => &m.$name,
Self::Legacy(l) => &l.$name,
}
};
($var:expr, $name:ident($($par:expr ) *)) => {
match $var {
Self::Modern(m) => m . $name ( $($par, )* ),
Self::Legacy(l) => l . $name ( $($par, )* ),
}
};
}
impl<'b> CompatTable<'b> {
pub fn as_modern(&self) -> &ModernTable<'b> {
match self {
Self::Modern(m) => m,
_ => panic!("not modern"),
}
}
pub fn as_legacy(&self) -> &LegacyTable<'b> {
match self {
Self::Legacy(l) => l,
_ => panic!("not legacy"),
}
}
pub fn as_modern_mut(&mut self) -> &mut ModernTable<'b> {
match self {
Self::Modern(m) => m,
_ => panic!("not modern"),
}
}
pub fn as_legacy_mut(&mut self) -> &mut LegacyTable<'b> {
match self {
Self::Legacy(l) => l,
_ => panic!("not legacy"),
}
}
pub fn into_modern(self) -> ModernTable<'b> {
match self {
Self::Modern(m) => m,
_ => panic!("not modern"),
}
}
pub fn into_legacy(self) -> LegacyTable<'b> {
match self {
Self::Legacy(l) => l,
_ => panic!("not legacy"),
}
}
pub fn is_modern(&self) -> bool {
matches!(self, Self::Modern(_))
}
pub fn is_legacy(&self) -> bool {
matches!(self, Self::Legacy(_))
}
pub fn try_into_modern(self) -> BdatResult<ModernTable<'b>> {
match self {
Self::Modern(m) => Ok(m),
Self::Legacy(l) => Ok(l.try_into()?),
}
}
pub fn try_into_legacy(self) -> BdatResult<LegacyTable<'b>> {
match self {
Self::Modern(m) => Ok(m.try_into()?),
Self::Legacy(l) => Ok(l),
}
}
pub fn name(&self) -> Label {
match self {
Self::Modern(m) => m.name().as_ref(),
Self::Legacy(l) => l.name().into(),
}
}
pub(crate) fn name_cloned(&self) -> Label<'b> {
match self {
Self::Modern(m) => m.name.clone(),
Self::Legacy(l) => l.name.clone().into(),
}
}
pub fn set_name(&mut self, name: Label<'b>) {
match self {
Self::Modern(m) => m.set_name(name),
Self::Legacy(l) => {
l.set_name(name.try_into().expect("hashed labels are not supported"))
}
}
}
pub fn base_id(&self) -> RowId {
match self {
Self::Modern(m) => m.base_id(),
Self::Legacy(l) => l.base_id() as u32,
}
}
pub fn row(&self, id: RowId) -> CompatRowRef<'_, 'b> {
match self {
Self::Modern(m) => m
.row(id)
.map(CompatRef::Modern, CompatColumnMap::Modern(&m.columns)),
Self::Legacy(l) => l
.row(id.try_into().expect("invalid id for legacy row"))
.map(CompatRef::Legacy, CompatColumnMap::Legacy(&l.columns)),
}
}
pub fn get_row(&self, id: RowId) -> Option<CompatRowRef<'_, 'b>> {
match self {
Self::Modern(m) => m
.get_row(id)
.map(|r| r.map(CompatRef::Modern, CompatColumnMap::Modern(&m.columns))),
Self::Legacy(l) => id
.try_into()
.ok()
.and_then(|id| l.get_row(id))
.map(|r| r.map(CompatRef::Legacy, CompatColumnMap::Legacy(&l.columns))),
}
}
pub fn rows(&self) -> impl Iterator<Item = CompatRowRef<'_, 'b>> {
match self {
Self::Modern(m) => CompatIter::Modern(
m.rows()
.map(|r| r.map(CompatRef::Modern, CompatColumnMap::Modern(&m.columns))),
),
Self::Legacy(l) => CompatIter::Legacy(
l.rows()
.map(|r| r.map(CompatRef::Legacy, CompatColumnMap::Legacy(&l.columns))),
),
}
}
pub fn into_rows(self) -> impl Iterator<Item = CompatRow<'b>> {
match self {
Self::Modern(m) => CompatIter::Modern(m.into_rows().map(CompatRow::Modern)),
Self::Legacy(l) => CompatIter::Legacy(l.into_rows().map(CompatRow::Legacy)),
}
}
pub fn into_rows_id(self) -> impl Iterator<Item = (u32, CompatRow<'b>)> {
match self {
Self::Modern(m) => {
CompatIter::Modern(m.into_rows_id().map(|(id, r)| (id, CompatRow::Modern(r))))
}
Self::Legacy(l) => CompatIter::Legacy(
l.into_rows_id()
.map(|(id, r)| (id as u32, CompatRow::Legacy(r))),
),
}
}
pub fn columns(&self) -> impl Iterator<Item = CompatColumnRef<'_, 'b>> {
match self {
Self::Modern(m) => CompatIter::Modern(m.columns().map(CompatColumnRef::Modern)),
Self::Legacy(l) => CompatIter::Legacy(l.columns().map(CompatColumnRef::Legacy)),
}
}
pub fn into_columns(self) -> impl Iterator<Item = CompatColumn<'b>> {
match self {
Self::Modern(m) => CompatIter::Modern(m.into_columns().map(CompatColumn::Modern)),
Self::Legacy(l) => CompatIter::Legacy(l.into_columns().map(CompatColumn::Legacy)),
}
}
pub fn row_count(&self) -> usize {
versioned!(&self, row_count())
}
pub fn column_count(&self) -> usize {
versioned!(&self, column_count())
}
}
impl<'b> CompatColumn<'b> {
pub fn as_ref(&self) -> CompatColumnRef<'_, 'b> {
match self {
CompatColumn::Modern(m) => CompatColumnRef::Modern(m),
CompatColumn::Legacy(l) => CompatColumnRef::Legacy(l),
}
}
}
impl<'buf> CompatColumn<'buf> {
pub fn label(&self) -> Label {
match self {
Self::Modern(m) => m.label().as_ref(),
Self::Legacy(l) => l.label().into(),
}
}
pub fn value_type(&self) -> ValueType {
self.as_ref().value_type()
}
pub fn flags(&self) -> &[LegacyFlag<'buf>] {
match self {
Self::Modern(_) => &[],
Self::Legacy(l) => l.flags(),
}
}
pub fn count(&self) -> usize {
self.as_ref().count()
}
pub fn data_size(&self) -> usize {
self.as_ref().data_size()
}
}
impl<'t, 'buf> CompatColumnRef<'t, 'buf> {
pub fn label(&self) -> Label<'t> {
match self {
Self::Modern(m) => m.label().as_ref(),
Self::Legacy(l) => l.label().into(),
}
}
pub fn value_type(&self) -> ValueType {
match self {
Self::Modern(m) => m.value_type(),
Self::Legacy(l) => l.value_type(),
}
}
pub fn flags(&self) -> &[LegacyFlag<'buf>] {
match self {
Self::Modern(_) => &[],
Self::Legacy(l) => l.flags(),
}
}
pub fn count(&self) -> usize {
match self {
Self::Modern(_) => 1,
Self::Legacy(l) => l.count(),
}
}
pub fn data_size(&self) -> usize {
match self {
Self::Modern(m) => m.data_size(),
Self::Legacy(l) => l.data_size(),
}
}
}
impl<'b> CompatRow<'b> {
pub fn cells(&self) -> impl Iterator<Item = Cell<'b>> + '_ {
match self {
CompatRow::Modern(m) => {
CompatIter::Modern(m.values.iter().map(|v| Cell::Single(v.clone())))
}
CompatRow::Legacy(l) => CompatIter::Legacy(l.cells.iter().cloned()),
}
}
pub fn into_cells(self) -> impl Iterator<Item = Cell<'b>> {
match self {
CompatRow::Modern(m) => CompatIter::Modern(m.into_values().map(Cell::Single)),
CompatRow::Legacy(l) => CompatIter::Legacy(l.into_cells()),
}
}
}
impl<'t, 'b> CompatRef<'t, 'b> {
pub fn cells(&self) -> impl Iterator<Item = Cell<'b>> + '_ {
match self {
CompatRef::Modern(m) => {
CompatIter::Modern(m.values.iter().map(|v| Cell::Single(v.clone())))
}
CompatRef::Legacy(l) => CompatIter::Legacy(l.cells.iter().cloned()),
}
}
}
impl<'buf> From<LegacyColumn<'buf>> for CompatColumn<'buf> {
fn from(value: LegacyColumn<'buf>) -> Self {
Self::Legacy(value)
}
}
impl<'buf> From<ModernColumn<'buf>> for CompatColumn<'buf> {
fn from(value: ModernColumn<'buf>) -> Self {
Self::Modern(value)
}
}
impl<'t, 'buf> From<&'t LegacyColumn<'buf>> for CompatColumnRef<'t, 'buf> {
fn from(value: &'t LegacyColumn<'buf>) -> Self {
Self::Legacy(value)
}
}
impl<'t, 'buf> From<&'t ModernColumn<'buf>> for CompatColumnRef<'t, 'buf> {
fn from(value: &'t ModernColumn<'buf>) -> Self {
Self::Modern(value)
}
}
impl<'buf> Table<'buf> for CompatTable<'buf> {
type Id = RowId;
type Name = Label<'buf>;
type Row = CompatRow<'buf>;
type BuilderRow = Infallible; type Column = CompatColumn<'buf>;
type BuilderColumn = CompatColumn<'buf>;
}
impl<'t, 'b> CellAccessor for CompatRef<'t, 'b> {
type Target = Cell<'b>;
fn access(self, pos: usize) -> Option<Self::Target> {
match self {
CompatRef::Modern(m) => m.values.get(pos).map(|v| Cell::Single(v.clone())),
CompatRef::Legacy(l) => l.cells.get(pos).cloned(),
}
}
}
impl<'t, 'b> LabelMap for CompatColumnMap<'t, 'b> {
type Name = Label<'b>;
fn position(&self, label: &Self::Name) -> Option<usize> {
match self {
CompatColumnMap::Modern(m) => m.position(label),
CompatColumnMap::Legacy(l) => {
let Label::String(s) = label else { return None };
l.position(s)
}
}
}
}
impl<'buf> ColumnSerialize for CompatColumn<'buf> {
fn ser_value_type(&self) -> crate::ValueType {
self.value_type()
}
fn ser_flags(&self) -> &[crate::LegacyFlag] {
match self {
Self::Modern(m) => m.ser_flags(),
Self::Legacy(l) => l.ser_flags(),
}
}
}
impl<'a, 'buf> ColumnSerialize for CompatColumnRef<'a, 'buf> {
fn ser_value_type(&self) -> crate::ValueType {
self.value_type()
}
fn ser_flags(&self) -> &[crate::LegacyFlag] {
match self {
Self::Modern(m) => m.ser_flags(),
Self::Legacy(l) => l.ser_flags(),
}
}
}