1use crate::client::Slot;
2use crate::error::{Error, Result};
3use crate::wire::*;
4use std::sync::{Arc, Mutex, MutexGuard};
5
6pub(crate) struct State {
7 pub(crate) handle: u64,
8 closed: bool,
9}
10
11pub struct Dir {
13 slot: Arc<Slot>,
14 epoch: u64,
15 st: Mutex<State>,
16}
17
18impl Dir {
19 pub(crate) fn new(slot: Arc<Slot>, handle: u64, epoch: u64) -> Dir {
20 Dir {
21 slot,
22 epoch,
23 st: Mutex::new(State { handle, closed: false }),
24 }
25 }
26
27 pub(crate) fn state(&self) -> Result<MutexGuard<'_, State>> {
28 let st = self.st.lock().unwrap_or_else(|e| e.into_inner());
29 if st.closed {
30 return Err(Error::server("EBADF", "directory is closed"));
31 }
32 Ok(st)
33 }
34
35 pub(crate) fn unary<R: prost::Message + Default>(&self, m: u16, req: &impl prost::Message) -> Result<R> {
36 Ok(self.slot.run(Some(self.epoch), |c| c.call_msg::<R>(m, req, &[]))?.0 .0)
37 }
38
39 pub fn readdir(&self, max: u32) -> Result<(Vec<DirEntry>, bool)> {
41 let st = self.state()?;
42 let r: ReaddirResponse = self.unary(
43 method::READDIR,
44 &ReaddirRequest {
45 handle: st.handle,
46 max_entries: max,
47 },
48 )?;
49 Ok((r.entries, r.eof))
50 }
51
52 pub fn close(&self) -> Result<()> {
54 let mut st = self.state()?;
55 st.closed = true;
56 self
57 .unary::<Empty>(method::CLOSEDIR, &ClosedirRequest { handle: st.handle })
58 .map(drop)
59 }
60}
61
62impl Drop for Dir {
63 fn drop(&mut self) {
64 let (closed, handle) = {
65 let st = self.st.get_mut().unwrap_or_else(|e| e.into_inner());
66 (st.closed, st.handle)
67 };
68 if !closed {
69 let _ = self.unary::<Empty>(method::CLOSEDIR, &ClosedirRequest { handle });
70 }
71 }
72}