aurora_db/
types.rs

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