use std::{fs::DirBuilder, path::PathBuf};
use anyhow::Result;
use tokio::{
net::UnixListener,
sync::mpsc::{UnboundedReceiver, UnboundedSender},
};
use tokio_stream::wrappers::UnixListenerStream;
use crate::IpcStream;
pub const IPC_DIR: &str = "/tmp/lazybar-ipc/";
pub fn init(enabled: bool, bar_name: &str) -> (Result<IpcStream>, String) {
let mut final_name = bar_name.to_string();
(
if enabled && DirBuilder::new().recursive(true).create(IPC_DIR).is_ok()
{
let (path, idx) = find_path(bar_name);
if idx > 0 {
final_name = format!("{bar_name}({idx})");
}
#[allow(clippy::option_if_let_else)]
if let Ok(listener) = UnixListener::bind(path) {
let stream = UnixListenerStream::new(listener);
Ok(Box::pin(stream))
} else {
Ok(Box::pin(tokio_stream::pending()))
}
} else {
Ok(Box::pin(tokio_stream::pending()))
},
final_name,
)
}
fn find_path(bar_name: &str) -> (PathBuf, i32) {
let mut fmt = format!("{IPC_DIR}{bar_name}");
let mut path = PathBuf::from(fmt);
let mut idx = 0;
while path.exists() {
idx += 1;
fmt = format!("{IPC_DIR}{bar_name}({idx})");
path = PathBuf::from(fmt.as_str());
}
(path, idx)
}
#[derive(Debug)]
pub struct ChannelEndpoint<T, U> {
pub send: UnboundedSender<T>,
pub recv: UnboundedReceiver<U>,
}
impl<T, U> ChannelEndpoint<T, U> {
#[must_use]
pub const fn new(
send: UnboundedSender<T>,
recv: UnboundedReceiver<U>,
) -> Self {
Self { send, recv }
}
}
impl<T, U> AsRef<UnboundedSender<T>> for ChannelEndpoint<T, U> {
fn as_ref(&self) -> &UnboundedSender<T> {
&self.send
}
}
impl<T, U> AsMut<UnboundedSender<T>> for ChannelEndpoint<T, U> {
fn as_mut(&mut self) -> &mut UnboundedSender<T> {
&mut self.send
}
}
impl<T, U> AsRef<UnboundedReceiver<U>> for ChannelEndpoint<T, U> {
fn as_ref(&self) -> &UnboundedReceiver<U> {
&self.recv
}
}
impl<T, U> AsMut<UnboundedReceiver<U>> for ChannelEndpoint<T, U> {
fn as_mut(&mut self) -> &mut UnboundedReceiver<U> {
&mut self.recv
}
}