trelent-hyok 0.1.12

A Rust library implementing Hold Your Own Key (HYOK) encryption patterns with support for multiple cloud providers
Documentation
//! In-memory DEK storage for testing and development.
//!
//! This module provides a simple in-memory storage implementation for
//! Data Encryption Keys (DEKs). It is intended for:
//!
//! - Testing and development
//! - Example implementations
//! - Prototyping
//!
//! # Warning
//!
//! This implementation is not suitable for production use as it:
//! - Stores keys in memory only
//! - Does not persist across restarts
//! - May not scale well with large numbers of keys

#![cfg(feature = "debug")]

use std::collections::HashMap;

use async_trait::async_trait;

use crate::error::generator::PersistError;

use std::sync::Mutex;

use super::DEKPersisterTrait;

/// An in-memory DEK persister for testing and debugging purposes.
///
/// This implementation:
/// - Stores keys in a thread-safe HashMap
/// - Provides basic persistence operations
/// - Supports concurrent access
/// - Uses hex-encoded contexts as keys
///
/// # Warning
///
/// This persister is intended for testing only and should not be used
/// in production environments as it:
/// - Does not provide persistent storage
/// - May have memory limitations
/// - Lacks security features
///
/// # Example
/// ```no_run
/// use hyokashi::MemPersister;
///
///     let persister = MemPersister::new();
///
///     // Store a key
///     let my_key = vec![1, 2, 3];
///     let stored = persister.persist(&my_key, "test-key".to_string()).await?;
///
///     // Retrieve the key
///     let retrieved = persister.fetch("test-key".to_string()).await?;
///
/// ```
#[derive(Debug)]
pub struct MemPersister(Mutex<HashMap<String, Vec<u8>>>);

impl MemPersister {
    /// Creates a new empty `MemPersister`.
    pub fn new() -> Self {
        MemPersister(Mutex::new(HashMap::new()))
    }

    /// Inserts a key into the in-memory store.
    ///
    /// # Arguments
    ///
    /// * `context` - The identifier for the key
    /// * `dek` - The key bytes to store
    ///
    /// # Errors
    ///
    /// Returns a `PersistError` if:
    /// - The mutex is poisoned
    /// - The key cannot be inserted
    pub async fn insert(&self, context: String, dek: Vec<u8>) -> Result<Vec<u8>, PersistError> {
        let data = self.0.lock();
        let context = hex::encode(context);
        match data {
            Ok(mut data) => {
                data.insert(context.clone(), dek);
                data.get(&context)
                    .cloned()
                    .ok_or(PersistError::Error("Could not insert!".to_string()))
            }
            Err(_) => Err(PersistError::Error("Mutex error!".to_string())),
        }
    }

    /// Retrieves a key from the in-memory store.
    ///
    /// # Arguments
    ///
    /// * `context` - The identifier for the key
    ///
    /// # Errors
    ///
    /// Returns a `PersistError` if:
    /// - The mutex is poisoned
    /// - The key is not found
    pub async fn fetch(&self, context: String) -> Result<Vec<u8>, PersistError> {
        let context = hex::encode(context);
        match self.0.lock() {
            Ok(data) =>
                data
                    .get(&context)
                    .cloned()
                    .ok_or(PersistError::NoKey("Could not fetch!".to_string())),
            Err(_) => Err(PersistError::Error("Mutex Error!".to_string())),
        }
    }
}

#[async_trait]
impl DEKPersisterTrait for MemPersister {
    /// Persists a key in the in-memory store.
    ///
    /// # Errors
    ///
    /// Returns a `PersistError` if the key cannot be stored
    async fn persist(&self, key: &Vec<u8>, context: String) -> Result<Vec<u8>, PersistError> {
        self.insert(context, key.clone()).await
    }

    /// Retrieves a key from the in-memory store.
    ///
    /// # Errors
    ///
    /// Returns a `PersistError` if the key cannot be found
    async fn fetch(&self, context: String) -> Result<Vec<u8>, PersistError> {
        match self.fetch(context).await {
            Ok(key) => Ok(key.clone()),
            Err(e) => Err(e),
        }
    }
}