kidex-common 0.1.0

Helper library for interacting with Kidex
Documentation
use std::path::PathBuf;

use serde::{Deserialize, Serialize};

pub const DEFAULT_SOCKET: &str = "/tmp/kidex.sock";

#[derive(Deserialize, Serialize)]
pub enum IpcCommand {
    FullIndex,
    Quit,
    Reload,
    GetIndex(Option<PathBuf>),
}

#[derive(Deserialize, Serialize)]
pub enum IpcResponse {
    Success,
    NotFound,
    Index(Vec<IndexEntry>),
}

#[derive(Deserialize, Serialize, Clone)]
pub struct IndexEntry {
    pub path: PathBuf,
    pub directory: bool,
}

#[cfg(feature = "util")]
pub mod util {
    use std::{
        env,
        fmt::Display,
        io::{self, Read, Write},
        os::unix::net::UnixStream,
        path::PathBuf,
    };

    use super::{IndexEntry, IpcCommand, IpcResponse, DEFAULT_SOCKET};

    #[derive(Debug)]
    pub enum Error {
        Io(io::Error),
        Serde(serde_json::Error),
        NotFound,
        Unknown,
    }

    impl From<io::Error> for Error {
        fn from(value: io::Error) -> Self {
            Self::Io(value)
        }
    }

    impl From<serde_json::Error> for Error {
        fn from(value: serde_json::Error) -> Self {
            Self::Serde(value)
        }
    }

    impl Display for Error {
        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
            match self {
                Error::Io(why) => write!(f, "An IO error occurred: {}", why),
                Error::Serde(why) => write!(f, "A se/deserialization error occurred: {}", why),
                Error::NotFound => write!(f, "Requested path not found"),
                Error::Unknown => write!(f, "An unknown error occurred"),
            }
        }
    }

    impl std::error::Error for Error {}

    fn fetch(command: &IpcCommand) -> Result<IpcResponse, Error> {
        let mut stream =
            UnixStream::connect(env::var("SOCKET_PATH").unwrap_or(DEFAULT_SOCKET.to_string()))?;

        let mut buf = serde_json::to_vec(command).unwrap();
        buf.push(0x0);

        stream.write_all(&buf)?;

        buf.clear();

        stream.read_to_end(&mut buf)?;

        Ok(serde_json::from_slice(&buf)?)
    }

    pub fn get_index(path: Option<PathBuf>) -> Result<Vec<IndexEntry>, Error> {
        match fetch(&IpcCommand::GetIndex(path))? {
            IpcResponse::Index(index) => Ok(index),
            IpcResponse::NotFound => Err(Error::NotFound),
            _ => unreachable!(),
        }
    }

    pub fn regenerate_index() -> Result<(), Error> {
        match fetch(&IpcCommand::FullIndex)? {
            IpcResponse::Success => Ok(()),
            _ => Err(Error::Unknown),
        }
    }

    pub fn shutdown_server() -> Result<(), Error> {
        match fetch(&IpcCommand::Quit)? {
            IpcResponse::Success => Ok(()),
            _ => Err(Error::Unknown),
        }
    }

    pub fn reload_config() -> Result<(), Error> {
        match fetch(&IpcCommand::Reload)? {
            IpcResponse::Success => Ok(()),
            _ => Err(Error::Unknown),
        }
    }
}