From c4ce04d700a98d23baf00048d8823665da9e994c Mon Sep 17 00:00:00 2001
From: niku <nvdpoel01@gmail.com>
Date: Sun, 13 Aug 2023 13:14:53 +0200
Subject: [PATCH] Implement table cursor

---
 src/cursor.rs    | 40 ++++++++++++++++++++++++++++++++++++++++
 src/lib.rs       |  1 +
 src/statement.rs | 20 +++++++++++---------
 3 files changed, 52 insertions(+), 9 deletions(-)
 create mode 100644 src/cursor.rs

diff --git a/src/cursor.rs b/src/cursor.rs
new file mode 100644
index 0000000..8098a6b
--- /dev/null
+++ b/src/cursor.rs
@@ -0,0 +1,40 @@
+use crate::table::Table;
+
+pub type Position = (usize, usize);
+
+pub struct Cursor<'a> {
+    pub table: &'a mut Table,
+    pub row_num: usize,
+    pub end_of_table: bool,
+}
+
+impl<'a> Cursor<'a> {
+    pub fn at_table_start(table: &'a mut Table) -> Self {
+        let end_of_table = table.row_count == 0;
+        Self {
+            table,
+            row_num: 0,
+            end_of_table,
+        }
+    }
+
+    pub fn at_table_end(table: &'a mut Table) -> Self {
+        let row_count = table.row_count;
+        Self {
+            table,
+            row_num: row_count,
+            end_of_table: true,
+        }
+    }
+
+    pub fn position(&self) -> Position {
+        self.table.row_slot(self.row_num)
+    }
+
+    pub fn advance(&mut self) {
+        self.row_num += 1;
+        if self.row_num >= self.table.row_count {
+            self.end_of_table = true;
+        }
+    }
+}
diff --git a/src/lib.rs b/src/lib.rs
index ae2874a..67ad978 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,3 +1,4 @@
+pub mod cursor;
 pub mod layout;
 pub mod pager;
 pub mod row;
diff --git a/src/statement.rs b/src/statement.rs
index 2e10c78..bb70136 100644
--- a/src/statement.rs
+++ b/src/statement.rs
@@ -1,4 +1,5 @@
 use crate::{
+    cursor::Cursor,
     layout::{ROW_SIZE, TABLE_MAX_ROWS},
     row::{Row, RowBytes},
     table::Table,
@@ -6,8 +7,6 @@ use crate::{
 use anyhow::Result;
 use thiserror::Error;
 
-type FilteredRows = Vec<Row>;
-
 #[derive(Debug)]
 pub enum StatementType {
     Insert(Box<Row>),
@@ -73,22 +72,25 @@ pub fn execute_insert(row: Row, table: &mut Table) -> Result<()> {
         return Err(ExecutionError::TableFull.into());
     }
 
+    let cursor = Cursor::at_table_end(table);
     let bytes: RowBytes = row.into();
-    let (page_num, offset) = table.row_slot(table.row_count);
+
+    let (page_num, offset) = cursor.position();
     let page = table.pager.page(page_num)?;
-    // let page = table.pager.pages[page_num].as_mut().unwrap();
     page[offset..offset + ROW_SIZE].copy_from_slice(&bytes);
     table.row_count += 1;
     Ok(())
 }
 
-pub fn execute_select(table: &mut Table) -> Result<FilteredRows> {
-    let mut rows: FilteredRows = vec![];
-    for i in 0..table.row_count {
-        let (page_num, offset) = table.row_slot(i);
-        let page = table.pager.page(page_num)?;
+pub fn execute_select(table: &mut Table) -> Result<Vec<Row>> {
+    let mut rows: Vec<Row> = vec![];
+    let mut cursor = Cursor::at_table_start(table);
+    while !cursor.end_of_table {
+        let (page_num, offset) = cursor.position();
+        let page = cursor.table.pager.page(page_num)?;
         let row: RowBytes = page[offset..offset + ROW_SIZE].try_into()?;
         rows.push(row.into());
+        cursor.advance();
     }
 
     Ok(rows)