diff --git a/src/main.rs b/src/main.rs index 0ef1c22..bdf1e71 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,17 +4,95 @@ mod file_storage; mod node; mod record; mod storage; + use crate::{btree::BPlusTree, file_storage::FileStorage}; +use std::{ + env, + io::{self, Write}, +}; fn main() { - let storage = FileStorage::new("data.db"); + let filename = match env::args().nth(1) { + Some(f) => f, + None => { + eprintln!("Usage: btree "); + std::process::exit(1); + } + }; + + let storage = FileStorage::new(&filename); let mut tree = BPlusTree::open(storage); - // Insert some key-value pairs - tree.insert([1, 0, 0, 0, 0, 0, 0]); - tree.insert([2, 1, 0, 1, 0, 1, 0]); - - // Find a key - let value = tree.find(2); - println!("Found value: {:?}", value); + repl(&mut tree); +} + +fn repl(tree: &mut BPlusTree) { + loop { + print!("> "); + io::stdout().flush().unwrap(); + + let mut input = String::new(); + if io::stdin().read_line(&mut input).is_err() { + println!("Failed to read input"); + continue; + } + + let input = input.trim(); + if input.is_empty() { + continue; + } + + if input == "exit" || input == "quit" { + break; + } + + if input == "help" { + continue; + } + + match handle_command(tree, input) { + Ok(()) => {} + Err(err) => println!("Error: {}", err), + } + } +} + +fn handle_command(tree: &mut BPlusTree, input: &str) -> Result<(), String> { + let parts: Vec<&str> = input.split_whitespace().collect(); + + match parts.as_slice() { + ["insert", rest @ ..] => handle_insert(tree, rest), + ["find", key] => handle_find(tree, key), + _ => Err("Unknown command".into()), + } +} + +fn handle_insert(tree: &mut BPlusTree, args: &[&str]) -> Result<(), String> { + if args.len() != 7 { + return Err("Usage: insert k x a_1 a_2 a_3 a_4 a_5".into()); + } + + let mut record = [0i32; 7]; + for (i, arg) in args.iter().enumerate() { + record[i] = arg + .parse::() + .map_err(|_| format!("Invalid integer: {}", arg))?; + } + + tree.insert(record); + println!("Inserted: {:?}", record); + Ok(()) +} + +fn handle_find(tree: &mut BPlusTree, key: &str) -> Result<(), String> { + let key = key + .parse::() + .map_err(|_| format!("Invalid key: {}", key))?; + + match tree.find(key) { + Some(record) => println!("Found: {:?}", record), + None => println!("Key not found"), + } + + Ok(()) } diff --git a/src/storage.rs b/src/storage.rs index 8ba1961..a0b64bd 100644 --- a/src/storage.rs +++ b/src/storage.rs @@ -5,31 +5,3 @@ pub trait Storage { fn write_node(&mut self, loc: usize, node: &Node); fn total_nodes(&self) -> usize; } - -// Example in-memory storage implementation for testing -pub struct InMemoryStorage { - pub nodes: Vec>, -} - -impl InMemoryStorage { - pub fn new() -> Self { - Self { nodes: Vec::new() } - } -} - -impl Storage for InMemoryStorage { - fn read_node(&mut self, loc: usize) -> Option { - self.nodes.get(loc)?.clone() - } - - fn write_node(&mut self, loc: usize, node: &Node) { - if loc >= self.nodes.len() { - self.nodes.resize(loc + 1, None); - } - self.nodes[loc] = Some(node.clone()); - } - - fn total_nodes(&self) -> usize { - self.nodes.len() - } -}