Skip to main content

qdb_rs/
entry.rs

1//! Entry types for QDB - Key, Value, and Entry definitions
2
3use crate::error::{QdbError, Result};
4use num_complex::Complex64;
5use qft::QftFile;
6use serde::{Deserialize, Serialize};
7use std::collections::HashMap;
8use std::time::{SystemTime, UNIX_EPOCH};
9
10// =============================================================================
11// Key Types
12// =============================================================================
13
14/// A database key - supports string, integer, and composite keys
15#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
16pub enum Key {
17    /// String key
18    String(String),
19    /// Integer key
20    Integer(i64),
21    /// Composite key (multiple parts)
22    Composite(Vec<Key>),
23    /// Binary key (hash)
24    Binary(Vec<u8>),
25}
26
27impl Key {
28    /// Create a string key
29    pub fn string(s: impl Into<String>) -> Self {
30        Key::String(s.into())
31    }
32
33    /// Create an integer key
34    pub fn integer(i: i64) -> Self {
35        Key::Integer(i)
36    }
37
38    /// Create a composite key
39    pub fn composite(parts: Vec<Key>) -> Self {
40        Key::Composite(parts)
41    }
42
43    /// Create a binary key from bytes
44    pub fn binary(data: impl AsRef<[u8]>) -> Self {
45        Key::Binary(data.as_ref().to_vec())
46    }
47
48    /// Hash the key to a fixed-size binary representation
49    pub fn hash(&self) -> [u8; 32] {
50        let bytes = self.to_bytes();
51        *blake3::hash(&bytes).as_bytes()
52    }
53
54    /// Convert key to bytes for hashing
55    pub fn to_bytes(&self) -> Vec<u8> {
56        match self {
57            Key::String(s) => {
58                let mut v = vec![0u8]; // type tag
59                v.extend(s.as_bytes());
60                v
61            }
62            Key::Integer(i) => {
63                let mut v = vec![1u8];
64                v.extend(&i.to_le_bytes());
65                v
66            }
67            Key::Composite(parts) => {
68                let mut v = vec![2u8];
69                for part in parts {
70                    let part_bytes = part.to_bytes();
71                    v.extend(&(part_bytes.len() as u32).to_le_bytes());
72                    v.extend(part_bytes);
73                }
74                v
75            }
76            Key::Binary(data) => {
77                let mut v = vec![3u8];
78                v.extend(data);
79                v
80            }
81        }
82    }
83
84    /// Map key to qubit index for quantum operations
85    /// Uses hash to distribute keys uniformly across 2^n indices
86    pub fn to_qubit_index(&self, num_qubits: usize) -> usize {
87        let hash = self.hash();
88        let mut index: usize = 0;
89        for (i, &byte) in hash.iter().take(8).enumerate() {
90            index |= (byte as usize) << (i * 8);
91        }
92        index % (1 << num_qubits)
93    }
94}
95
96impl From<&str> for Key {
97    fn from(s: &str) -> Self {
98        Key::String(s.to_string())
99    }
100}
101
102impl From<String> for Key {
103    fn from(s: String) -> Self {
104        Key::String(s)
105    }
106}
107
108impl From<i64> for Key {
109    fn from(i: i64) -> Self {
110        Key::Integer(i)
111    }
112}
113
114impl std::fmt::Display for Key {
115    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
116        match self {
117            Key::String(s) => write!(f, "{}", s),
118            Key::Integer(i) => write!(f, "{}", i),
119            Key::Composite(parts) => {
120                let strs: Vec<String> = parts.iter().map(|p| p.to_string()).collect();
121                write!(f, "({})", strs.join(", "))
122            }
123            Key::Binary(data) => write!(f, "0x{}", hex::encode(data)),
124        }
125    }
126}
127
128// =============================================================================
129// Value Types
130// =============================================================================
131
132/// A database value - supports classical data and quantum states
133#[derive(Debug, Clone, Serialize, Deserialize)]
134pub enum Value {
135    /// Null value
136    Null,
137    /// Boolean value
138    Bool(bool),
139    /// Integer value
140    Integer(i64),
141    /// Floating point value
142    Float(f64),
143    /// String value
144    String(String),
145    /// Binary data
146    Binary(Vec<u8>),
147    /// JSON document
148    Json(serde_json::Value),
149    /// Quantum state (serialized QFT)
150    #[serde(skip)]
151    Quantum(Box<QftFile>),
152    /// Complex number
153    Complex { re: f64, im: f64 },
154    /// Array of values
155    Array(Vec<Value>),
156    /// Map of key-value pairs
157    Map(HashMap<String, Value>),
158}
159
160impl Value {
161    /// Create a quantum value from a QFT file
162    pub fn quantum(qft: QftFile) -> Self {
163        Value::Quantum(Box::new(qft))
164    }
165
166    /// Create a complex value
167    pub fn complex(re: f64, im: f64) -> Self {
168        Value::Complex { re, im }
169    }
170
171    /// Check if value is null
172    pub fn is_null(&self) -> bool {
173        matches!(self, Value::Null)
174    }
175
176    /// Check if value is a quantum state
177    pub fn is_quantum(&self) -> bool {
178        matches!(self, Value::Quantum(_))
179    }
180
181    /// Get as quantum state if applicable
182    pub fn as_quantum(&self) -> Option<&QftFile> {
183        match self {
184            Value::Quantum(qft) => Some(qft),
185            _ => None,
186        }
187    }
188
189    /// Get as mutable quantum state if applicable
190    pub fn as_quantum_mut(&mut self) -> Option<&mut QftFile> {
191        match self {
192            Value::Quantum(qft) => Some(qft),
193            _ => None,
194        }
195    }
196
197    /// Convert to Complex64 if applicable
198    pub fn to_complex(&self) -> Option<Complex64> {
199        match self {
200            Value::Complex { re, im } => Some(Complex64::new(*re, *im)),
201            Value::Float(f) => Some(Complex64::new(*f, 0.0)),
202            Value::Integer(i) => Some(Complex64::new(*i as f64, 0.0)),
203            _ => None,
204        }
205    }
206
207    /// Serialize value to bytes
208    pub fn to_bytes(&self) -> Result<Vec<u8>> {
209        match self {
210            Value::Quantum(qft) => qft.to_bytes().map_err(QdbError::from),
211            _ => serde_json::to_vec(self).map_err(QdbError::from),
212        }
213    }
214
215    /// Get the type name of this value
216    pub fn type_name(&self) -> &'static str {
217        match self {
218            Value::Null => "null",
219            Value::Bool(_) => "bool",
220            Value::Integer(_) => "integer",
221            Value::Float(_) => "float",
222            Value::String(_) => "string",
223            Value::Binary(_) => "binary",
224            Value::Json(_) => "json",
225            Value::Quantum(_) => "quantum",
226            Value::Complex { .. } => "complex",
227            Value::Array(_) => "array",
228            Value::Map(_) => "map",
229        }
230    }
231}
232
233impl Default for Value {
234    fn default() -> Self {
235        Value::Null
236    }
237}
238
239impl From<bool> for Value {
240    fn from(b: bool) -> Self {
241        Value::Bool(b)
242    }
243}
244
245impl From<i64> for Value {
246    fn from(i: i64) -> Self {
247        Value::Integer(i)
248    }
249}
250
251impl From<f64> for Value {
252    fn from(f: f64) -> Self {
253        Value::Float(f)
254    }
255}
256
257impl From<String> for Value {
258    fn from(s: String) -> Self {
259        Value::String(s)
260    }
261}
262
263impl From<&str> for Value {
264    fn from(s: &str) -> Self {
265        Value::String(s.to_string())
266    }
267}
268
269impl From<QftFile> for Value {
270    fn from(qft: QftFile) -> Self {
271        Value::Quantum(Box::new(qft))
272    }
273}
274
275impl From<serde_json::Value> for Value {
276    fn from(v: serde_json::Value) -> Self {
277        Value::Json(v)
278    }
279}
280
281// =============================================================================
282// Entry Types
283// =============================================================================
284
285/// Type of database entry
286#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
287pub enum EntryType {
288    /// Classical key-value entry
289    KeyValue,
290    /// JSON document entry
291    Document,
292    /// Quantum state entry
293    QuantumState,
294    /// Tensor network entry (for relational joins)
295    TensorNetwork,
296}
297
298/// A complete database entry with metadata
299#[derive(Debug, Clone, Serialize, Deserialize)]
300pub struct Entry {
301    /// The entry key
302    pub key: Key,
303    /// The entry value
304    pub value: Value,
305    /// Entry type
306    pub entry_type: EntryType,
307    /// Creation timestamp (Unix epoch milliseconds)
308    pub created_at: u64,
309    /// Last modified timestamp
310    pub modified_at: u64,
311    /// Version number for optimistic concurrency
312    pub version: u64,
313    /// Custom metadata
314    pub metadata: HashMap<String, String>,
315    /// Checksum for integrity verification
316    #[serde(skip)]
317    pub checksum: Option<[u8; 32]>,
318}
319
320impl Entry {
321    /// Create a new entry
322    pub fn new(key: Key, value: Value) -> Self {
323        let now = SystemTime::now()
324            .duration_since(UNIX_EPOCH)
325            .unwrap_or_default()
326            .as_millis() as u64;
327
328        let entry_type = match &value {
329            Value::Quantum(_) => EntryType::QuantumState,
330            Value::Json(_) | Value::Map(_) => EntryType::Document,
331            _ => EntryType::KeyValue,
332        };
333
334        Self {
335            key,
336            value,
337            entry_type,
338            created_at: now,
339            modified_at: now,
340            version: 1,
341            metadata: HashMap::new(),
342            checksum: None,
343        }
344    }
345
346    /// Create a quantum state entry
347    pub fn quantum(key: Key, qft: QftFile) -> Self {
348        let mut entry = Self::new(key, Value::quantum(qft));
349        entry.entry_type = EntryType::QuantumState;
350        entry
351    }
352
353    /// Create a document entry
354    pub fn document(key: Key, doc: serde_json::Value) -> Self {
355        let mut entry = Self::new(key, Value::Json(doc));
356        entry.entry_type = EntryType::Document;
357        entry
358    }
359
360    /// Set metadata
361    pub fn with_metadata(mut self, key: impl Into<String>, value: impl Into<String>) -> Self {
362        self.metadata.insert(key.into(), value.into());
363        self
364    }
365
366    /// Update the value and increment version
367    pub fn update(&mut self, value: Value) {
368        self.value = value;
369        self.modified_at = SystemTime::now()
370            .duration_since(UNIX_EPOCH)
371            .unwrap_or_default()
372            .as_millis() as u64;
373        self.version += 1;
374        self.checksum = None;
375    }
376
377    /// Compute and cache checksum
378    pub fn compute_checksum(&mut self) -> Result<[u8; 32]> {
379        let value_bytes = self.value.to_bytes()?;
380        let key_bytes = self.key.to_bytes();
381
382        let mut hasher = blake3::Hasher::new();
383        hasher.update(&key_bytes);
384        hasher.update(&value_bytes);
385        hasher.update(&self.version.to_le_bytes());
386
387        let hash = *hasher.finalize().as_bytes();
388        self.checksum = Some(hash);
389        Ok(hash)
390    }
391
392    /// Verify checksum
393    pub fn verify_checksum(&self) -> Result<bool> {
394        if let Some(stored) = self.checksum {
395            let value_bytes = self.value.to_bytes()?;
396            let key_bytes = self.key.to_bytes();
397
398            let mut hasher = blake3::Hasher::new();
399            hasher.update(&key_bytes);
400            hasher.update(&value_bytes);
401            hasher.update(&self.version.to_le_bytes());
402
403            let computed = *hasher.finalize().as_bytes();
404            Ok(stored == computed)
405        } else {
406            Ok(true) // No checksum to verify
407        }
408    }
409
410    /// Get the size of this entry in bytes (approximate)
411    pub fn size_bytes(&self) -> usize {
412        let key_size = self.key.to_bytes().len();
413        let value_size = self.value.to_bytes().map(|b| b.len()).unwrap_or(0);
414        let metadata_size: usize = self
415            .metadata
416            .iter()
417            .map(|(k, v)| k.len() + v.len())
418            .sum();
419
420        key_size + value_size + metadata_size + 64 // overhead for timestamps, version, etc.
421    }
422}
423
424// Hex encoding helper (minimal implementation)
425mod hex {
426    pub fn encode(data: &[u8]) -> String {
427        data.iter().map(|b| format!("{:02x}", b)).collect()
428    }
429}
430
431#[cfg(test)]
432mod tests {
433    use super::*;
434
435    #[test]
436    fn test_key_string() {
437        let key = Key::string("test");
438        assert_eq!(key.to_string(), "test");
439    }
440
441    #[test]
442    fn test_key_hash() {
443        let key1 = Key::string("test");
444        let key2 = Key::string("test");
445        let key3 = Key::string("other");
446
447        assert_eq!(key1.hash(), key2.hash());
448        assert_ne!(key1.hash(), key3.hash());
449    }
450
451    #[test]
452    fn test_key_qubit_index() {
453        let key = Key::string("test");
454        let idx = key.to_qubit_index(10);
455        assert!(idx < 1024);
456    }
457
458    #[test]
459    fn test_value_types() {
460        assert!(Value::Null.is_null());
461        assert!(!Value::Integer(42).is_null());
462
463        let qft = QftFile::new(2).unwrap();
464        let quantum_val = Value::quantum(qft);
465        assert!(quantum_val.is_quantum());
466    }
467
468    #[test]
469    fn test_entry_creation() {
470        let entry = Entry::new(Key::string("key1"), Value::Integer(42));
471        assert_eq!(entry.entry_type, EntryType::KeyValue);
472        assert_eq!(entry.version, 1);
473    }
474
475    #[test]
476    fn test_entry_update() {
477        let mut entry = Entry::new(Key::string("key1"), Value::Integer(42));
478        entry.update(Value::Integer(100));
479        assert_eq!(entry.version, 2);
480    }
481
482    #[test]
483    fn test_entry_checksum() {
484        let mut entry = Entry::new(Key::string("key1"), Value::Integer(42));
485        let checksum = entry.compute_checksum().unwrap();
486        assert!(entry.verify_checksum().unwrap());
487
488        // Modify without updating checksum
489        entry.value = Value::Integer(100);
490        assert!(!entry.verify_checksum().unwrap());
491    }
492}