Skip to content

Commit

Permalink
feat: stream API
Browse files Browse the repository at this point in the history
  • Loading branch information
JakkuSakura committed May 22, 2024
1 parent 76ad9ca commit e7f0075
Show file tree
Hide file tree
Showing 5 changed files with 88 additions and 34 deletions.
24 changes: 24 additions & 0 deletions src/field.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
use crate::column::IntoColumn;
use crate::Value;

pub trait WorkTableField {
#[allow(private_bounds)]
type Type: IntoColumn + Into<Value>;
const INDEX: usize;
const NAME: &'static str;
const PRIMARY: bool = false;
}
#[macro_export]
macro_rules! field {
(
$index: expr, $f: ident: $ty: ty, $name: expr $(, primary = $indexed: expr)?
) => {
pub struct $f;
impl $crate::WorkTableField for $f {
type Type = $ty;
const INDEX: usize = $index;
const NAME: &'static str = $name;
$(const PRIMARY: bool = $indexed;)? // optional
}
};
}
2 changes: 2 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
///! worktable
mod column;
mod field;
mod row;
mod ty;
mod value;
mod worktable;
pub use column::*;
pub use field::*;
pub use row::*;
pub use value::*;
pub use worktable::*;
35 changes: 34 additions & 1 deletion src/row.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use crate::column::ColumnId;
use crate::value::{Value, ValueRef, ValueRefMut};
use crate::worktable::{WorkTable, WorkTableField};
use crate::worktable::WorkTable;
use crate::WorkTableField;

#[derive(Clone)]
pub struct RowView<'a> {
Expand Down Expand Up @@ -126,3 +127,35 @@ impl<'a> RowViewMut<'a> {
.collect()
}
}

#[must_use = "RowInsertion::finish() must be called to insert to the table"]
pub struct RowInsertion<'a> {
pub(crate) values: Vec<Value>,
pub(crate) table: &'a mut WorkTable,
}
impl RowInsertion<'_> {
pub fn set<F>(mut self, _field: F, value: F::Type) -> Self
where
F: WorkTableField,
{
self.values[F::INDEX] = value.into();
self
}
pub fn finish(self) {
let len = self.table.len();
self.table
.column_values
.iter_mut()
.zip(self.values.into_iter())
.for_each(|(x, y)| {
if matches!(y, Value::Null) {
panic!("Cannot insert null value. check if your insertion is complete");
}
x.push(y)
});
if let Some(index_values) = &mut self.table.primary_map {
let index_value = self.table.column_values[0].get_value(len).unwrap();
index_values.insert(index_value, len);
}
}
}
2 changes: 2 additions & 0 deletions src/value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use std::hash::{Hash, Hasher};

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub enum Value {
Null,
Int(i64),
String(String),
Float(f64),
Expand Down Expand Up @@ -44,6 +45,7 @@ impl Ord for Value {
impl Hash for Value {
fn hash<H: Hasher>(&self, state: &mut H) {
match self {
Value::Null => 0.hash(state),
Value::Int(x) => x.hash(state),
Value::String(x) => x.hash(state),
Value::Float(x) => x.to_bits().hash(state),
Expand Down
59 changes: 26 additions & 33 deletions src/worktable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use tokio::sync::RwLock;

use crate::column::{Column, ColumnId};
use crate::value::Value;
use crate::{IntoColumn, RowView, RowViewMut};
use crate::{IntoColumn, RowInsertion, RowView, RowViewMut, WorkTableField};

pub struct WorkTable {
pub(crate) column_names: Vec<String>,
Expand Down Expand Up @@ -65,7 +65,7 @@ impl WorkTable {
self.set_primary();
}
}
pub fn add_row<const N: usize>(&mut self, row: [Value; N]) {
pub fn push<const N: usize>(&mut self, row: [Value; N]) {
assert_eq!(self.column_values.len(), N);
if let Some(primary_map) = &mut self.primary_map {
let index = primary_map.len();
Expand All @@ -76,6 +76,13 @@ impl WorkTable {
}
}

pub fn insert(&mut self) -> RowInsertion {
RowInsertion {
values: vec![Value::Null; self.column_values.len()],
table: self,
}
}

pub fn len(&self) -> usize {
if self.column_values.is_empty() {
return 0;
Expand Down Expand Up @@ -241,31 +248,10 @@ impl WorkTable {

pub type SyncWorkTable = Arc<RwLock<WorkTable>>;

pub trait WorkTableField {
#[allow(private_bounds)]
type Type: IntoColumn;
const INDEX: usize;
const NAME: &'static str;
const PRIMARY: bool = false;
}
#[macro_export]
macro_rules! field {
(
$index: expr, $f: ident: $ty: ty, $name: expr $(, primary = $indexed: expr)?
) => {
pub struct $f;
impl $crate::worktable::WorkTableField for $f {
type Type = $ty;
const INDEX: usize = $index;
const NAME: &'static str = $name;
$(const PRIMARY: bool = $indexed;)? // optional
}
};
}

#[cfg(test)]
mod tests {
use super::*;
use crate::field;

field!(0, PrimaryA: i64, "ia", primary = true);
field!(0, A: i64, "a");
Expand All @@ -277,9 +263,16 @@ mod tests {
table.add_field(A);
table.add_field(B);
table.add_field(C);
table.add_row([1.into(), "a".into(), 1.0.into()]);
table.add_row([2.into(), "b".into(), 2.0.into()]);
table.add_row([3.into(), "c".into(), 3.0.into()]);

// stream API
table
.insert()
.set(A, 1)
.set(B, "a".to_string())
.set(C, 1.0)
.finish();
table.push([2.into(), "b".into(), 2.0.into()]);
table.push([3.into(), "c".into(), 3.0.into()]);
assert_eq!(table.shape(), (3, 3));
assert_eq!(table.index(0).index(A), &1);
assert_eq!(table.index(0).index(B), "a");
Expand Down Expand Up @@ -316,9 +309,9 @@ mod tests {
table.add_field(A);
table.add_field(B);
table.add_field(C);
table.add_row([1.into(), "a".into(), 1.0.into()]);
table.add_row([2.into(), "b".into(), 2.0.into()]);
table.add_row([3.into(), "c".into(), 3.0.into()]);
table.push([1.into(), "a".into(), 1.0.into()]);
table.push([2.into(), "b".into(), 2.0.into()]);
table.push([3.into(), "c".into(), 3.0.into()]);
*table.index_mut(1).index_mut(A) = 4;
table.index_mut(1).index_mut(B).push_str("b");
*table.index_mut(1).index_mut(C) = 4.0;
Expand All @@ -340,9 +333,9 @@ mod tests {
table.add_field(PrimaryA);
table.add_field(B);
table.add_field(C);
table.add_row([1.into(), "a".into(), 1.0.into()]);
table.add_row([2.into(), "b".into(), 2.0.into()]);
table.add_row([3.into(), "c".into(), 3.0.into()]);
table.push([1.into(), "a".into(), 1.0.into()]);
table.push([2.into(), "b".into(), 2.0.into()]);
table.push([3.into(), "c".into(), 3.0.into()]);
assert_eq!(table.shape(), (3, 3));
assert_eq!(table.get_by_primary(&1.into()).unwrap().index(A), &1);
assert_eq!(table.get_by_primary(&1.into()).unwrap().index(B), "a");
Expand Down

0 comments on commit e7f0075

Please sign in to comment.