1pub mod process;
2
3#[cfg(unix)]
4mod unix;
5#[cfg(windows)]
6mod windows;
7
8#[cfg(unix)]
9use std::path::PathBuf;
10
11use anyhow::Result;
12
13#[derive(Debug, Clone)]
15pub enum DaemonAddr {
16 #[cfg(unix)]
17 Unix(PathBuf),
18 #[cfg(windows)]
19 NamedPipe(String),
20}
21
22impl DaemonAddr {
23 pub fn default_for_current_os() -> Self {
24 #[cfg(unix)]
25 {
26 Self::Unix(unix::default_socket_path())
27 }
28 #[cfg(windows)]
29 {
30 Self::NamedPipe(windows::default_pipe_name())
31 }
32 }
33
34 pub fn display(&self) -> String {
35 match self {
36 #[cfg(unix)]
37 Self::Unix(p) => p.display().to_string(),
38 #[cfg(windows)]
39 Self::NamedPipe(n) => n.clone(),
40 }
41 }
42
43 pub fn is_listening(&self) -> bool {
45 match self {
46 #[cfg(unix)]
47 Self::Unix(p) => p.exists(),
48 #[cfg(windows)]
49 Self::NamedPipe(name) => windows::pipe_exists(name),
50 }
51 }
52}
53
54pub fn cleanup(addr: &DaemonAddr) {
56 match addr {
57 #[cfg(unix)]
58 DaemonAddr::Unix(p) => {
59 if p.exists() {
60 let _ = std::fs::remove_file(p);
61 }
62 }
63 #[cfg(windows)]
64 DaemonAddr::NamedPipe(_) => {
65 }
67 }
68}
69
70#[cfg(unix)]
72pub fn bind_listener(addr: &DaemonAddr) -> Result<tokio::net::UnixListener> {
73 match addr {
74 DaemonAddr::Unix(path) => unix::bind_listener(path),
75 }
76}
77
78#[cfg(unix)]
80pub async fn connect(addr: &DaemonAddr) -> Result<tokio::net::UnixStream> {
81 match addr {
82 DaemonAddr::Unix(path) => unix::connect(path).await,
83 }
84}
85
86#[cfg(windows)]
88pub async fn connect(
89 addr: &DaemonAddr,
90) -> Result<tokio::net::windows::named_pipe::NamedPipeClient> {
91 match addr {
92 DaemonAddr::NamedPipe(name) => windows::connect(name).await,
93 }
94}
95
96#[cfg(test)]
97mod tests {
98 use super::*;
99
100 #[test]
101 fn daemon_addr_display_non_empty() {
102 let addr = DaemonAddr::default_for_current_os();
103 let display = addr.display();
104 assert!(!display.is_empty());
105 }
106
107 #[test]
108 fn cleanup_nonexistent_does_not_panic() {
109 #[cfg(unix)]
110 {
111 let addr = DaemonAddr::Unix(std::path::PathBuf::from(
112 "/tmp/lean-ctx-test-nonexistent.sock",
113 ));
114 cleanup(&addr);
115 }
116 }
117}