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 CLONE: u16 = 56;
48 pub const CLONE_DIR: u16 = 57;
49 pub const REMOVE_DIR: u16 = 58;
50 pub const OP_CANCEL: u16 = 59;
51 pub const WATCH: u16 = 60;
52 pub const UNWATCH: u16 = 61;
53 pub const WARM_OPEN: u16 = 70;
54 pub const WARM_READ: u16 = 71;
55 pub const NOTICE: u16 = 62;
56}
57
58#[derive(Clone, Debug, Default, PartialEq)]
60#[non_exhaustive]
61pub struct StatfsInfo {
62 pub block_size: u32,
63 pub blocks: u64,
64 pub blocks_free: u64,
65 pub blocks_avail: u64,
66 pub files: u64,
67 pub files_free: u64,
68 pub name_max: u32,
69}
70
71impl Client {
72 pub fn ping(&self) -> Result<()> {
74 self.unary::<Empty>(method::PING, &Empty {}).map(drop)
75 }
76
77 pub fn stat(&self, path: &str) -> Result<FileInfo> {
79 let r: StatResponse = self.unary(method::STAT, &StatRequest { path: path.into() })?;
80 r.info.ok_or_else(|| Error::Protocol("stat reply has no info".into()))
81 }
82
83 pub fn lstat(&self, path: &str) -> Result<FileInfo> {
85 let r: LstatResponse = self.unary(method::LSTAT, &LstatRequest { path: path.into() })?;
86 r.info.ok_or_else(|| Error::Protocol("lstat reply has no info".into()))
87 }
88
89 pub fn mkdir(&self, path: &str, mode: u32) -> Result<()> {
91 self
92 .unary::<Empty>(
93 method::MKDIR,
94 &MkdirRequest {
95 path: path.into(),
96 mode,
97 },
98 )
99 .map(drop)
100 }
101
102 pub fn rmdir(&self, path: &str) -> Result<()> {
104 self
105 .unary::<Empty>(method::RMDIR, &RmdirRequest { path: path.into() })
106 .map(drop)
107 }
108
109 pub fn unlink(&self, path: &str) -> Result<()> {
111 self
112 .unary::<Empty>(method::UNLINK, &UnlinkRequest { path: path.into() })
113 .map(drop)
114 }
115
116 pub fn rename(&self, from: &str, to: &str) -> Result<()> {
118 self
119 .unary::<Empty>(
120 method::RENAME,
121 &RenameRequest {
122 from: from.into(),
123 to: to.into(),
124 },
125 )
126 .map(drop)
127 }
128
129 pub fn symlink(&self, target: &str, link_path: &str) -> Result<()> {
131 self
132 .unary::<Empty>(
133 method::SYMLINK,
134 &SymlinkRequest {
135 target: target.into(),
136 link_path: link_path.into(),
137 },
138 )
139 .map(drop)
140 }
141
142 pub fn readlink(&self, path: &str) -> Result<String> {
144 let r: ReadlinkResponse = self.unary(method::READLINK, &ReadlinkRequest { path: path.into() })?;
145 Ok(r.target)
146 }
147
148 pub fn link(&self, existing: &str, new_path: &str) -> Result<()> {
150 self
151 .unary::<Empty>(
152 method::LINK,
153 &LinkRequest {
154 existing: existing.into(),
155 new_path: new_path.into(),
156 },
157 )
158 .map(drop)
159 }
160
161 pub fn chmod(&self, path: &str, mode: u32) -> Result<()> {
163 self
164 .unary::<Empty>(
165 method::CHMOD,
166 &ChmodRequest {
167 path: path.into(),
168 mode,
169 },
170 )
171 .map(drop)
172 }
173
174 pub fn truncate(&self, path: &str, size: i64) -> Result<()> {
176 self
177 .unary::<Empty>(
178 method::TRUNCATE,
179 &TruncateRequest {
180 path: path.into(),
181 size,
182 },
183 )
184 .map(drop)
185 }
186
187 pub fn statfs(&self, path: &str) -> Result<StatfsInfo> {
189 let r: StatfsResponse = self.unary(method::STATFS, &StatfsRequest { path: path.into() })?;
190 Ok(StatfsInfo {
191 block_size: r.block_size,
192 blocks: r.blocks,
193 blocks_free: r.blocks_free,
194 blocks_avail: r.blocks_avail,
195 files: r.files,
196 files_free: r.files_free,
197 name_max: r.name_max,
198 })
199 }
200
201 pub fn access(&self, path: &str, mode: u32) -> Result<()> {
203 self
204 .unary::<Empty>(
205 method::ACCESS,
206 &AccessRequest {
207 path: path.into(),
208 mode,
209 },
210 )
211 .map(drop)
212 }
213
214 pub fn remove_all(&self, path: &str) -> Result<u64> {
216 let r: RemoveAllResponse = self.unary(method::REMOVE_ALL, &RemoveAllRequest { path: path.into() })?;
217 Ok(r.removed)
218 }
219
220 pub fn warm_open(&self, path: &str) -> Result<u64> {
222 let r: WarmOpenResponse = self.unary(method::WARM_OPEN, &WarmOpenRequest { path: path.into() })?;
223 Ok(r.warm_id)
224 }
225
226 pub fn warm_read(&self, path: &str, offset: i64, length: i64) -> Result<u64> {
228 let r: WarmReadResponse = self.unary(
229 method::WARM_READ,
230 &WarmReadRequest {
231 path: path.into(),
232 offset,
233 length,
234 },
235 )?;
236 Ok(r.warm_id)
237 }
238}
239
240impl File {
241 pub fn flush(&self) -> Result<()> {
243 let st = self.state()?;
244 self
245 .unary::<Empty>(method::FLUSH, &FlushRequest { handle: st.handle })
246 .map(drop)
247 }
248
249 pub fn truncate(&self, size: i64) -> Result<()> {
251 let st = self.state()?;
252 self
253 .unary::<Empty>(
254 method::FTRUNCATE,
255 &FtruncateRequest {
256 handle: st.handle,
257 size,
258 },
259 )
260 .map(drop)
261 }
262
263 pub fn stat(&self) -> Result<FileInfo> {
265 let st = self.state()?;
266 let r: FstatResponse = self.unary(method::FSTAT, &FstatRequest { handle: st.handle })?;
267 r.info.ok_or_else(|| Error::Protocol("fstat reply has no info".into()))
268 }
269}