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