use hax_types::engine_api::protocol::FromEngine;
use serde::Deserialize;
use serde::de::DeserializeOwned;
use std::io::{BufRead, BufReader, Stdin, stdin, stdout};
use std::sync::{LazyLock, Mutex};
use hax_frontend_exporter::id_table::WithTable;
use hax_types::engine_api::{EngineOptions, protocol::ToEngine};
static STDIN: LazyLock<Mutex<BufReader<Stdin>>> =
LazyLock::new(|| Mutex::new(BufReader::new(stdin())));
fn read<T: DeserializeOwned>() -> T {
let mut stdin = STDIN.lock().unwrap();
let mut slice = Vec::new();
stdin
.read_until(b'\n', &mut slice)
.expect("No message left! Did the engine crash?");
let mut de = serde_json::Deserializer::from_slice(&slice);
de.disable_recursion_limit();
T::deserialize(serde_stacker::Deserializer::new(&mut de)).unwrap_or_else(|err| {
panic!(
"Could not parse as a `{}` message! Error: {err}",
std::any::type_name::<T>()
)
})
}
pub fn read_to_engine_message() -> ToEngine {
read()
}
pub fn read_engine_input_message() -> WithTable<EngineOptions> {
read()
}
pub fn read_query() -> WithTable<EngineOptions> {
let mut stdin = STDIN.lock().unwrap();
let mut slice = Vec::new();
stdin
.read_until(b'\n', &mut slice)
.expect("No message left! Did the engine crash?");
let mut de = serde_json::Deserializer::from_slice(&slice);
de.disable_recursion_limit();
WithTable::deserialize(serde_stacker::Deserializer::new(&mut de))
.expect("Could not parse as a table of EngineOptions!")
}
pub fn write(message: &FromEngine) {
use std::io::Write;
let mut stdout = stdout();
serde_json::to_writer(&mut stdout, message).unwrap();
stdout.write_all(b"\n").unwrap();
stdout.flush().unwrap();
}