1use std::path::PathBuf;
2
3use serde::{Deserialize, Serialize};
4
5pub const DEFAULT_SOCKET: &str = "/tmp/kidex.sock";
6
7#[derive(Deserialize, Serialize)]
8pub enum IpcCommand {
9 FullIndex,
10 Quit,
11 Reload,
12 GetIndex(Option<PathBuf>),
13}
14
15#[derive(Deserialize, Serialize)]
16pub enum IpcResponse {
17 Success,
18 NotFound,
19 Index(Vec<IndexEntry>),
20}
21
22#[derive(Deserialize, Serialize, Clone)]
23pub struct IndexEntry {
24 pub path: PathBuf,
25 pub directory: bool,
26}
27
28#[cfg(feature = "util")]
29pub mod util {
30 use std::{
31 env,
32 fmt::Display,
33 io::{self, Read, Write},
34 os::unix::net::UnixStream,
35 path::PathBuf,
36 };
37
38 use super::{IndexEntry, IpcCommand, IpcResponse, DEFAULT_SOCKET};
39
40 #[derive(Debug)]
41 pub enum Error {
42 Io(io::Error),
43 Serde(serde_json::Error),
44 NotFound,
45 Unknown,
46 }
47
48 impl From<io::Error> for Error {
49 fn from(value: io::Error) -> Self {
50 Self::Io(value)
51 }
52 }
53
54 impl From<serde_json::Error> for Error {
55 fn from(value: serde_json::Error) -> Self {
56 Self::Serde(value)
57 }
58 }
59
60 impl Display for Error {
61 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
62 match self {
63 Error::Io(why) => write!(f, "An IO error occurred: {}", why),
64 Error::Serde(why) => write!(f, "A se/deserialization error occurred: {}", why),
65 Error::NotFound => write!(f, "Requested path not found"),
66 Error::Unknown => write!(f, "An unknown error occurred"),
67 }
68 }
69 }
70
71 impl std::error::Error for Error {}
72
73 fn fetch(command: &IpcCommand) -> Result<IpcResponse, Error> {
74 let mut stream =
75 UnixStream::connect(env::var("SOCKET_PATH").unwrap_or(DEFAULT_SOCKET.to_string()))?;
76
77 let mut buf = serde_json::to_vec(command).unwrap();
78 buf.push(0x0);
79
80 stream.write_all(&buf)?;
81
82 buf.clear();
83
84 stream.read_to_end(&mut buf)?;
85
86 Ok(serde_json::from_slice(&buf)?)
87 }
88
89 pub fn get_index(path: Option<PathBuf>) -> Result<Vec<IndexEntry>, Error> {
90 match fetch(&IpcCommand::GetIndex(path))? {
91 IpcResponse::Index(index) => Ok(index),
92 IpcResponse::NotFound => Err(Error::NotFound),
93 _ => unreachable!(),
94 }
95 }
96
97 pub fn regenerate_index() -> Result<(), Error> {
98 match fetch(&IpcCommand::FullIndex)? {
99 IpcResponse::Success => Ok(()),
100 _ => Err(Error::Unknown),
101 }
102 }
103
104 pub fn shutdown_server() -> Result<(), Error> {
105 match fetch(&IpcCommand::Quit)? {
106 IpcResponse::Success => Ok(()),
107 _ => Err(Error::Unknown),
108 }
109 }
110
111 pub fn reload_config() -> Result<(), Error> {
112 match fetch(&IpcCommand::Reload)? {
113 IpcResponse::Success => Ok(()),
114 _ => Err(Error::Unknown),
115 }
116 }
117}