hyperdb_api_core/client/
sync_stream.rs1use std::io::{self, Read, Write};
11use std::net::TcpStream;
12
13#[cfg(unix)]
14use std::os::unix::net::UnixStream;
15
16#[cfg(windows)]
17use std::fs::File;
18
19#[derive(Debug)]
25pub enum SyncStream {
26 Tcp(TcpStream),
28
29 #[cfg(unix)]
31 Unix(UnixStream),
32
33 #[cfg(windows)]
35 NamedPipe(File),
36}
37
38impl SyncStream {
39 #[must_use]
41 pub fn tcp(stream: TcpStream) -> Self {
42 SyncStream::Tcp(stream)
43 }
44
45 #[cfg(unix)]
47 #[must_use]
48 pub fn unix(stream: UnixStream) -> Self {
49 SyncStream::Unix(stream)
50 }
51
52 #[must_use]
54 pub fn is_tcp(&self) -> bool {
55 matches!(self, SyncStream::Tcp(_))
56 }
57
58 #[cfg(unix)]
60 #[must_use]
61 pub fn is_unix(&self) -> bool {
62 matches!(self, SyncStream::Unix(_))
63 }
64
65 #[cfg(windows)]
67 pub fn named_pipe(file: File) -> Self {
68 SyncStream::NamedPipe(file)
69 }
70
71 #[cfg(windows)]
73 pub fn is_named_pipe(&self) -> bool {
74 matches!(self, SyncStream::NamedPipe(_))
75 }
76
77 pub fn set_nodelay(&self, nodelay: bool) -> io::Result<()> {
86 match self {
87 SyncStream::Tcp(stream) => stream.set_nodelay(nodelay),
88 #[cfg(unix)]
89 SyncStream::Unix(_) => Ok(()), #[cfg(windows)]
91 SyncStream::NamedPipe(_) => Ok(()), }
93 }
94
95 pub fn set_read_timeout(&self, dur: Option<std::time::Duration>) -> io::Result<()> {
103 match self {
104 SyncStream::Tcp(stream) => stream.set_read_timeout(dur),
105 #[cfg(unix)]
106 SyncStream::Unix(stream) => stream.set_read_timeout(dur),
107 #[cfg(windows)]
108 SyncStream::NamedPipe(_) => Ok(()), }
110 }
111
112 pub fn set_write_timeout(&self, dur: Option<std::time::Duration>) -> io::Result<()> {
120 match self {
121 SyncStream::Tcp(stream) => stream.set_write_timeout(dur),
122 #[cfg(unix)]
123 SyncStream::Unix(stream) => stream.set_write_timeout(dur),
124 #[cfg(windows)]
125 SyncStream::NamedPipe(_) => Ok(()), }
127 }
128
129 #[must_use]
131 pub fn local_addr_string(&self) -> String {
132 match self {
133 SyncStream::Tcp(stream) => stream
134 .local_addr()
135 .map_or_else(|_| "unknown".to_string(), |a| a.to_string()),
136 #[cfg(unix)]
137 SyncStream::Unix(stream) => stream
138 .local_addr()
139 .ok()
140 .and_then(|a| a.as_pathname().map(|p| p.display().to_string()))
141 .unwrap_or_else(|| "unix-socket".to_string()),
142 #[cfg(windows)]
143 SyncStream::NamedPipe(_) => "named-pipe".to_string(),
144 }
145 }
146
147 #[must_use]
149 pub fn peer_addr_string(&self) -> String {
150 match self {
151 SyncStream::Tcp(stream) => stream
152 .peer_addr()
153 .map_or_else(|_| "unknown".to_string(), |a| a.to_string()),
154 #[cfg(unix)]
155 SyncStream::Unix(stream) => stream
156 .peer_addr()
157 .ok()
158 .and_then(|a| a.as_pathname().map(|p| p.display().to_string()))
159 .unwrap_or_else(|| "unix-socket".to_string()),
160 #[cfg(windows)]
161 SyncStream::NamedPipe(_) => "named-pipe".to_string(),
162 }
163 }
164
165 pub fn try_clone(&self) -> io::Result<Self> {
173 match self {
174 SyncStream::Tcp(stream) => Ok(SyncStream::Tcp(stream.try_clone()?)),
175 #[cfg(unix)]
176 SyncStream::Unix(stream) => Ok(SyncStream::Unix(stream.try_clone()?)),
177 #[cfg(windows)]
178 SyncStream::NamedPipe(file) => Ok(SyncStream::NamedPipe(file.try_clone()?)),
179 }
180 }
181}
182
183impl Read for SyncStream {
184 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
185 match self {
186 SyncStream::Tcp(stream) => stream.read(buf),
187 #[cfg(unix)]
188 SyncStream::Unix(stream) => stream.read(buf),
189 #[cfg(windows)]
190 SyncStream::NamedPipe(file) => file.read(buf),
191 }
192 }
193}
194
195impl Write for SyncStream {
196 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
197 match self {
198 SyncStream::Tcp(stream) => stream.write(buf),
199 #[cfg(unix)]
200 SyncStream::Unix(stream) => stream.write(buf),
201 #[cfg(windows)]
202 SyncStream::NamedPipe(file) => file.write(buf),
203 }
204 }
205
206 fn flush(&mut self) -> io::Result<()> {
207 match self {
208 SyncStream::Tcp(stream) => stream.flush(),
209 #[cfg(unix)]
210 SyncStream::Unix(stream) => stream.flush(),
211 #[cfg(windows)]
212 SyncStream::NamedPipe(file) => file.flush(),
213 }
214 }
215}
216
217#[cfg(test)]
218mod tests {
219 #[expect(
220 clippy::assertions_on_constants,
221 reason = "compile-time invariant check kept as an assert for readability at the call site"
222 )]
223 #[test]
224 fn test_sync_stream_variants_exist() {
225 assert!(true);
228 }
229}