2019-06-27 18:47:24 +02:00
|
|
|
use crate::errors::ShellError;
|
2019-07-16 09:08:35 +02:00
|
|
|
use crate::parser::registry;
|
2019-06-27 18:47:24 +02:00
|
|
|
use crate::prelude::*;
|
2019-07-16 09:08:35 +02:00
|
|
|
use derive_new::new;
|
2019-06-27 18:47:24 +02:00
|
|
|
use serde::{self, Deserialize, Serialize};
|
|
|
|
use std::io::prelude::*;
|
|
|
|
use std::io::BufReader;
|
2019-06-29 10:55:42 +02:00
|
|
|
use std::io::Write;
|
2019-06-27 18:47:24 +02:00
|
|
|
|
|
|
|
#[derive(Debug, Serialize, Deserialize)]
|
|
|
|
pub struct JsonRpc<T> {
|
|
|
|
jsonrpc: String,
|
|
|
|
pub method: String,
|
|
|
|
pub params: T,
|
|
|
|
}
|
2019-06-29 10:55:42 +02:00
|
|
|
|
2019-06-27 18:47:24 +02:00
|
|
|
impl<T> JsonRpc<T> {
|
|
|
|
pub fn new<U: Into<String>>(method: U, params: T) -> Self {
|
|
|
|
JsonRpc {
|
|
|
|
jsonrpc: "2.0".into(),
|
|
|
|
method: method.into(),
|
|
|
|
params,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, Serialize, Deserialize)]
|
|
|
|
#[serde(tag = "method")]
|
|
|
|
#[allow(non_camel_case_types)]
|
|
|
|
pub enum NuResult {
|
2019-07-02 09:56:20 +02:00
|
|
|
response {
|
|
|
|
params: Result<VecDeque<ReturnValue>, ShellError>,
|
|
|
|
},
|
2019-06-27 18:47:24 +02:00
|
|
|
}
|
|
|
|
|
2019-07-16 09:08:35 +02:00
|
|
|
#[derive(new)]
|
|
|
|
pub struct PluginCommand {
|
|
|
|
name: String,
|
|
|
|
path: String,
|
|
|
|
config: registry::CommandConfig,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Command for PluginCommand {
|
2019-07-24 00:22:11 +02:00
|
|
|
fn run(
|
|
|
|
&self,
|
|
|
|
args: CommandArgs,
|
|
|
|
registry: &CommandRegistry,
|
|
|
|
) -> Result<OutputStream, ShellError> {
|
|
|
|
filter_plugin(self.path.clone(), args, registry)
|
2019-07-16 09:08:35 +02:00
|
|
|
}
|
|
|
|
fn name(&self) -> &str {
|
|
|
|
&self.name
|
|
|
|
}
|
|
|
|
fn config(&self) -> registry::CommandConfig {
|
|
|
|
self.config.clone()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(new)]
|
|
|
|
pub struct PluginSink {
|
|
|
|
name: String,
|
|
|
|
path: String,
|
|
|
|
config: registry::CommandConfig,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Sink for PluginSink {
|
|
|
|
fn run(&self, args: SinkCommandArgs) -> Result<(), ShellError> {
|
|
|
|
sink_plugin(self.path.clone(), args)
|
|
|
|
}
|
|
|
|
fn name(&self) -> &str {
|
|
|
|
&self.name
|
|
|
|
}
|
|
|
|
fn config(&self) -> registry::CommandConfig {
|
|
|
|
self.config.clone()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-07-24 00:22:11 +02:00
|
|
|
pub fn filter_plugin(
|
|
|
|
path: String,
|
|
|
|
args: CommandArgs,
|
|
|
|
registry: &CommandRegistry,
|
|
|
|
) -> Result<OutputStream, ShellError> {
|
|
|
|
let args = args.evaluate_once(registry)?;
|
|
|
|
|
2019-06-27 18:47:24 +02:00
|
|
|
let mut child = std::process::Command::new(path)
|
|
|
|
.stdin(std::process::Stdio::piped())
|
|
|
|
.stdout(std::process::Stdio::piped())
|
|
|
|
.spawn()
|
|
|
|
.expect("Failed to spawn child process");
|
|
|
|
|
|
|
|
{
|
2019-06-29 10:55:42 +02:00
|
|
|
let stdin = child.stdin.as_mut().expect("Failed to open stdin");
|
|
|
|
let stdout = child.stdout.as_mut().expect("Failed to open stdout");
|
2019-06-27 18:47:24 +02:00
|
|
|
|
2019-07-13 18:59:59 +02:00
|
|
|
let mut reader = BufReader::new(stdout);
|
2019-06-27 18:47:24 +02:00
|
|
|
|
2019-07-24 00:22:11 +02:00
|
|
|
let request = JsonRpc::new("begin_filter", args.args.call_info);
|
2019-06-27 18:47:24 +02:00
|
|
|
let request_raw = serde_json::to_string(&request).unwrap();
|
2019-06-29 10:55:42 +02:00
|
|
|
stdin.write(format!("{}\n", request_raw).as_bytes())?;
|
2019-07-13 18:59:59 +02:00
|
|
|
let mut input = String::new();
|
|
|
|
match reader.read_line(&mut input) {
|
|
|
|
Ok(_) => {
|
|
|
|
let response = serde_json::from_str::<NuResult>(&input);
|
|
|
|
match response {
|
|
|
|
Ok(NuResult::response { params }) => match params {
|
|
|
|
Ok(_) => {}
|
|
|
|
Err(e) => {
|
|
|
|
return Err(e);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
Err(e) => {
|
|
|
|
return Err(ShellError::string(format!(
|
|
|
|
"Error while processing input: {:?} {}",
|
|
|
|
e, input
|
|
|
|
)));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
2019-06-27 18:47:24 +02:00
|
|
|
}
|
2019-06-29 10:55:42 +02:00
|
|
|
|
2019-07-08 18:44:53 +02:00
|
|
|
let mut eos: VecDeque<Spanned<Value>> = VecDeque::new();
|
|
|
|
eos.push_back(Value::Primitive(Primitive::EndOfStream).spanned_unknown());
|
2019-06-27 18:47:24 +02:00
|
|
|
|
2019-07-02 09:56:20 +02:00
|
|
|
let stream = args
|
|
|
|
.input
|
2019-07-13 04:07:06 +02:00
|
|
|
.values
|
2019-06-27 18:47:24 +02:00
|
|
|
.chain(eos)
|
|
|
|
.map(move |v| match v {
|
2019-07-08 18:44:53 +02:00
|
|
|
Spanned {
|
|
|
|
item: Value::Primitive(Primitive::EndOfStream),
|
|
|
|
..
|
|
|
|
} => {
|
2019-06-29 10:55:42 +02:00
|
|
|
let stdin = child.stdin.as_mut().expect("Failed to open stdin");
|
|
|
|
let stdout = child.stdout.as_mut().expect("Failed to open stdout");
|
2019-06-27 18:47:24 +02:00
|
|
|
|
2019-06-29 10:55:42 +02:00
|
|
|
let _ = BufReader::new(stdout);
|
2019-06-27 18:47:24 +02:00
|
|
|
let request: JsonRpc<std::vec::Vec<Value>> = JsonRpc::new("quit", vec![]);
|
|
|
|
let request_raw = serde_json::to_string(&request).unwrap();
|
2019-06-29 10:55:42 +02:00
|
|
|
let _ = stdin.write(format!("{}\n", request_raw).as_bytes()); // TODO: Handle error
|
2019-06-27 18:47:24 +02:00
|
|
|
|
|
|
|
VecDeque::new()
|
|
|
|
}
|
|
|
|
_ => {
|
2019-06-29 10:55:42 +02:00
|
|
|
let stdin = child.stdin.as_mut().expect("Failed to open stdin");
|
|
|
|
let stdout = child.stdout.as_mut().expect("Failed to open stdout");
|
2019-06-27 18:47:24 +02:00
|
|
|
|
|
|
|
let mut reader = BufReader::new(stdout);
|
|
|
|
|
|
|
|
let request = JsonRpc::new("filter", v);
|
|
|
|
let request_raw = serde_json::to_string(&request).unwrap();
|
2019-06-29 10:55:42 +02:00
|
|
|
let _ = stdin.write(format!("{}\n", request_raw).as_bytes()); // TODO: Handle error
|
2019-06-27 18:47:24 +02:00
|
|
|
|
|
|
|
let mut input = String::new();
|
|
|
|
match reader.read_line(&mut input) {
|
|
|
|
Ok(_) => {
|
|
|
|
let response = serde_json::from_str::<NuResult>(&input);
|
|
|
|
match response {
|
2019-07-02 09:56:20 +02:00
|
|
|
Ok(NuResult::response { params }) => match params {
|
|
|
|
Ok(params) => params,
|
|
|
|
Err(e) => {
|
|
|
|
let mut result = VecDeque::new();
|
2019-07-13 04:07:06 +02:00
|
|
|
result.push_back(ReturnValue::Err(e));
|
2019-07-02 09:56:20 +02:00
|
|
|
result
|
|
|
|
}
|
|
|
|
},
|
|
|
|
Err(e) => {
|
2019-06-27 18:47:24 +02:00
|
|
|
let mut result = VecDeque::new();
|
2019-07-03 22:31:15 +02:00
|
|
|
result.push_back(Err(ShellError::string(format!(
|
|
|
|
"Error while processing input: {:?} {}",
|
|
|
|
e, input
|
2019-06-27 18:47:24 +02:00
|
|
|
))));
|
|
|
|
result
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-07-02 09:56:20 +02:00
|
|
|
Err(e) => {
|
2019-06-27 18:47:24 +02:00
|
|
|
let mut result = VecDeque::new();
|
2019-07-03 22:31:15 +02:00
|
|
|
result.push_back(Err(ShellError::string(format!(
|
|
|
|
"Error while processing input: {:?}",
|
|
|
|
e
|
2019-06-27 18:47:24 +02:00
|
|
|
))));
|
|
|
|
result
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
.flatten();
|
|
|
|
|
2019-07-03 22:31:15 +02:00
|
|
|
Ok(stream.to_output_stream())
|
2019-06-27 18:47:24 +02:00
|
|
|
}
|
2019-07-02 09:56:20 +02:00
|
|
|
|
2019-07-03 19:37:09 +02:00
|
|
|
pub fn sink_plugin(path: String, args: SinkCommandArgs) -> Result<(), ShellError> {
|
2019-07-05 00:17:18 +02:00
|
|
|
//use subprocess::Exec;
|
2019-07-20 04:27:10 +02:00
|
|
|
let request = JsonRpc::new("sink", (args.call_info, args.input));
|
2019-07-05 00:17:18 +02:00
|
|
|
let request_raw = serde_json::to_string(&request).unwrap();
|
|
|
|
let mut tmpfile = tempfile::NamedTempFile::new()?;
|
|
|
|
let _ = writeln!(tmpfile, "{}", request_raw);
|
|
|
|
let _ = tmpfile.flush();
|
|
|
|
|
2019-07-02 09:56:20 +02:00
|
|
|
let mut child = std::process::Command::new(path)
|
2019-07-05 00:17:18 +02:00
|
|
|
.arg(tmpfile.path())
|
2019-07-02 09:56:20 +02:00
|
|
|
.spawn()
|
|
|
|
.expect("Failed to spawn child process");
|
|
|
|
|
|
|
|
let _ = child.wait();
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|