use crate::actions::Action;
use crate::{command::Command, context::GremlinContext};
use async_std::prelude::*;
use futures::future::BoxFuture;
use futures::FutureExt;
use gremlin_client::{
aio::{GResultSet, GremlinClient},
GValue,
};
use crate::actions::display_results;
pub struct FallbackAction;
impl Action for FallbackAction {
fn name(&self) -> &str {
"g."
}
fn description(&self) -> &str {
"Execute a gremlin query."
}
fn handle(
&self,
ctx: &crate::context::GremlinContext,
cmd: String,
_: Vec<String>,
) -> Vec<crate::command::Command> {
if cmd.trim().starts_with(&ctx.alias) {
match ctx.client {
Some(ref client) => {
vec![Command::Exec(Box::new(execute_query(client.clone(), cmd)))]
}
None => vec![Command::Print(Some(String::from("Not connected!")))],
}
} else {
vec![Command::Print(Some(String::from("Command unrecognized!")))]
}
}
}
fn execute_query(
client: GremlinClient,
query: String,
) -> impl FnOnce(&GremlinContext) -> BoxFuture<'static, Vec<Command>> {
move |_| {
async move {
match client.execute(query, &[]).await {
Ok(stream) => match map_result(stream).await {
Ok(results) => vec![
display_results(&results),
Command::Update(Box::new(|ctx| GremlinContext {
last_results: results,
..ctx
})),
],
Err(error) => vec![Command::Print(Some(error))],
},
Err(err) => vec![Command::Print(Some(format!("{}", err)))],
}
}
.boxed()
}
}
async fn map_result(stream: GResultSet) -> Result<Vec<GValue>, String> {
stream
.collect::<Result<Vec<GValue>, _>>()
.await
.map_err(|err| format!("{}", err))
}