zapdb/
lib.rs

1use std::collections::HashMap;
2use std::hash::{Hash, Hasher};
3use std::time::Instant;
4use std::fs::File;
5use std::io::{self, Write, Read};
6use serde::{Serialize, Deserialize};
7
8
9#[derive(Clone, Debug, Serialize, Deserialize)]
10pub struct Column {
11    pub name: String,
12    pub data_type: DataType,
13}
14
15impl Column {
16    pub fn new(name: String, data_type: DataType) -> Self {
17        Column { name, data_type }
18    }
19}
20
21#[derive(Clone, Debug, Serialize, Deserialize)]
22pub enum DataType {
23    Integer,
24    String,
25    Float,
26    Boolean,
27}
28
29#[derive(Clone, Debug, Serialize, Deserialize)]
30pub struct Table {
31    name: String,
32    columns: Vec<Column>,
33    data: Vec<HashMap<String, Value>>,
34}
35
36
37#[derive(Clone, Debug, Serialize, Deserialize)]
38pub enum Value {
39    Integer(i64),
40    String(String),
41    Float(f64),
42    Boolean(bool),
43    Null,
44}
45
46pub struct Database {
47    tables: HashMap<String, Table>,
48}
49
50impl Database {
51    pub fn new() -> Self {
52        Database {
53            tables: HashMap::new(),
54        }
55    }
56    pub async fn save(&self, path: &str) -> io::Result<()> {
57        let start = Instant::now();
58        let encoded: Vec<u8> = bincode::serialize(&self.tables).unwrap();
59        let mut file = File::create(path)?;
60        file.write_all(&encoded)?;
61
62        println!("Database saved in {:?}", start.elapsed());
63        Ok(())
64    }
65
66    pub async fn load(&mut self, path: &str) -> io::Result<()> {
67        let start = Instant::now();
68        let mut file = File::open(path)?;
69        let mut buffer = Vec::new();
70        file.read_to_end(&mut buffer)?;
71    
72        let tables: HashMap<String, Table> = bincode::deserialize(&buffer)
73            .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
74        
75        self.tables = tables;
76        println!("Database loaded in {:?}", start.elapsed());
77        Ok(())
78    }
79    pub fn create_table(&mut self, name: String, columns: Vec<Column>) -> Result<(), String> {
80        let start = Instant::now();
81        if self.tables.contains_key(&name) {
82            return Err(format!("Table {} already exists", name));
83        }
84        self.tables.insert(
85            name.clone(),
86            Table {
87                name,
88                columns,
89                data: Vec::new(),
90            },
91        );
92
93        println!("Table created in {:?}", start.elapsed());
94        Ok(())
95    }
96
97    pub fn insert(&mut self, table_name: &str, row: HashMap<String, Value>) -> Result<(), String> {
98        let start = Instant::now();
99        let table = self
100            .tables
101            .get_mut(table_name)
102            .ok_or_else(|| format!("Table {} not found", table_name))?;
103
104        for col in &table.columns {
105            if !row.contains_key(&col.name) {
106                return Err(format!("Missing column: {}", col.name));
107            }
108        }
109
110        table.data.push(row);
111
112        println!("Row inserted in {:?}", start.elapsed());
113        Ok(())
114    }
115
116    pub fn select(
117        &self,
118        table_name: &str,
119        conditions: Option<fn(&HashMap<String, Value>) -> bool>,
120    ) -> Result<Vec<&HashMap<String, Value>>, String> {
121        let start = Instant::now();
122        let table = self
123            .tables
124            .get(table_name)
125            .ok_or_else(|| format!("Table {} not found", table_name))?;
126
127        let results = match conditions {
128            Some(filter) => table.data.iter().filter(|row| filter(row)).collect(),
129            None => table.data.iter().collect(),
130        };
131
132        println!("Rows selected in {:?}", start.elapsed());
133        Ok(results)
134    }
135
136    pub fn update(
137        &mut self,
138        table_name: &str,
139        conditions: fn(&HashMap<String, Value>) -> bool,
140        update_fn: fn(&mut HashMap<String, Value>),
141    ) -> Result<usize, String> {
142        let table = self
143            .tables
144            .get_mut(table_name)
145            .ok_or_else(|| format!("Table {} not found", table_name))?;
146
147        let mut updated_count = 0;
148        for row in &mut table.data {
149            if conditions(row) {
150                update_fn(row);
151                updated_count += 1;
152            }
153        }
154
155        Ok(updated_count)
156    }
157
158    pub fn delete(
159        &mut self,
160        table_name: &str,
161        conditions: fn(&HashMap<String, Value>) -> bool,
162    ) -> Result<usize, String> {
163        let table = self
164            .tables
165            .get_mut(table_name)
166            .ok_or_else(|| format!("Table {} not found", table_name))?;
167
168        let initial_len = table.data.len();
169        table.data.retain(|row| !conditions(row));
170
171        Ok(initial_len - table.data.len())
172    }
173}