1use crate::client::Client;
4use crate::error::{Error, Result};
5use crate::file::File;
6use crate::wire::*;
7
8pub mod method {
10 pub const HELLO: u16 = 1;
11 pub const PING: u16 = 2;
12 pub const OPEN: u16 = 10;
13 pub const CLOSE: u16 = 11;
14 pub const READ: u16 = 12;
15 pub const WRITE: u16 = 13;
16 pub const READ_AT: u16 = 14;
17 pub const WRITE_AT: u16 = 15;
18 pub const SEEK: u16 = 16;
19 pub const FSYNC: u16 = 17;
20 pub const FLUSH: u16 = 18;
21 pub const FTRUNCATE: u16 = 19;
22 pub const STAT: u16 = 20;
23 pub const LSTAT: u16 = 21;
24 pub const FSTAT: u16 = 22;
25 pub const MKDIR: u16 = 23;
26 pub const RMDIR: u16 = 24;
27 pub const UNLINK: u16 = 25;
28 pub const RENAME: u16 = 26;
29 pub const SYMLINK: u16 = 27;
30 pub const READLINK: u16 = 28;
31 pub const LINK: u16 = 29;
32 pub const CHMOD: u16 = 30;
33 pub const UTIMENS: u16 = 31;
34 pub const TRUNCATE: u16 = 32;
35 pub const STATFS: u16 = 33;
36 pub const ACCESS: u16 = 34;
37 pub const OPENDIR: u16 = 40;
38 pub const READDIR: u16 = 41;
39 pub const CLOSEDIR: u16 = 42;
40 pub const LS: u16 = 43;
41 pub const STAT_BATCH: u16 = 50;
42 pub const READ_BATCH: u16 = 51;
43 pub const WRITE_BATCH: u16 = 52;
44 pub const READ_FILE: u16 = 53;
45 pub const WRITE_FILE: u16 = 54;
46 pub const REMOVE_ALL: u16 = 55;
47 pub const WATCH: u16 = 60;
48 pub const UNWATCH: u16 = 61;
49 pub const WARM_OPEN: u16 = 70;
50 pub const WARM_READ: u16 = 71;
51 pub const NOTICE: u16 = 62;
52}
53
54#[derive(Clone, Debug, Default, PartialEq)]
56#[non_exhaustive]
57pub struct StatfsInfo {
58 pub block_size: u32,
59 pub blocks: u64,
60 pub blocks_free: u64,
61 pub blocks_avail: u64,
62 pub files: u64,
63 pub files_free: u64,
64 pub name_max: u32,
65}
66
67impl Client {
68 pub fn ping(&self) -> Result<()> {
70 self.unary::<Empty>(method::PING, &Empty {}).map(drop)
71 }
72
73 pub fn stat(&self, path: &str) -> Result<FileInfo> {
75 let r: StatResponse = self.unary(method::STAT, &StatRequest { path: path.into() })?;
76 r.info.ok_or_else(|| Error::Protocol("stat reply has no info".into()))
77 }
78
79 pub fn lstat(&self, path: &str) -> Result<FileInfo> {
81 let r: LstatResponse = self.unary(method::LSTAT, &LstatRequest { path: path.into() })?;
82 r.info.ok_or_else(|| Error::Protocol("lstat reply has no info".into()))
83 }
84
85 pub fn mkdir(&self, path: &str, mode: u32) -> Result<()> {
87 self
88 .unary::<Empty>(
89 method::MKDIR,
90 &MkdirRequest {
91 path: path.into(),
92 mode,
93 },
94 )
95 .map(drop)
96 }
97
98 pub fn rmdir(&self, path: &str) -> Result<()> {
100 self
101 .unary::<Empty>(method::RMDIR, &RmdirRequest { path: path.into() })
102 .map(drop)
103 }
104
105 pub fn unlink(&self, path: &str) -> Result<()> {
107 self
108 .unary::<Empty>(method::UNLINK, &UnlinkRequest { path: path.into() })
109 .map(drop)
110 }
111
112 pub fn rename(&self, from: &str, to: &str) -> Result<()> {
114 self
115 .unary::<Empty>(
116 method::RENAME,
117 &RenameRequest {
118 from: from.into(),
119 to: to.into(),
120 },
121 )
122 .map(drop)
123 }
124
125 pub fn symlink(&self, target: &str, link_path: &str) -> Result<()> {
127 self
128 .unary::<Empty>(
129 method::SYMLINK,
130 &SymlinkRequest {
131 target: target.into(),
132 link_path: link_path.into(),
133 },
134 )
135 .map(drop)
136 }
137
138 pub fn readlink(&self, path: &str) -> Result<String> {
140 let r: ReadlinkResponse = self.unary(method::READLINK, &ReadlinkRequest { path: path.into() })?;
141 Ok(r.target)
142 }
143
144 pub fn link(&self, existing: &str, new_path: &str) -> Result<()> {
146 self
147 .unary::<Empty>(
148 method::LINK,
149 &LinkRequest {
150 existing: existing.into(),
151 new_path: new_path.into(),
152 },
153 )
154 .map(drop)
155 }
156
157 pub fn chmod(&self, path: &str, mode: u32) -> Result<()> {
159 self
160 .unary::<Empty>(
161 method::CHMOD,
162 &ChmodRequest {
163 path: path.into(),
164 mode,
165 },
166 )
167 .map(drop)
168 }
169
170 pub fn truncate(&self, path: &str, size: i64) -> Result<()> {
172 self
173 .unary::<Empty>(
174 method::TRUNCATE,
175 &TruncateRequest {
176 path: path.into(),
177 size,
178 },
179 )
180 .map(drop)
181 }
182
183 pub fn statfs(&self, path: &str) -> Result<StatfsInfo> {
185 let r: StatfsResponse = self.unary(method::STATFS, &StatfsRequest { path: path.into() })?;
186 Ok(StatfsInfo {
187 block_size: r.block_size,
188 blocks: r.blocks,
189 blocks_free: r.blocks_free,
190 blocks_avail: r.blocks_avail,
191 files: r.files,
192 files_free: r.files_free,
193 name_max: r.name_max,
194 })
195 }
196
197 pub fn access(&self, path: &str, mode: u32) -> Result<()> {
199 self
200 .unary::<Empty>(
201 method::ACCESS,
202 &AccessRequest {
203 path: path.into(),
204 mode,
205 },
206 )
207 .map(drop)
208 }
209
210 pub fn remove_all(&self, path: &str) -> Result<u64> {
212 let r: RemoveAllResponse = self.unary(method::REMOVE_ALL, &RemoveAllRequest { path: path.into() })?;
213 Ok(r.removed)
214 }
215
216 pub fn warm_open(&self, path: &str) -> Result<u64> {
218 let r: WarmOpenResponse = self.unary(method::WARM_OPEN, &WarmOpenRequest { path: path.into() })?;
219 Ok(r.warm_id)
220 }
221
222 pub fn warm_read(&self, path: &str, offset: i64, length: i64) -> Result<u64> {
224 let r: WarmReadResponse = self.unary(
225 method::WARM_READ,
226 &WarmReadRequest {
227 path: path.into(),
228 offset,
229 length,
230 },
231 )?;
232 Ok(r.warm_id)
233 }
234}
235
236impl File {
237 pub fn flush(&self) -> Result<()> {
239 let st = self.state()?;
240 self
241 .unary::<Empty>(method::FLUSH, &FlushRequest { handle: st.handle })
242 .map(drop)
243 }
244
245 pub fn truncate(&self, size: i64) -> Result<()> {
247 let st = self.state()?;
248 self
249 .unary::<Empty>(
250 method::FTRUNCATE,
251 &FtruncateRequest {
252 handle: st.handle,
253 size,
254 },
255 )
256 .map(drop)
257 }
258
259 pub fn stat(&self) -> Result<FileInfo> {
261 let st = self.state()?;
262 let r: FstatResponse = self.unary(method::FSTAT, &FstatRequest { handle: st.handle })?;
263 r.info.ok_or_else(|| Error::Protocol("fstat reply has no info".into()))
264 }
265}