#![allow(dead_code)]
use anyhow::{Context, Result};
use std::path::Path;
pub use interprocess::local_socket::tokio::Stream as TokioStream;
pub use interprocess::local_socket::{ListenerOptions, Name, Stream as SyncStream};
#[allow(unused_imports)]
pub use interprocess::local_socket::tokio::Listener as TokioListener;
pub mod prelude {
pub use interprocess::local_socket::traits::tokio::{Listener as _, Stream as _};
pub use interprocess::local_socket::traits::{Listener as _, Stream as _};
}
pub fn socket_name(path: &Path) -> Result<Name<'static>> {
#[cfg(unix)]
{
use interprocess::local_socket::{GenericFilePath, ToFsName};
path.to_fs_name::<GenericFilePath>()
.with_context(|| format!("converting {} to local-socket name", path.display()))
.map(|n| n.into_owned())
}
#[cfg(windows)]
{
use interprocess::local_socket::{GenericNamespaced, ToNsName};
let hash = blake3::hash(path.as_os_str().as_encoded_bytes());
let short = &hash.to_hex()[..16];
let pipe_name = format!("kache-daemon-{short}");
pipe_name
.to_ns_name::<GenericNamespaced>()
.with_context(|| format!("converting {} to named pipe name", path.display()))
.map(|n| n.into_owned())
}
}
pub fn is_reachable(path: &Path) -> bool {
use interprocess::local_socket::traits::Stream as _;
let Ok(name) = socket_name(path) else {
return false;
};
SyncStream::connect(name).is_ok()
}
pub fn is_peer_disconnect(e: &std::io::Error) -> bool {
use std::io::ErrorKind::*;
matches!(
e.kind(),
BrokenPipe | ConnectionReset | ConnectionAborted | UnexpectedEof
) || e.raw_os_error() == Some(32) }