use redb::{ReadableTable}; use crate::error::DBError; use super::*; impl Storage { // ✅ ENCRYPTION APPLIED: Values are encrypted before storage pub fn hset(&self, key: &str, pairs: Vec<(String, String)>) -> Result { let write_txn = self.db.begin_write()?; let mut new_fields = 0i64; { let mut types_table = write_txn.open_table(TYPES_TABLE)?; let mut hashes_table = write_txn.open_table(HASHES_TABLE)?; let key_type = { let access_guard = types_table.get(key)?; access_guard.map(|v| v.value().to_string()) }; match key_type.as_deref() { Some("hash") | None => { // Proceed if hash or new key // Set the type to hash (only if new key or existing hash) types_table.insert(key, "hash")?; for (field, value) in pairs { // Check if field already exists let exists = hashes_table.get((key, field.as_str()))?.is_some(); // Encrypt the value before storing let encrypted = self.encrypt_if_needed(value.as_bytes())?; hashes_table.insert((key, field.as_str()), encrypted.as_slice())?; if !exists { new_fields += 1; } } } Some(_) => return Err(DBError("WRONGTYPE Operation against a key holding the wrong kind of value".to_string())), } } write_txn.commit()?; Ok(new_fields) } // ✅ ENCRYPTION APPLIED: Value is decrypted after retrieval pub fn hget(&self, key: &str, field: &str) -> Result, DBError> { let read_txn = self.db.begin_read()?; let types_table = read_txn.open_table(TYPES_TABLE)?; let key_type = types_table.get(key)?.map(|v| v.value().to_string()); match key_type.as_deref() { Some("hash") => { let hashes_table = read_txn.open_table(HASHES_TABLE)?; match hashes_table.get((key, field))? { Some(data) => { let decrypted = self.decrypt_if_needed(data.value())?; let value = String::from_utf8(decrypted)?; Ok(Some(value)) } None => Ok(None), } } Some(_) => Err(DBError("WRONGTYPE Operation against a key holding the wrong kind of value".to_string())), None => Ok(None), } } // ✅ ENCRYPTION APPLIED: All values are decrypted after retrieval pub fn hgetall(&self, key: &str) -> Result, DBError> { let read_txn = self.db.begin_read()?; let types_table = read_txn.open_table(TYPES_TABLE)?; let key_type = { let access_guard = types_table.get(key)?; access_guard.map(|v| v.value().to_string()) }; match key_type.as_deref() { Some("hash") => { let hashes_table = read_txn.open_table(HASHES_TABLE)?; let mut result = Vec::new(); let mut iter = hashes_table.iter()?; while let Some(entry) = iter.next() { let entry = entry?; let (hash_key, field) = entry.0.value(); if hash_key == key { let decrypted = self.decrypt_if_needed(entry.1.value())?; let value = String::from_utf8(decrypted)?; result.push((field.to_string(), value)); } } Ok(result) } Some(_) => Err(DBError("WRONGTYPE Operation against a key holding the wrong kind of value".to_string())), None => Ok(Vec::new()), } } pub fn hdel(&self, key: &str, fields: Vec) -> Result { let write_txn = self.db.begin_write()?; let mut deleted = 0i64; // First check if key exists and is a hash let key_type = { let types_table = write_txn.open_table(TYPES_TABLE)?; let access_guard = types_table.get(key)?; access_guard.map(|v| v.value().to_string()) }; match key_type.as_deref() { Some("hash") => { let mut hashes_table = write_txn.open_table(HASHES_TABLE)?; for field in fields { if hashes_table.remove((key, field.as_str()))?.is_some() { deleted += 1; } } // Check if hash is now empty and remove type if so let mut has_fields = false; let mut iter = hashes_table.iter()?; while let Some(entry) = iter.next() { let entry = entry?; let (hash_key, _) = entry.0.value(); if hash_key == key { has_fields = true; break; } } drop(iter); if !has_fields { let mut types_table = write_txn.open_table(TYPES_TABLE)?; types_table.remove(key)?; } } Some(_) => return Err(DBError("WRONGTYPE Operation against a key holding the wrong kind of value".to_string())), None => {} // Key does not exist, nothing to delete, return 0 deleted } write_txn.commit()?; Ok(deleted) } pub fn hexists(&self, key: &str, field: &str) -> Result { let read_txn = self.db.begin_read()?; let types_table = read_txn.open_table(TYPES_TABLE)?; let key_type = { let access_guard = types_table.get(key)?; access_guard.map(|v| v.value().to_string()) }; match key_type.as_deref() { Some("hash") => { let hashes_table = read_txn.open_table(HASHES_TABLE)?; Ok(hashes_table.get((key, field))?.is_some()) } Some(_) => Err(DBError("WRONGTYPE Operation against a key holding the wrong kind of value".to_string())), None => Ok(false), } } pub fn hkeys(&self, key: &str) -> Result, DBError> { let read_txn = self.db.begin_read()?; let types_table = read_txn.open_table(TYPES_TABLE)?; let key_type = { let access_guard = types_table.get(key)?; access_guard.map(|v| v.value().to_string()) }; match key_type.as_deref() { Some("hash") => { let hashes_table = read_txn.open_table(HASHES_TABLE)?; let mut result = Vec::new(); let mut iter = hashes_table.iter()?; while let Some(entry) = iter.next() { let entry = entry?; let (hash_key, field) = entry.0.value(); if hash_key == key { result.push(field.to_string()); } } Ok(result) } Some(_) => Err(DBError("WRONGTYPE Operation against a key holding the wrong kind of value".to_string())), None => Ok(Vec::new()), } } // ✅ ENCRYPTION APPLIED: All values are decrypted after retrieval pub fn hvals(&self, key: &str) -> Result, DBError> { let read_txn = self.db.begin_read()?; let types_table = read_txn.open_table(TYPES_TABLE)?; let key_type = { let access_guard = types_table.get(key)?; access_guard.map(|v| v.value().to_string()) }; match key_type.as_deref() { Some("hash") => { let hashes_table = read_txn.open_table(HASHES_TABLE)?; let mut result = Vec::new(); let mut iter = hashes_table.iter()?; while let Some(entry) = iter.next() { let entry = entry?; let (hash_key, _) = entry.0.value(); if hash_key == key { let decrypted = self.decrypt_if_needed(entry.1.value())?; let value = String::from_utf8(decrypted)?; result.push(value); } } Ok(result) } Some(_) => Err(DBError("WRONGTYPE Operation against a key holding the wrong kind of value".to_string())), None => Ok(Vec::new()), } } pub fn hlen(&self, key: &str) -> Result { let read_txn = self.db.begin_read()?; let types_table = read_txn.open_table(TYPES_TABLE)?; let key_type = { let access_guard = types_table.get(key)?; access_guard.map(|v| v.value().to_string()) }; match key_type.as_deref() { Some("hash") => { let hashes_table = read_txn.open_table(HASHES_TABLE)?; let mut count = 0i64; let mut iter = hashes_table.iter()?; while let Some(entry) = iter.next() { let entry = entry?; let (hash_key, _) = entry.0.value(); if hash_key == key { count += 1; } } Ok(count) } Some(_) => Err(DBError("WRONGTYPE Operation against a key holding the wrong kind of value".to_string())), None => Ok(0), } } // ✅ ENCRYPTION APPLIED: Values are decrypted after retrieval pub fn hmget(&self, key: &str, fields: Vec) -> Result>, DBError> { let read_txn = self.db.begin_read()?; let types_table = read_txn.open_table(TYPES_TABLE)?; let key_type = { let access_guard = types_table.get(key)?; access_guard.map(|v| v.value().to_string()) }; match key_type.as_deref() { Some("hash") => { let hashes_table = read_txn.open_table(HASHES_TABLE)?; let mut result = Vec::new(); for field in fields { match hashes_table.get((key, field.as_str()))? { Some(data) => { let decrypted = self.decrypt_if_needed(data.value())?; let value = String::from_utf8(decrypted)?; result.push(Some(value)); } None => result.push(None), } } Ok(result) } Some(_) => Err(DBError("WRONGTYPE Operation against a key holding the wrong kind of value".to_string())), None => Ok(fields.into_iter().map(|_| None).collect()), } } // ✅ ENCRYPTION APPLIED: Value is encrypted before storage pub fn hsetnx(&self, key: &str, field: &str, value: &str) -> Result { let write_txn = self.db.begin_write()?; let mut result = false; { let mut types_table = write_txn.open_table(TYPES_TABLE)?; let mut hashes_table = write_txn.open_table(HASHES_TABLE)?; let key_type = { let access_guard = types_table.get(key)?; access_guard.map(|v| v.value().to_string()) }; match key_type.as_deref() { Some("hash") | None => { // Proceed if hash or new key // Check if field already exists if hashes_table.get((key, field))?.is_none() { // Set the type to hash (only if new key or existing hash) types_table.insert(key, "hash")?; // Encrypt the value before storing let encrypted = self.encrypt_if_needed(value.as_bytes())?; hashes_table.insert((key, field), encrypted.as_slice())?; result = true; } } Some(_) => return Err(DBError("WRONGTYPE Operation against a key holding the wrong kind of value".to_string())), } } write_txn.commit()?; Ok(result) } // ✅ ENCRYPTION APPLIED: Values are decrypted after retrieval pub fn hscan(&self, key: &str, cursor: u64, pattern: Option<&str>, count: Option) -> Result<(u64, Vec<(String, String)>), DBError> { let read_txn = self.db.begin_read()?; let types_table = read_txn.open_table(TYPES_TABLE)?; let key_type = { let access_guard = types_table.get(key)?; access_guard.map(|v| v.value().to_string()) }; match key_type.as_deref() { Some("hash") => { let hashes_table = read_txn.open_table(HASHES_TABLE)?; let mut result = Vec::new(); let mut current_cursor = 0u64; let limit = count.unwrap_or(10) as usize; let mut iter = hashes_table.iter()?; while let Some(entry) = iter.next() { let entry = entry?; let (hash_key, field) = entry.0.value(); if hash_key == key { if current_cursor >= cursor { let field_str = field.to_string(); // Apply pattern matching if specified let matches = if let Some(pat) = pattern { super::storage_extra::glob_match(pat, &field_str) } else { true }; if matches { let decrypted = self.decrypt_if_needed(entry.1.value())?; let value = String::from_utf8(decrypted)?; result.push((field_str, value)); if result.len() >= limit { break; } } } current_cursor += 1; } } let next_cursor = if result.len() < limit { 0 } else { current_cursor }; Ok((next_cursor, result)) } Some(_) => Err(DBError("WRONGTYPE Operation against a key holding the wrong kind of value".to_string())), None => Ok((0, Vec::new())), } } }