use std::io::BufRead;
use anyhow::Result;
use async_trait::async_trait;
use surrealdb_types::ToSql;
use surrealism_runtime::config::SurrealismConfig;
use surrealism_runtime::host::InvocationContext;
use surrealism_runtime::kv::{BTreeMapStore, KVStore};
pub struct DemoHost {
kv: BTreeMapStore,
}
impl DemoHost {
pub fn new() -> Self {
Self {
kv: BTreeMapStore::new(),
}
}
}
fn parse_value(s: &str) -> Result<surrealdb_types::Value, String> {
crate::core::syn::value(s).map_err(|e| format!("Invalid value: {e}"))
}
#[async_trait]
impl InvocationContext for DemoHost {
fn kv(&mut self) -> Result<&dyn KVStore> {
Ok(&self.kv)
}
async fn sql(
&mut self,
_config: &SurrealismConfig,
query: String,
vars: surrealdb_types::Object,
) -> Result<surrealdb_types::Value> {
println!("The module is running a SQL query:");
println!("SQL: {query}");
println!("Vars: {}", vars.to_sql());
println!("Please enter the result:");
let stdin = std::io::stdin();
loop {
let line = match stdin.lock().lines().next() {
Some(Ok(line)) => line,
Some(Err(e)) => {
anyhow::bail!("Failed to read from stdin: {e}");
}
None => {
anyhow::bail!("stdin closed unexpectedly");
}
};
match parse_value(&line) {
Ok(x) => {
println!(" ");
return Ok(x);
}
Err(e) => {
println!("Failed to parse value: {e}");
println!("Please try again");
}
}
}
}
async fn run(
&mut self,
_config: &SurrealismConfig,
fnc: String,
version: Option<String>,
args: Vec<surrealdb_types::Value>,
) -> Result<surrealdb_types::Value> {
let version = version.map(|x| format!("<{x}>")).unwrap_or_default();
println!("The module is running a function:");
println!(
" - {fnc}{version}({})",
args.iter().map(|x| x.to_sql()).collect::<Vec<String>>().join(", ")
);
println!("\nPlease enter the result:");
let stdin = std::io::stdin();
loop {
let line = match stdin.lock().lines().next() {
Some(Ok(line)) => line,
Some(Err(e)) => {
anyhow::bail!("Failed to read from stdin: {e}");
}
None => {
anyhow::bail!("stdin closed unexpectedly");
}
};
match parse_value(&line) {
Ok(x) => {
println!(" ");
return Ok(x);
}
Err(e) => {
println!("Failed to parse value: {e}");
println!("Please try again");
}
}
}
}
fn stdout(&mut self, output: &str) -> Result<()> {
println!("[surli::out] {}", output);
Ok(())
}
fn stderr(&mut self, output: &str) -> Result<()> {
eprintln!("[surli::err] {}", output);
Ok(())
}
}