use std::collections::HashMap;
use anyhow::Result;
use async_trait::async_trait;
#[derive(Debug, Clone)]
pub struct SandboxOutput {
pub stdout: String,
pub stderr: String,
pub exit_code: i32,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum SandboxKind {
None,
OpenSandbox,
}
impl SandboxKind {
#[must_use]
pub fn parse(value: &str) -> Option<Self> {
match value.trim().to_ascii_lowercase().as_str() {
"none" | "" => Some(Self::None),
"opensandbox" | "open-sandbox" | "open_sandbox" => Some(Self::OpenSandbox),
_ => None,
}
}
#[must_use]
pub fn as_str(self) -> &'static str {
match self {
Self::None => "none",
Self::OpenSandbox => "opensandbox",
}
}
}
#[async_trait]
pub trait SandboxBackend: Send + Sync {
async fn exec(&self, cmd: &str, env: &HashMap<String, String>) -> Result<SandboxOutput>;
}
use crate::config::Config;
pub fn create_backend(config: &Config) -> Result<Option<Box<dyn SandboxBackend>>> {
let kind = config
.sandbox_backend
.as_deref()
.and_then(SandboxKind::parse)
.unwrap_or(SandboxKind::None);
match kind {
SandboxKind::None => Ok(None),
SandboxKind::OpenSandbox => {
let base_url = config
.sandbox_url
.clone()
.unwrap_or_else(|| "http://localhost:8080".to_string());
let api_key = config.sandbox_api_key.clone();
let backend = super::opensandbox::OpenSandboxBackend::new(base_url, api_key, 30)?;
Ok(Some(Box::new(backend)))
}
}
}