403 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
			
		
		
	
	
			403 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
use redb::{ReadableTable};
 | 
						|
use crate::error::DBError;
 | 
						|
use super::*;
 | 
						|
 | 
						|
impl Storage {
 | 
						|
    // ✅ ENCRYPTION APPLIED: Elements are encrypted before storage
 | 
						|
    pub fn lpush(&self, key: &str, elements: Vec<String>) -> Result<i64, DBError> {
 | 
						|
        let write_txn = self.db.begin_write()?;
 | 
						|
        let mut _length = 0i64;
 | 
						|
        
 | 
						|
        {
 | 
						|
            let mut types_table = write_txn.open_table(TYPES_TABLE)?;
 | 
						|
            let mut lists_table = write_txn.open_table(LISTS_TABLE)?;
 | 
						|
            
 | 
						|
            // Set the type to list
 | 
						|
            types_table.insert(key, "list")?;
 | 
						|
            
 | 
						|
            // Get current list or create empty one
 | 
						|
            let mut list: Vec<String> = match lists_table.get(key)? {
 | 
						|
                Some(data) => {
 | 
						|
                    let decrypted = self.decrypt_if_needed(data.value())?;
 | 
						|
                    serde_json::from_slice(&decrypted)?
 | 
						|
                }
 | 
						|
                None => Vec::new(),
 | 
						|
            };
 | 
						|
            
 | 
						|
            // Add elements to the front (left)
 | 
						|
            for element in elements.into_iter() {
 | 
						|
                list.insert(0, element);
 | 
						|
            }
 | 
						|
            
 | 
						|
            _length = list.len() as i64;
 | 
						|
            
 | 
						|
            // Encrypt and store the updated list
 | 
						|
            let serialized = serde_json::to_vec(&list)?;
 | 
						|
            let encrypted = self.encrypt_if_needed(&serialized)?;
 | 
						|
            lists_table.insert(key, encrypted.as_slice())?;
 | 
						|
        }
 | 
						|
        
 | 
						|
        write_txn.commit()?;
 | 
						|
        Ok(_length)
 | 
						|
    }
 | 
						|
 | 
						|
    // ✅ ENCRYPTION APPLIED: Elements are encrypted before storage
 | 
						|
    pub fn rpush(&self, key: &str, elements: Vec<String>) -> Result<i64, DBError> {
 | 
						|
        let write_txn = self.db.begin_write()?;
 | 
						|
        let mut _length = 0i64;
 | 
						|
        
 | 
						|
        {
 | 
						|
            let mut types_table = write_txn.open_table(TYPES_TABLE)?;
 | 
						|
            let mut lists_table = write_txn.open_table(LISTS_TABLE)?;
 | 
						|
            
 | 
						|
            // Set the type to list
 | 
						|
            types_table.insert(key, "list")?;
 | 
						|
            
 | 
						|
            // Get current list or create empty one
 | 
						|
            let mut list: Vec<String> = match lists_table.get(key)? {
 | 
						|
                Some(data) => {
 | 
						|
                    let decrypted = self.decrypt_if_needed(data.value())?;
 | 
						|
                    serde_json::from_slice(&decrypted)?
 | 
						|
                }
 | 
						|
                None => Vec::new(),
 | 
						|
            };
 | 
						|
            
 | 
						|
            // Add elements to the end (right)
 | 
						|
            list.extend(elements);
 | 
						|
            _length = list.len() as i64;
 | 
						|
            
 | 
						|
            // Encrypt and store the updated list
 | 
						|
            let serialized = serde_json::to_vec(&list)?;
 | 
						|
            let encrypted = self.encrypt_if_needed(&serialized)?;
 | 
						|
            lists_table.insert(key, encrypted.as_slice())?;
 | 
						|
        }
 | 
						|
        
 | 
						|
        write_txn.commit()?;
 | 
						|
        Ok(_length)
 | 
						|
    }
 | 
						|
 | 
						|
    // ✅ ENCRYPTION APPLIED: Elements are decrypted after retrieval and encrypted before storage
 | 
						|
    pub fn lpop(&self, key: &str, count: u64) -> Result<Vec<String>, DBError> {
 | 
						|
        let write_txn = self.db.begin_write()?;
 | 
						|
        let mut result = Vec::new();
 | 
						|
        
 | 
						|
        // First check if key exists and is a list, and get the data
 | 
						|
        let list_data = {
 | 
						|
            let types_table = write_txn.open_table(TYPES_TABLE)?;
 | 
						|
            let lists_table = write_txn.open_table(LISTS_TABLE)?;
 | 
						|
            
 | 
						|
            let result = match types_table.get(key)? {
 | 
						|
                Some(type_val) if type_val.value() == "list" => {
 | 
						|
                    if let Some(data) = lists_table.get(key)? {
 | 
						|
                        let decrypted = self.decrypt_if_needed(data.value())?;
 | 
						|
                        let list: Vec<String> = serde_json::from_slice(&decrypted)?;
 | 
						|
                        Some(list)
 | 
						|
                    } else {
 | 
						|
                        None
 | 
						|
                    }
 | 
						|
                }
 | 
						|
                _ => None,
 | 
						|
            };
 | 
						|
            result
 | 
						|
        };
 | 
						|
        
 | 
						|
        if let Some(mut list) = list_data {
 | 
						|
            let pop_count = std::cmp::min(count as usize, list.len());
 | 
						|
            for _ in 0..pop_count {
 | 
						|
                if !list.is_empty() {
 | 
						|
                    result.push(list.remove(0));
 | 
						|
                }
 | 
						|
            }
 | 
						|
            
 | 
						|
            let mut lists_table = write_txn.open_table(LISTS_TABLE)?;
 | 
						|
            if list.is_empty() {
 | 
						|
                // Remove the key if list is empty
 | 
						|
                lists_table.remove(key)?;
 | 
						|
                let mut types_table = write_txn.open_table(TYPES_TABLE)?;
 | 
						|
                types_table.remove(key)?;
 | 
						|
            } else {
 | 
						|
                // Encrypt and store the updated list
 | 
						|
                let serialized = serde_json::to_vec(&list)?;
 | 
						|
                let encrypted = self.encrypt_if_needed(&serialized)?;
 | 
						|
                lists_table.insert(key, encrypted.as_slice())?;
 | 
						|
            }
 | 
						|
        }
 | 
						|
        
 | 
						|
        write_txn.commit()?;
 | 
						|
        Ok(result)
 | 
						|
    }
 | 
						|
 | 
						|
    // ✅ ENCRYPTION APPLIED: Elements are decrypted after retrieval and encrypted before storage
 | 
						|
    pub fn rpop(&self, key: &str, count: u64) -> Result<Vec<String>, DBError> {
 | 
						|
        let write_txn = self.db.begin_write()?;
 | 
						|
        let mut result = Vec::new();
 | 
						|
        
 | 
						|
        // First check if key exists and is a list, and get the data
 | 
						|
        let list_data = {
 | 
						|
            let types_table = write_txn.open_table(TYPES_TABLE)?;
 | 
						|
            let lists_table = write_txn.open_table(LISTS_TABLE)?;
 | 
						|
            
 | 
						|
            let result = match types_table.get(key)? {
 | 
						|
                Some(type_val) if type_val.value() == "list" => {
 | 
						|
                    if let Some(data) = lists_table.get(key)? {
 | 
						|
                        let decrypted = self.decrypt_if_needed(data.value())?;
 | 
						|
                        let list: Vec<String> = serde_json::from_slice(&decrypted)?;
 | 
						|
                        Some(list)
 | 
						|
                    } else {
 | 
						|
                        None
 | 
						|
                    }
 | 
						|
                }
 | 
						|
                _ => None,
 | 
						|
            };
 | 
						|
            result
 | 
						|
        };
 | 
						|
        
 | 
						|
        if let Some(mut list) = list_data {
 | 
						|
            let pop_count = std::cmp::min(count as usize, list.len());
 | 
						|
            for _ in 0..pop_count {
 | 
						|
                if !list.is_empty() {
 | 
						|
                    result.push(list.pop().unwrap());
 | 
						|
                }
 | 
						|
            }
 | 
						|
            
 | 
						|
            let mut lists_table = write_txn.open_table(LISTS_TABLE)?;
 | 
						|
            if list.is_empty() {
 | 
						|
                // Remove the key if list is empty
 | 
						|
                lists_table.remove(key)?;
 | 
						|
                let mut types_table = write_txn.open_table(TYPES_TABLE)?;
 | 
						|
                types_table.remove(key)?;
 | 
						|
            } else {
 | 
						|
                // Encrypt and store the updated list
 | 
						|
                let serialized = serde_json::to_vec(&list)?;
 | 
						|
                let encrypted = self.encrypt_if_needed(&serialized)?;
 | 
						|
                lists_table.insert(key, encrypted.as_slice())?;
 | 
						|
            }
 | 
						|
        }
 | 
						|
        
 | 
						|
        write_txn.commit()?;
 | 
						|
        Ok(result)
 | 
						|
    }
 | 
						|
 | 
						|
    pub fn llen(&self, key: &str) -> Result<i64, DBError> {
 | 
						|
        let read_txn = self.db.begin_read()?;
 | 
						|
        let types_table = read_txn.open_table(TYPES_TABLE)?;
 | 
						|
        
 | 
						|
        match types_table.get(key)? {
 | 
						|
            Some(type_val) if type_val.value() == "list" => {
 | 
						|
                let lists_table = read_txn.open_table(LISTS_TABLE)?;
 | 
						|
                match lists_table.get(key)? {
 | 
						|
                    Some(data) => {
 | 
						|
                        let decrypted = self.decrypt_if_needed(data.value())?;
 | 
						|
                        let list: Vec<String> = serde_json::from_slice(&decrypted)?;
 | 
						|
                        Ok(list.len() as i64)
 | 
						|
                    }
 | 
						|
                    None => Ok(0),
 | 
						|
                }
 | 
						|
            }
 | 
						|
            _ => Ok(0),
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    // ✅ ENCRYPTION APPLIED: Element is decrypted after retrieval
 | 
						|
    pub fn lindex(&self, key: &str, index: i64) -> Result<Option<String>, DBError> {
 | 
						|
        let read_txn = self.db.begin_read()?;
 | 
						|
        let types_table = read_txn.open_table(TYPES_TABLE)?;
 | 
						|
        
 | 
						|
        match types_table.get(key)? {
 | 
						|
            Some(type_val) if type_val.value() == "list" => {
 | 
						|
                let lists_table = read_txn.open_table(LISTS_TABLE)?;
 | 
						|
                match lists_table.get(key)? {
 | 
						|
                    Some(data) => {
 | 
						|
                        let decrypted = self.decrypt_if_needed(data.value())?;
 | 
						|
                        let list: Vec<String> = serde_json::from_slice(&decrypted)?;
 | 
						|
                        
 | 
						|
                        let actual_index = if index < 0 {
 | 
						|
                            list.len() as i64 + index
 | 
						|
                        } else {
 | 
						|
                            index
 | 
						|
                        };
 | 
						|
                        
 | 
						|
                        if actual_index >= 0 && (actual_index as usize) < list.len() {
 | 
						|
                            Ok(Some(list[actual_index as usize].clone()))
 | 
						|
                        } else {
 | 
						|
                            Ok(None)
 | 
						|
                        }
 | 
						|
                    }
 | 
						|
                    None => Ok(None),
 | 
						|
                }
 | 
						|
            }
 | 
						|
            _ => Ok(None),
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    // ✅ ENCRYPTION APPLIED: Elements are decrypted after retrieval
 | 
						|
    pub fn lrange(&self, key: &str, start: i64, stop: i64) -> Result<Vec<String>, DBError> {
 | 
						|
        let read_txn = self.db.begin_read()?;
 | 
						|
        let types_table = read_txn.open_table(TYPES_TABLE)?;
 | 
						|
        
 | 
						|
        match types_table.get(key)? {
 | 
						|
            Some(type_val) if type_val.value() == "list" => {
 | 
						|
                let lists_table = read_txn.open_table(LISTS_TABLE)?;
 | 
						|
                match lists_table.get(key)? {
 | 
						|
                    Some(data) => {
 | 
						|
                        let decrypted = self.decrypt_if_needed(data.value())?;
 | 
						|
                        let list: Vec<String> = serde_json::from_slice(&decrypted)?;
 | 
						|
                        
 | 
						|
                        if list.is_empty() {
 | 
						|
                            return Ok(Vec::new());
 | 
						|
                        }
 | 
						|
                        
 | 
						|
                        let len = list.len() as i64;
 | 
						|
                        let start_idx = if start < 0 { std::cmp::max(0, len + start) } else { std::cmp::min(start, len) };
 | 
						|
                        let stop_idx = if stop < 0 { std::cmp::max(-1, len + stop) } else { std::cmp::min(stop, len - 1) };
 | 
						|
                        
 | 
						|
                        if start_idx > stop_idx || start_idx >= len {
 | 
						|
                            return Ok(Vec::new());
 | 
						|
                        }
 | 
						|
                        
 | 
						|
                        let start_usize = start_idx as usize;
 | 
						|
                        let stop_usize = (stop_idx + 1) as usize;
 | 
						|
                        
 | 
						|
                        Ok(list[start_usize..std::cmp::min(stop_usize, list.len())].to_vec())
 | 
						|
                    }
 | 
						|
                    None => Ok(Vec::new()),
 | 
						|
                }
 | 
						|
            }
 | 
						|
            _ => Ok(Vec::new()),
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    // ✅ ENCRYPTION APPLIED: Elements are decrypted after retrieval and encrypted before storage
 | 
						|
    pub fn ltrim(&self, key: &str, start: i64, stop: i64) -> Result<(), DBError> {
 | 
						|
        let write_txn = self.db.begin_write()?;
 | 
						|
        
 | 
						|
        // First check if key exists and is a list, and get the data
 | 
						|
        let list_data = {
 | 
						|
            let types_table = write_txn.open_table(TYPES_TABLE)?;
 | 
						|
            let lists_table = write_txn.open_table(LISTS_TABLE)?;
 | 
						|
            
 | 
						|
            let result = match types_table.get(key)? {
 | 
						|
                Some(type_val) if type_val.value() == "list" => {
 | 
						|
                    if let Some(data) = lists_table.get(key)? {
 | 
						|
                        let decrypted = self.decrypt_if_needed(data.value())?;
 | 
						|
                        let list: Vec<String> = serde_json::from_slice(&decrypted)?;
 | 
						|
                        Some(list)
 | 
						|
                    } else {
 | 
						|
                        None
 | 
						|
                    }
 | 
						|
                }
 | 
						|
                _ => None,
 | 
						|
            };
 | 
						|
            result
 | 
						|
        };
 | 
						|
        
 | 
						|
        if let Some(list) = list_data {
 | 
						|
            if list.is_empty() {
 | 
						|
                write_txn.commit()?;
 | 
						|
                return Ok(());
 | 
						|
            }
 | 
						|
            
 | 
						|
            let len = list.len() as i64;
 | 
						|
            let start_idx = if start < 0 { std::cmp::max(0, len + start) } else { std::cmp::min(start, len) };
 | 
						|
            let stop_idx = if stop < 0 { std::cmp::max(-1, len + stop) } else { std::cmp::min(stop, len - 1) };
 | 
						|
            
 | 
						|
            let mut lists_table = write_txn.open_table(LISTS_TABLE)?;
 | 
						|
            if start_idx > stop_idx || start_idx >= len {
 | 
						|
                // Remove the entire list
 | 
						|
                lists_table.remove(key)?;
 | 
						|
                let mut types_table = write_txn.open_table(TYPES_TABLE)?;
 | 
						|
                types_table.remove(key)?;
 | 
						|
            } else {
 | 
						|
                let start_usize = start_idx as usize;
 | 
						|
                let stop_usize = (stop_idx + 1) as usize;
 | 
						|
                let trimmed = list[start_usize..std::cmp::min(stop_usize, list.len())].to_vec();
 | 
						|
                
 | 
						|
                if trimmed.is_empty() {
 | 
						|
                    lists_table.remove(key)?;
 | 
						|
                    let mut types_table = write_txn.open_table(TYPES_TABLE)?;
 | 
						|
                    types_table.remove(key)?;
 | 
						|
                } else {
 | 
						|
                    // Encrypt and store the trimmed list
 | 
						|
                    let serialized = serde_json::to_vec(&trimmed)?;
 | 
						|
                    let encrypted = self.encrypt_if_needed(&serialized)?;
 | 
						|
                    lists_table.insert(key, encrypted.as_slice())?;
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
        
 | 
						|
        write_txn.commit()?;
 | 
						|
        Ok(())
 | 
						|
    }
 | 
						|
 | 
						|
    // ✅ ENCRYPTION APPLIED: Elements are decrypted after retrieval and encrypted before storage
 | 
						|
    pub fn lrem(&self, key: &str, count: i64, element: &str) -> Result<i64, DBError> {
 | 
						|
        let write_txn = self.db.begin_write()?;
 | 
						|
        let mut removed = 0i64;
 | 
						|
        
 | 
						|
        // First check if key exists and is a list, and get the data
 | 
						|
        let list_data = {
 | 
						|
            let types_table = write_txn.open_table(TYPES_TABLE)?;
 | 
						|
            let lists_table = write_txn.open_table(LISTS_TABLE)?;
 | 
						|
            
 | 
						|
            let result = match types_table.get(key)? {
 | 
						|
                Some(type_val) if type_val.value() == "list" => {
 | 
						|
                    if let Some(data) = lists_table.get(key)? {
 | 
						|
                        let decrypted = self.decrypt_if_needed(data.value())?;
 | 
						|
                        let list: Vec<String> = serde_json::from_slice(&decrypted)?;
 | 
						|
                        Some(list)
 | 
						|
                    } else {
 | 
						|
                        None
 | 
						|
                    }
 | 
						|
                }
 | 
						|
                _ => None,
 | 
						|
            };
 | 
						|
            result
 | 
						|
        };
 | 
						|
        
 | 
						|
        if let Some(mut list) = list_data {
 | 
						|
            if count == 0 {
 | 
						|
                // Remove all occurrences
 | 
						|
                let original_len = list.len();
 | 
						|
                list.retain(|x| x != element);
 | 
						|
                removed = (original_len - list.len()) as i64;
 | 
						|
            } else if count > 0 {
 | 
						|
                // Remove first count occurrences
 | 
						|
                let mut to_remove = count as usize;
 | 
						|
                list.retain(|x| {
 | 
						|
                    if x == element && to_remove > 0 {
 | 
						|
                        to_remove -= 1;
 | 
						|
                        removed += 1;
 | 
						|
                        false
 | 
						|
                    } else {
 | 
						|
                        true
 | 
						|
                    }
 | 
						|
                });
 | 
						|
            } else {
 | 
						|
                // Remove last |count| occurrences
 | 
						|
                let mut to_remove = (-count) as usize;
 | 
						|
                for i in (0..list.len()).rev() {
 | 
						|
                    if list[i] == element && to_remove > 0 {
 | 
						|
                        list.remove(i);
 | 
						|
                        to_remove -= 1;
 | 
						|
                        removed += 1;
 | 
						|
                    }
 | 
						|
                }
 | 
						|
            }
 | 
						|
            
 | 
						|
            let mut lists_table = write_txn.open_table(LISTS_TABLE)?;
 | 
						|
            if list.is_empty() {
 | 
						|
                lists_table.remove(key)?;
 | 
						|
                let mut types_table = write_txn.open_table(TYPES_TABLE)?;
 | 
						|
                types_table.remove(key)?;
 | 
						|
            } else {
 | 
						|
                // Encrypt and store the updated list
 | 
						|
                let serialized = serde_json::to_vec(&list)?;
 | 
						|
                let encrypted = self.encrypt_if_needed(&serialized)?;
 | 
						|
                lists_table.insert(key, encrypted.as_slice())?;
 | 
						|
            }
 | 
						|
        }
 | 
						|
        
 | 
						|
        write_txn.commit()?;
 | 
						|
        Ok(removed)
 | 
						|
    }
 | 
						|
} |