use memtable_core::Table;
use memtable_macros::Table;
use std::{convert::TryFrom, path::Path};
#[derive(Debug, PartialEq, Eq, Table)]
#[table(mode(fixed(rows = "123")))]
struct MyRow {
field1: bool,
field2: usize,
}
#[derive(Table)]
#[table(mode(fixed(rows = "123")))]
struct GenericRow<A: Default, B> {
field1: A,
field2: B,
}
#[derive(Table)]
#[table(mode(fixed(rows = "123")))]
struct LifetimeRow<'a> {
field1: &'a str,
field2: &'a Path,
}
#[test]
fn should_support_retrieving_column_names() {
assert_eq!(MyRowTable::COLUMN_NAMES, &["field1", "field2"]);
assert_eq!(
GenericRowTable::<u8, u8>::COLUMN_NAMES,
&["field1", "field2"]
);
assert_eq!(LifetimeRowTable::COLUMN_NAMES, &["field1", "field2"]);
}
#[test]
fn should_support_retrieving_columns_by_name() {
let mut table = MyRowTable::new();
table.push_row((false, 123));
table.push_row((true, 999));
let column: Vec<bool> = table
.column_by_name("field1")
.unwrap()
.filter_map(|x| x.as_field1().copied())
.collect();
assert_eq!(column, vec![false, true]);
let column: Vec<usize> = table
.column_by_name("field2")
.unwrap()
.filter_map(|x| x.as_field2().copied())
.collect();
assert_eq!(column, vec![123, 999]);
assert!(table.column_by_name("???").is_none());
}
#[test]
fn should_support_converting_into_columns_by_name() {
let mut table = MyRowTable::new();
table.push_row((false, 123));
table.push_row((true, 999));
let column: Vec<bool> = table
.into_column_by_name("field1")
.unwrap()
.filter_map(MyRowTableData::into_field1)
.collect();
assert_eq!(column, vec![false, true]);
let mut table = MyRowTable::new();
table.push_row((false, 123));
table.push_row((true, 999));
let column: Vec<usize> = table
.into_column_by_name("field2")
.unwrap()
.filter_map(MyRowTableData::into_field2)
.collect();
assert_eq!(column, vec![123, 999]);
let mut table = MyRowTable::new();
table.push_row((false, 123));
table.push_row((true, 999));
assert!(table.into_column_by_name("???").is_none());
}
#[test]
fn should_support_retrieving_typed_rows() {
let mut table = MyRowTable::new();
table.push_row((false, 123));
table.push_row((true, 999));
let mut rows = table.rows();
assert_eq!(rows.next(), Some((&false, &123)));
assert_eq!(rows.next(), Some((&true, &999)));
assert!(rows.next().is_none());
}
#[test]
fn should_support_retrieving_a_single_typed_row() {
let mut table = MyRowTable::new();
table.push_row((false, 123));
table.push_row((true, 999));
assert_eq!(table.row(0), Some((&false, &123)));
assert_eq!(table.row(1), Some((&true, &999)));
assert!(table.row(2).is_none());
}
#[test]
fn should_support_inserting_typed_rows() {
let mut table = MyRowTable::new();
table.push_row((false, 123));
table.push_row((true, 999));
table.insert_row(0, (true, 456));
{
let mut rows = table.rows();
assert_eq!(rows.next(), Some((&true, &456)));
assert_eq!(rows.next(), Some((&false, &123)));
assert_eq!(rows.next(), Some((&true, &999)));
assert!(rows.next().is_none());
}
table.insert_row(table.row_cnt(), (false, 0));
{
let mut rows = table.rows();
assert_eq!(rows.next(), Some((&true, &456)));
assert_eq!(rows.next(), Some((&false, &123)));
assert_eq!(rows.next(), Some((&true, &999)));
assert_eq!(rows.next(), Some((&false, &0)));
assert!(rows.next().is_none());
}
table.insert_row(table.row_cnt() / 2, (true, 789));
{
let mut rows = table.rows();
assert_eq!(rows.next(), Some((&true, &456)));
assert_eq!(rows.next(), Some((&false, &123)));
assert_eq!(rows.next(), Some((&true, &789)));
assert_eq!(rows.next(), Some((&true, &999)));
assert_eq!(rows.next(), Some((&false, &0)));
assert!(rows.next().is_none());
}
}
#[test]
fn should_support_pushing_typed_rows_to_end() {
let mut table = MyRowTable::new();
table.push_row((false, 123));
table.push_row((true, 999));
let mut rows = table.rows();
assert_eq!(rows.next(), Some((&false, &123)));
assert_eq!(rows.next(), Some((&true, &999)));
assert!(rows.next().is_none());
}
#[test]
fn should_support_removing_typed_rows() {
let mut table = MyRowTable::new();
assert!(table.remove_row(0).is_none());
assert!(table.rows().next().is_none());
table.push_row((false, 1));
table.push_row((false, 2));
table.push_row((false, 3));
table.push_row((false, 4));
table.push_row((false, 5));
assert_eq!(
table.remove_row(0),
Some(MyRow {
field1: false,
field2: 1
})
);
{
let mut rows = table.rows();
assert_eq!(rows.next(), Some((&false, &2)));
assert_eq!(rows.next(), Some((&false, &3)));
assert_eq!(rows.next(), Some((&false, &4)));
assert_eq!(rows.next(), Some((&false, &5)));
assert!(rows.next().is_none());
}
assert_eq!(
table.remove_row(table.row_cnt() - 1),
Some(MyRow {
field1: false,
field2: 5
})
);
{
let mut rows = table.rows();
assert_eq!(rows.next(), Some((&false, &2)));
assert_eq!(rows.next(), Some((&false, &3)));
assert_eq!(rows.next(), Some((&false, &4)));
assert!(rows.next().is_none());
}
assert_eq!(
table.remove_row(table.row_cnt() / 2),
Some(MyRow {
field1: false,
field2: 3
})
);
{
let mut rows = table.rows();
assert_eq!(rows.next(), Some((&false, &2)));
assert_eq!(rows.next(), Some((&false, &4)));
assert!(rows.next().is_none());
}
}
#[test]
fn should_support_removing_typed_rows_from_end() {
let mut table = MyRowTable::new();
assert!(table.pop_row().is_none());
assert!(table.rows().next().is_none());
table.push_row((false, 1));
table.push_row((false, 2));
table.push_row((false, 3));
table.push_row((false, 4));
table.push_row((false, 5));
assert_eq!(
table.pop_row(),
Some(MyRow {
field1: false,
field2: 5
})
);
{
let mut rows = table.rows();
assert_eq!(rows.next(), Some((&false, &1)));
assert_eq!(rows.next(), Some((&false, &2)));
assert_eq!(rows.next(), Some((&false, &3)));
assert_eq!(rows.next(), Some((&false, &4)));
assert!(rows.next().is_none());
}
}
#[test]
fn should_support_retrieving_typed_columns() {
let mut table = MyRowTable::new();
table.push_row((false, 123));
table.push_row((true, 999));
let mut column = table.field1_column();
assert_eq!(column.next(), Some(&false));
assert_eq!(column.next(), Some(&true));
assert!(column.next().is_none());
let mut column = table.field2_column();
assert_eq!(column.next(), Some(&123));
assert_eq!(column.next(), Some(&999));
assert!(column.next().is_none());
}
#[test]
fn should_support_converting_into_typed_columns() {
let mut table = MyRowTable::new();
table.push_row((false, 123));
table.push_row((true, 999));
let mut column = table.into_field1_column();
assert_eq!(column.next(), Some(false));
assert_eq!(column.next(), Some(true));
assert!(column.next().is_none());
let mut table = MyRowTable::new();
table.push_row((false, 123));
table.push_row((true, 999));
let mut column = table.into_field2_column();
assert_eq!(column.next(), Some(123));
assert_eq!(column.next(), Some(999));
assert!(column.next().is_none());
}
#[test]
fn should_support_replacing_individual_cells() {
let mut table = MyRowTable::new();
table.push_row((false, 123));
table.push_row((true, 999));
assert_eq!(table.replace_field1(0, true), Some(false));
{
let mut column = table.field1_column();
assert_eq!(column.next(), Some(&true));
assert_eq!(column.next(), Some(&true));
assert!(column.next().is_none());
}
assert_eq!(table.replace_field2(1, 0usize), Some(999));
{
let mut column = table.field2_column();
assert_eq!(column.next(), Some(&123));
assert_eq!(column.next(), Some(&0));
assert!(column.next().is_none());
}
assert_eq!(table.replace_field2(2, 999usize), None);
{
assert_eq!(table.row_cnt(), 2);
assert_eq!(table.col_cnt(), 2);
let mut column = table.field2_column();
assert_eq!(column.next(), Some(&123));
assert_eq!(column.next(), Some(&0));
assert!(column.next().is_none());
}
}
#[test]
fn should_support_retrieving_individual_cells() {
let mut table = MyRowTable::new();
table.push_row((false, 123));
table.push_row((true, 999));
assert_eq!(table.field1(0), Some(&false));
assert_eq!(table.field1(1), Some(&true));
assert_eq!(table.field1(2), None);
assert_eq!(table.field2(0), Some(&123));
assert_eq!(table.field2(1), Some(&999));
assert_eq!(table.field2(2), None);
}
#[test]
fn should_support_mutating_individual_cells() {
let mut table = MyRowTable::new();
table.push_row((false, 123));
table.push_row((true, 999));
*table.mut_field1(0).unwrap() = true;
*table.mut_field1(1).unwrap() = false;
assert!(table.mut_field1(2).is_none());
*table.mut_field2(0).unwrap() = 999;
*table.mut_field2(1).unwrap() = 123;
assert!(table.mut_field2(2).is_none());
assert_eq!(table.field1(0), Some(&true));
assert_eq!(table.field1(1), Some(&false));
assert_eq!(table.field1(2), None);
assert_eq!(table.field2(0), Some(&999));
assert_eq!(table.field2(1), Some(&123));
assert_eq!(table.field2(2), None);
}
#[test]
fn should_support_trying_to_convert_from_untyped_table() {
{
let mut table = memtable::FixedTable::new();
table.push_row(vec![
MyRowTableData::Field1(false),
MyRowTableData::Field2(123),
]);
table.push_row(vec![
MyRowTableData::Field1(true),
MyRowTableData::Field2(999),
]);
let table = MyRowTable::try_from(table).unwrap();
let mut rows = table.rows();
assert_eq!(rows.next(), Some((&false, &123)));
assert_eq!(rows.next(), Some((&true, &999)));
assert!(rows.next().is_none());
}
{
let mut table = memtable::FixedTable::new();
table.push_row(vec![
MyRowTableData::Field2(123),
MyRowTableData::Field1(false),
]);
table.push_row(vec![
MyRowTableData::Field2(999),
MyRowTableData::Field1(true),
]);
assert!(MyRowTable::try_from(table).is_err());
}
{
let mut table = memtable::FixedTable::new();
table.push_row(vec![
MyRowTableData::Field1(false),
MyRowTableData::Field2(123),
]);
table.push_row(vec![MyRowTableData::Field1(true)]);
assert!(MyRowTable::try_from(table).is_err());
}
}