Skip to main content

travsr_plugin_sdk/
runner.rs

1use std::io::{self, BufReader, BufWriter};
2use tracing::{error, info};
3use travsr_plugin_protocol::{
4    codec::{decode_message, write_message},
5    HandshakeResponse, Plugin, PluginRequest, PluginResponse, PROTOCOL_VERSION,
6};
7
8/// Run the plugin event loop on stdin/stdout. Blocks until stdin closes.
9pub fn run_plugin<P: Plugin>(plugin: P) {
10    let stdin = io::stdin();
11    let stdout = io::stdout();
12    let mut reader = BufReader::new(stdin.lock());
13    let mut writer = BufWriter::new(stdout.lock());
14
15    loop {
16        let req: PluginRequest = match decode_message(&mut reader) {
17            Ok(r) => r,
18            Err(e) if e.kind() == io::ErrorKind::UnexpectedEof => break,
19            Err(e) => {
20                error!("framing error: {e}");
21                break;
22            }
23        };
24
25        let resp = match req {
26            PluginRequest::Handshake(h) => {
27                info!("handshake: daemon_version={}", h.daemon_protocol_version);
28                PluginResponse::Handshake(HandshakeResponse {
29                    protocol_version: PROTOCOL_VERSION,
30                    plugin_version: env!("CARGO_PKG_VERSION").to_string(),
31                    language: plugin.language().as_str().to_string(),
32                    extensions: plugin.extensions().iter().map(|s| s.to_string()).collect(),
33                    supports_phase_b: plugin.supports_phase_b(),
34                })
35            }
36            PluginRequest::Parse(req) => PluginResponse::Parse(plugin.parse(&req)),
37            PluginRequest::Invoke(req) => PluginResponse::Invoke(plugin.invoke_phase_b(&req)),
38        };
39
40        if let Err(e) = write_message(&mut writer, &resp) {
41            error!("write error: {e}");
42            break;
43        }
44    }
45}