1use 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#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
16pub enum Key {
17 String(String),
19 Integer(i64),
21 Composite(Vec<Key>),
23 Binary(Vec<u8>),
25}
26
27impl Key {
28 pub fn string(s: impl Into<String>) -> Self {
30 Key::String(s.into())
31 }
32
33 pub fn integer(i: i64) -> Self {
35 Key::Integer(i)
36 }
37
38 pub fn composite(parts: Vec<Key>) -> Self {
40 Key::Composite(parts)
41 }
42
43 pub fn binary(data: impl AsRef<[u8]>) -> Self {
45 Key::Binary(data.as_ref().to_vec())
46 }
47
48 pub fn hash(&self) -> [u8; 32] {
50 let bytes = self.to_bytes();
51 *blake3::hash(&bytes).as_bytes()
52 }
53
54 pub fn to_bytes(&self) -> Vec<u8> {
56 match self {
57 Key::String(s) => {
58 let mut v = vec![0u8]; 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 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#[derive(Debug, Clone, Serialize, Deserialize)]
134pub enum Value {
135 Null,
137 Bool(bool),
139 Integer(i64),
141 Float(f64),
143 String(String),
145 Binary(Vec<u8>),
147 Json(serde_json::Value),
149 #[serde(skip)]
151 Quantum(Box<QftFile>),
152 Complex { re: f64, im: f64 },
154 Array(Vec<Value>),
156 Map(HashMap<String, Value>),
158}
159
160impl Value {
161 pub fn quantum(qft: QftFile) -> Self {
163 Value::Quantum(Box::new(qft))
164 }
165
166 pub fn complex(re: f64, im: f64) -> Self {
168 Value::Complex { re, im }
169 }
170
171 pub fn is_null(&self) -> bool {
173 matches!(self, Value::Null)
174 }
175
176 pub fn is_quantum(&self) -> bool {
178 matches!(self, Value::Quantum(_))
179 }
180
181 pub fn as_quantum(&self) -> Option<&QftFile> {
183 match self {
184 Value::Quantum(qft) => Some(qft),
185 _ => None,
186 }
187 }
188
189 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 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 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 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#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
287pub enum EntryType {
288 KeyValue,
290 Document,
292 QuantumState,
294 TensorNetwork,
296}
297
298#[derive(Debug, Clone, Serialize, Deserialize)]
300pub struct Entry {
301 pub key: Key,
303 pub value: Value,
305 pub entry_type: EntryType,
307 pub created_at: u64,
309 pub modified_at: u64,
311 pub version: u64,
313 pub metadata: HashMap<String, String>,
315 #[serde(skip)]
317 pub checksum: Option<[u8; 32]>,
318}
319
320impl Entry {
321 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 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 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 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 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 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 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) }
408 }
409
410 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 }
422}
423
424mod 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 entry.value = Value::Integer(100);
490 assert!(!entry.verify_checksum().unwrap());
491 }
492}