1#[cfg(unix)]
4pub use unix_impl::Client;
5
6#[cfg(not(unix))]
7pub use stub_impl::Client;
8
9#[cfg(not(unix))]
13mod stub_impl {
14 use std::path::Path;
15
16 use crate::error::{Error, Result};
17 use crate::proto::{Request, Response};
18
19 pub struct Client {
21 _private: (),
22 }
23
24 impl Client {
25 pub fn try_connect(_socket: &Path) -> Option<Client> {
27 None
28 }
29
30 pub fn request(&mut self, _req: &Request) -> Result<Response> {
32 Err(Error::other(
33 "greplm daemon is not supported on this platform",
34 ))
35 }
36
37 pub fn request_routed(
39 &mut self,
40 _root: &std::path::Path,
41 _req: &Request,
42 ) -> Result<Response> {
43 Err(Error::other(
44 "greplm daemon is not supported on this platform",
45 ))
46 }
47 }
48}
49
50#[cfg(unix)]
51mod unix_impl {
52 use std::io::{BufRead, BufReader, Write};
53 use std::os::unix::net::UnixStream;
54 use std::path::Path;
55
56 use crate::error::{Error, Result};
57 use crate::proto::{Request, Response, RoutedRequest};
58
59 pub struct Client {
61 reader: BufReader<UnixStream>,
62 writer: UnixStream,
63 }
64
65 impl Client {
66 pub fn try_connect(socket: &Path) -> Option<Client> {
69 let stream = UnixStream::connect(socket).ok()?;
70 let reader = BufReader::new(stream.try_clone().ok()?);
71 Some(Client {
72 reader,
73 writer: stream,
74 })
75 }
76
77 pub fn request(&mut self, req: &Request) -> Result<Response> {
79 self.round_trip(req)
80 }
81
82 pub fn request_routed(&mut self, root: &Path, req: &Request) -> Result<Response> {
85 let routed = RoutedRequest {
86 root: root.to_path_buf(),
87 req: req.clone(),
88 };
89 self.round_trip(&routed)
90 }
91
92 fn round_trip<T: serde::Serialize>(&mut self, value: &T) -> Result<Response> {
93 let mut bytes = serde_json::to_vec(value)?;
94 bytes.push(b'\n');
95 self.writer.write_all(&bytes).map_err(Error::PlainIo)?;
96 self.writer.flush().map_err(Error::PlainIo)?;
97 let mut line = String::new();
98 let n = self.reader.read_line(&mut line).map_err(Error::PlainIo)?;
99 if n == 0 {
100 return Err(Error::other("daemon closed connection"));
101 }
102 let resp: Response = serde_json::from_str(line.trim())?;
103 Ok(resp)
104 }
105 }
106}