coil-runtime 0.1.1

HTTP runtime and request handling for the Coil framework.
Documentation
use std::collections::BTreeMap;
use std::sync::Arc;

use coil_wasm::SecretExecution;

use super::super::*;

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum SecretBackendMode {
    Runtime,
    #[cfg(test)]
    Test,
}

#[derive(Debug, Clone)]
pub(super) struct RuntimeSecretBackend {
    mode: SecretBackendMode,
    scope: Arc<String>,
    values: Arc<BTreeMap<String, String>>,
}

impl Default for RuntimeSecretBackend {
    fn default() -> Self {
        Self::deny_all("unknown-runtime")
    }
}

impl RuntimeSecretBackend {
    pub(super) fn runtime_scoped(
        scope: impl Into<String>,
        values: BTreeMap<String, String>,
    ) -> Self {
        Self {
            mode: SecretBackendMode::Runtime,
            scope: Arc::new(scope.into()),
            values: Arc::new(values),
        }
    }

    pub(super) fn deny_all(scope: impl Into<String>) -> Self {
        Self {
            mode: SecretBackendMode::Runtime,
            scope: Arc::new(scope.into()),
            values: Arc::new(BTreeMap::new()),
        }
    }

    #[cfg(test)]
    pub(super) fn with_values(values: BTreeMap<String, String>) -> Self {
        Self {
            mode: SecretBackendMode::Test,
            scope: Arc::new("test-runtime".to_string()),
            values: Arc::new(values),
        }
    }

    pub(super) fn read(
        &self,
        secret: &str,
        _context: &InvocationContext,
    ) -> Result<SecretExecution, String> {
        if let Some(value) = self.values.get(secret) {
            let source = match self.mode {
                SecretBackendMode::Runtime => format!("runtime:{}:{secret}", self.scope),
                #[cfg(test)]
                SecretBackendMode::Test => format!("in-memory:{secret}"),
            };
            return Ok(SecretExecution {
                secret: secret.to_string(),
                source,
                value_bytes: value.len(),
            });
        }

        Err(format!(
            "secret `{secret}` was not provided to runtime `{}`",
            self.scope
        ))
    }
}