//! One JSON call over stdin/stdout. Script exception text never leaves this guest. use sausage_cred_script::{ErrorKind, Limits, evaluate}; use std::io::{Read, Write}; use zeroize::Zeroizing; #[derive(serde::Deserialize)] struct Request { source: String, input: Zeroizing, export: Option, max_time_ms: u64, max_memory_bytes: usize, } fn run() -> Result<(), Box> { let mut wire = Zeroizing::new(String::new()); std::io::stdin().read_to_string(&mut wire)?; let request: Request = serde_json::from_str(&wire)?; let result = evaluate( &request.source, &request.input, request.export.as_deref(), Limits { max_time_ms: Some(request.max_time_ms), max_memory_bytes: Some(request.max_memory_bytes), ..Limits::default() }, ); let response = match result { Ok(result) => serde_json::json!({"result": result}), Err(error) => serde_json::json!({"kind": match error.kind { ErrorKind::Limit => "Limit", ErrorKind::Syntax => "Syntax", ErrorKind::Throw => "Throw", ErrorKind::NonJson => "NonJson", ErrorKind::Engine => "Engine", }}), }; serde_json::to_writer(std::io::stdout().lock(), &response)?; std::io::stdout().flush()?; Ok(()) } fn main() { if run().is_err() { std::process::exit(1); } } #[cfg(test)] mod tests { use super::*; #[test] fn request_input_has_zeroizing_ownership() { let request: Request = serde_json::from_str(r#"{"source":"export default x=>x","input":"null","export":null,"max_time_ms":100,"max_memory_bytes":8388608}"#).unwrap(); let _: &Zeroizing = &request.input; } }