use axum::{extract::State, http::StatusCode, Json};
use serde::{Deserialize, Serialize};
use std::sync::Arc;
use tokio::sync::oneshot;
use crate::AppState;
#[derive(Debug, Deserialize)]
pub struct EvalRequest {
pub code: String,
}
#[derive(Debug, Serialize)]
pub struct EvalResponse {
pub success: bool,
pub result: Option<String>,
pub error: Option<String>,
}
pub struct EvalJob {
pub code: String,
pub response_tx: oneshot::Sender<EvalResult>,
}
pub struct EvalResult {
pub success: bool,
pub result: Option<String>,
pub error: Option<String>,
}
pub async fn eval_code(
State(state): State<Arc<AppState>>,
Json(req): Json<EvalRequest>,
) -> (StatusCode, Json<EvalResponse>) {
let eval_tx = match &state.eval_tx {
Some(tx) => tx,
None => {
return (
StatusCode::SERVICE_UNAVAILABLE,
Json(EvalResponse {
success: false,
result: None,
error: Some("Eval not available in this mode".to_string()),
}),
);
}
};
let (response_tx, response_rx) = oneshot::channel();
let job = EvalJob {
code: req.code,
response_tx,
};
if eval_tx.send(job).is_err() {
return (
StatusCode::INTERNAL_SERVER_ERROR,
Json(EvalResponse {
success: false,
result: None,
error: Some("Failed to send eval request".to_string()),
}),
);
}
match response_rx.await {
Ok(result) => (
if result.success {
StatusCode::OK
} else {
StatusCode::BAD_REQUEST
},
Json(EvalResponse {
success: result.success,
result: result.result,
error: result.error,
}),
),
Err(_) => (
StatusCode::INTERNAL_SERVER_ERROR,
Json(EvalResponse {
success: false,
result: None,
error: Some("Eval request cancelled".to_string()),
}),
),
}
}