1use spin::Mutex;
2#[cfg(unix)]
3use std::os::unix::io::FromRawFd;
4#[cfg(windows)]
5use std::os::windows::io::FromRawHandle;
6use std::{fs::File, io::Write, sync::LazyLock};
7
8use serde::Serialize;
9
10static PIPE_WRITER: LazyLock<Mutex<Option<File>>> = LazyLock::new(|| Mutex::new(None));
11
12pub fn init(pipe_id: usize) {
13 let pipe_writer = {
14 #[cfg(windows)]
15 {
16 unsafe { File::from_raw_handle(pipe_id as *mut std::ffi::c_void) }
17 }
18 #[cfg(unix)]
19 {
20 unsafe { File::from_raw_fd(pipe_id as i32) }
21 }
22 };
23 let mut w = PIPE_WRITER
24 .lock();
25 *w = Some(pipe_writer);
26}
27
28#[derive(Debug)]
29pub enum PipeError {
30 WriteError(std::io::Error),
31 SerialiseError(serde_json::Error),
32}
33
34impl From<std::io::Error> for PipeError {
35 fn from(value: std::io::Error) -> Self {
36 PipeError::WriteError(value)
37 }
38}
39
40impl From<serde_json::Error> for PipeError {
41 fn from(value: serde_json::Error) -> Self {
42 PipeError::SerialiseError(value)
43 }
44}
45
46pub fn send<T: Serialize>(obj: &T) {
55 try_send(obj).expect("Serialisation or io::Error occurred. Use `pipe::try_send` instead.")
56}
57
58pub fn try_send<T: Serialize>(obj: &T) -> Result<(), PipeError> {
63 let mut binding = PIPE_WRITER
64 .lock();
65 let w = binding
66 .as_mut()
67 .expect("Pipe must be initialised (with pipe::init) before sending data.");
68 writeln!(
69 w,
70 "{}",
71 serde_json::to_string(obj).map_err(PipeError::from)?
72 )
73 .map_err(Into::into)
74}