diff --git a/Cargo.lock b/Cargo.lock index f15fe41..732c409 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1411,6 +1411,7 @@ dependencies = [ "anyhow", "async-io", "async-oneshot", + "async-process", "async-trait", "futures", "futures-core", diff --git a/service/Cargo.toml b/service/Cargo.toml index 5c22b65..0066a43 100644 --- a/service/Cargo.toml +++ b/service/Cargo.toml @@ -28,3 +28,4 @@ toml = "0.5" tracing = "0.1" tracing-subscriber = { version = "0.3", features = ["fmt"] } futures-core = "0.3.16" +async-process = "1.3.0" diff --git a/service/src/client.rs b/service/src/client.rs new file mode 100644 index 0000000..a0e3160 --- /dev/null +++ b/service/src/client.rs @@ -0,0 +1,62 @@ +// Copyright 2021 System76 +// SPDX-License-Identifier: MPL-2.0 + +use async_process as process; +use futures::{AsyncBufReadExt, AsyncWriteExt, Stream, StreamExt}; +use pop_launcher::{Request, Response}; +use std::io; + +pub struct IpcClient { + pub child: process::Child, + pub stdin: process::ChildStdin, +} + +impl IpcClient { + pub fn new() -> io::Result<(Self, impl Stream)> { + let mut child = process::Command::new("pop-launcher") + .stdin(process::Stdio::piped()) + .stdout(process::Stdio::piped()) + .spawn()?; + + let stdin = child + .stdin + .take() + .ok_or_else(|| io::Error::new(io::ErrorKind::Other, "failed to find child stdin"))?; + + let stdout = child + .stdout + .take() + .ok_or_else(|| io::Error::new(io::ErrorKind::Other, "failed to find child stdout"))?; + + let responses = + futures::io::BufReader::new(stdout) + .lines() + .filter_map(|result| async move { + if let Ok(line) = result { + if let Ok(event) = serde_json::from_str::(&line) { + return Some(event); + } + } + + None + }); + + let client = Self { child, stdin }; + + Ok((client, responses)) + } + + pub async fn send(&mut self, request: Request) -> io::Result<()> { + let mut request_json = serde_json::to_string(&request) + .map_err(|err| io::Error::new(io::ErrorKind::InvalidInput, err))?; + + request_json.push('\n'); + + self.stdin.write_all(request_json.as_bytes()).await + } + + pub async fn exit(mut self) { + let _ = self.send(Request::Exit).await; + let _ = self.child.status().await; + } +} diff --git a/service/src/lib.rs b/service/src/lib.rs index a91a221..cbbe4f0 100644 --- a/service/src/lib.rs +++ b/service/src/lib.rs @@ -1,8 +1,11 @@ // Copyright 2021 System76 // SPDX-License-Identifier: MPL-2.0 +mod client; mod plugins; +pub use client::*; + use crate::plugins::*; use futures::SinkExt; use futures_core::Stream;