aurora_db/
types.rs

1use std::collections::HashMap;
2use std::cmp::Ordering;
3use std::hash::{Hash, Hasher};
4use uuid::Uuid;
5use serde::{Serialize, Deserialize};
6use std::fmt;
7use std::path::{Path, PathBuf};
8
9#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
10pub enum FieldType {
11    String,
12    Int,
13    Uuid,
14    Boolean,
15    Float,
16    Array,
17}
18
19#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
20pub struct FieldDefinition {
21    pub field_type: FieldType,
22    pub unique: bool,
23    pub indexed: bool,
24}
25
26#[derive(Debug, Clone, Serialize, Deserialize)]
27pub struct Collection {
28    pub name: String,
29    pub fields: HashMap<String, FieldDefinition>,
30    pub unique_fields: Vec<String>,
31}
32
33#[derive(Clone, Serialize, Deserialize)]
34pub struct Document {
35    pub id: String,
36    pub data: HashMap<String, Value>,
37}
38
39impl Document {
40    pub fn new() -> Self {
41        Self {
42            id: Uuid::new_v4().to_string(),
43            data: HashMap::new(),
44        }
45    }
46}
47
48impl fmt::Display for Document {
49    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
50        write!(f, "{{ ")?;
51        let mut first = true;
52        for (key, value) in &self.data {
53            if !first {
54                write!(f, ", ")?;
55            }
56            write!(f, "{}: {}", key, value)?;
57            first = false;
58        }
59        write!(f, " }}")
60    }
61}
62
63impl fmt::Debug for Document {
64    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
65        // Use the same formatting as Display
66        fmt::Display::fmt(self, f)
67    }
68}
69
70#[derive(Debug, Clone, Serialize, Deserialize)]
71pub enum Value {
72    Null,
73    String(String),
74    Int(i64),
75    Float(f64),
76    Bool(bool),
77    Array(Vec<Value>),
78    Object(HashMap<String, Value>),
79    Uuid(Uuid),
80}
81
82// Custom implementations for Hash, Eq, and PartialEq
83impl Hash for Value {
84    fn hash<H: Hasher>(&self, state: &mut H) {
85        match self {
86            Value::Null => 0.hash(state),
87            Value::String(s) => s.hash(state),
88            Value::Int(i) => i.hash(state),
89            Value::Float(f) => {
90                // Convert to bits to hash floating point numbers
91                f.to_bits().hash(state)
92            },
93            Value::Bool(b) => b.hash(state),
94            Value::Array(arr) => arr.hash(state),
95            Value::Object(map) => {
96                // Sort keys for consistent hashing
97                let mut keys: Vec<_> = map.keys().collect();
98                keys.sort();
99                for key in keys {
100                    key.hash(state);
101                    map.get(key).unwrap().hash(state);
102                }
103            },
104            Value::Uuid(u) => u.hash(state),
105        }
106    }
107}
108
109impl PartialEq for Value {
110    fn eq(&self, other: &Self) -> bool {
111        match (self, other) {
112            (Value::Null, Value::Null) => true,
113            (Value::String(a), Value::String(b)) => a == b,
114            (Value::Int(a), Value::Int(b)) => a == b,
115            (Value::Float(a), Value::Float(b)) => {
116                if a.is_nan() && b.is_nan() {
117                    true
118                } else {
119                    a == b
120                }
121            },
122            (Value::Bool(a), Value::Bool(b)) => a == b,
123            (Value::Array(a), Value::Array(b)) => a == b,
124            (Value::Object(a), Value::Object(b)) => a == b,
125            (Value::Uuid(a), Value::Uuid(b)) => a == b,
126            _ => false,
127        }
128    }
129}
130
131impl Eq for Value {}
132
133// Implement Display for Value
134impl fmt::Display for Value {
135    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
136        match self {
137            Value::String(s) => write!(f, "{}", s),
138            Value::Int(i) => write!(f, "{}", i),
139            Value::Float(fl) => write!(f, "{}", fl),
140            Value::Bool(b) => write!(f, "{}", b),
141            Value::Array(arr) => {
142                let items: Vec<String> = arr.iter()
143                    .map(|v| v.to_string())
144                    .collect();
145                write!(f, "{}", items.join(", "))
146            },
147            Value::Object(obj) => {
148                let items: Vec<String> = obj.iter()
149                    .map(|(k, v)| format!("{}: {}", k, v))
150                    .collect();
151                write!(f, "{}", items.join(", "))
152            },
153            Value::Uuid(u) => write!(f, "{}", u),
154            Value::Null => write!(f, ""),
155        }
156    }
157}
158
159impl PartialOrd for Value {
160    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
161        match (self, other) {
162            (Value::String(a), Value::String(b)) => Some(a.cmp(b)),
163            (Value::Int(a), Value::Int(b)) => Some(a.cmp(b)),
164            (Value::Float(a), Value::Float(b)) => a.partial_cmp(b),
165            (Value::Bool(a), Value::Bool(b)) => Some(a.cmp(b)),
166            (Value::Array(a), Value::Array(b)) => {
167                // Compare arrays element by element
168                for (x, y) in a.iter().zip(b.iter()) {
169                    match x.partial_cmp(y) {
170                        Some(Ordering::Equal) => continue,
171                        other => return other,
172                    }
173                }
174                // If all elements are equal, compare lengths
175                Some(a.len().cmp(&b.len()))
176            },
177            (Value::Object(a), Value::Object(b)) => {
178                // Compare objects by their sorted keys and values
179                let mut a_keys: Vec<_> = a.keys().collect();
180                let mut b_keys: Vec<_> = b.keys().collect();
181                a_keys.sort();
182                b_keys.sort();
183                
184                // First compare keys
185                match a_keys.partial_cmp(&b_keys) {
186                    Some(Ordering::Equal) => {
187                        // If keys are equal, compare values
188                        for key in a_keys {
189                            match (a.get(key), b.get(key)) {
190                                (Some(a_val), Some(b_val)) => {
191                                    match a_val.partial_cmp(b_val) {
192                                        Some(Ordering::Equal) => continue,
193                                        other => return other,
194                                    }
195                                }
196                                _ => unreachable!(), // Keys are identical, so this can't happen
197                            }
198                        }
199                        Some(Ordering::Equal)
200                    }
201                    other => other,
202                }
203            },
204            (Value::Uuid(a), Value::Uuid(b)) => Some(a.cmp(b)),
205            (Value::Null, Value::Null) => Some(Ordering::Equal),
206            // Different types are not comparable
207            _ => None,
208        }
209    }
210}
211
212impl Ord for Value {
213    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
214        self.partial_cmp(other).unwrap_or(std::cmp::Ordering::Equal)
215    }
216}
217
218pub type InsertData = Vec<(&'static str, Value)>; 
219
220// Add From implementations for common types
221impl From<i64> for Value {
222    fn from(v: i64) -> Self {
223        Value::Int(v)
224    }
225}
226
227impl From<i32> for Value {
228    fn from(v: i32) -> Self {
229        Value::Int(v as i64)
230    }
231}
232
233impl From<&str> for Value {
234    fn from(v: &str) -> Self {
235        Value::String(v.to_string())
236    }
237}
238
239impl From<String> for Value {
240    fn from(v: String) -> Self {
241        Value::String(v)
242    }
243}
244
245impl From<bool> for Value {
246    fn from(v: bool) -> Self {
247        Value::Bool(v)
248    }
249}
250
251impl From<f64> for Value {
252    fn from(v: f64) -> Self {
253        Value::Float(v)
254    }
255}
256
257impl From<Vec<Value>> for Value {
258    fn from(v: Vec<Value>) -> Self {
259        Value::Array(v)
260    }
261}
262
263impl From<HashMap<String, Value>> for Value {
264    fn from(v: HashMap<String, Value>) -> Self {
265        Value::Object(v)
266    }
267}
268
269impl From<Uuid> for Value {
270    fn from(v: Uuid) -> Self {
271        Value::Uuid(v)
272    }
273}
274
275/// Configuration for Aurora database
276#[derive(Debug, Clone)]
277pub struct AuroraConfig {
278    // Database location settings
279    pub db_path: PathBuf,
280    pub create_dirs: bool,      // Create parent directories if they don't exist
281    
282    // Hot store config
283    pub hot_cache_size_mb: usize,
284    pub hot_cache_cleanup_interval_secs: u64,
285    
286    // Cold store config
287    pub cold_cache_capacity_mb: usize,
288    pub cold_flush_interval_ms: Option<u64>,
289    pub cold_mode: ColdStoreMode,
290    
291    // General config
292    pub auto_compact: bool,
293    pub compact_interval_mins: u64,
294}
295
296#[derive(Debug, Clone, Copy)]
297pub enum ColdStoreMode {
298    HighThroughput,
299    LowSpace,
300}
301
302impl Default for AuroraConfig {
303    fn default() -> Self {
304        Self {
305            db_path: PathBuf::from("aurora.db"),
306            create_dirs: true,
307            
308            hot_cache_size_mb: 128,
309            hot_cache_cleanup_interval_secs: 30,
310            
311            cold_cache_capacity_mb: 64,
312            cold_flush_interval_ms: Some(100),
313            cold_mode: ColdStoreMode::HighThroughput,
314            
315            auto_compact: true,
316            compact_interval_mins: 60,
317        }
318    }
319}
320
321impl AuroraConfig {
322    /// Create a new configuration with a specific database path
323    pub fn with_path<P: AsRef<Path>>(path: P) -> Self {
324        let mut config = Self::default();
325        config.db_path = path.as_ref().to_path_buf();
326        config
327    }
328}