diff options
Diffstat (limited to 'src/ops/traits.rs')
| -rw-r--r-- | src/ops/traits.rs | 190 |
1 files changed, 190 insertions, 0 deletions
diff --git a/src/ops/traits.rs b/src/ops/traits.rs new file mode 100644 index 0000000..8bb59e4 --- /dev/null +++ b/src/ops/traits.rs @@ -0,0 +1,190 @@ +use crate::{ + io::{Entry, FsInfo, Interruptible, Known, Stat}, + Done, Operation, Reply, Ttl, +}; + +pub use super::{ + dir::{ReplyEntries, ReplyFound}, + entry::ReplyStat, + global::ReplyFsInfo, + open::{ReplyOpen, ReplyPermissionDenied}, + rw::ReplyAll, + xattr::ReplyXattrRead, +}; + +use super::make_entry; +use bytes::BufMut; +use std::{ffi::OsStr, os::unix::ffi::OsStrExt}; + +pub trait ReplyOk<'o>: Operation<'o> { + fn ok(reply: Reply<'o, Self>) -> Done<'o> { + reply.empty() + } +} + +pub trait ReplyKnown<'o>: Operation<'o> { + fn known(reply: Reply<'o, Self>, entry: impl Known, ttl: Ttl) -> Done<'o> { + let (attrs, attrs_ttl) = entry.inode().attrs(); + let attrs = attrs.finish(entry.inode()); + + let done = reply.single(&make_entry((entry.inode().ino(), ttl), (attrs, attrs_ttl))); + entry.unveil(); + + done + } +} + +pub trait ReplyNotFound<'o>: Operation<'o> { + fn not_found(reply: Reply<'o, Self>) -> Done<'o>; +} + +pub trait ReplyBuffered<'o, B>: Operation<'o> +where + B: BufMut + AsRef<[u8]>, +{ + type Buffered: Operation<'o>; + fn buffered(reply: Reply<'o, Self>, buffer: B) -> Reply<'o, Self::Buffered>; +} + +pub trait ReplyGather<'o>: Operation<'o> { + fn blob(reply: Reply<'o, Self>, blob: impl AsRef<OsStr>) -> Done<'o> { + Self::slice(reply, blob.as_ref().as_bytes()) + } + + fn slice(reply: Reply<'o, Self>, slice: impl AsRef<[u8]>) -> Done<'o> { + Self::gather(reply, &[slice.as_ref()]) + } + + fn gather(reply: Reply<'o, Self>, fragments: &[&[u8]]) -> Done<'o> { + reply.chain(crate::util::OutputChain::tail(fragments)) + } +} + +impl<'o, O: Operation<'o>> Reply<'o, O> { + pub fn ok(self) -> Done<'o> + where + O: ReplyOk<'o>, + { + O::ok(self) + } + + pub fn known(self, entry: impl Known, ttl: Ttl) -> Done<'o> + where + O: ReplyKnown<'o>, + { + O::known(self, entry, ttl) + } + + pub fn not_found(self) -> Done<'o> + where + O: ReplyNotFound<'o>, + { + O::not_found(self) + } + + pub fn permission_denied(self) -> Done<'o> + where + O: ReplyPermissionDenied<'o>, + { + O::permission_denied(self) + } + + pub fn stat(self, inode: &impl Stat) -> Done<'o> + where + O: ReplyStat<'o>, + { + O::stat(self, inode) + } + + pub fn ok_with_handle(self, handle: u64) -> Done<'o> + where + O: ReplyOpen<'o>, + { + O::ok_with_handle(self, handle) + } + + pub fn force_direct_io(&mut self) + where + O: ReplyOpen<'o>, + { + O::force_direct_io(self) + } + + pub fn not_found_for(self, ttl: Ttl) -> Done<'o> + where + O: ReplyFound<'o>, + { + O::not_found_for(self, ttl) + } + + pub fn entry(self, entry: Entry<impl Known>) -> Interruptible<'o, O, ()> + where + O: ReplyEntries<'o>, + { + O::entry(self, entry) + } + + pub fn end(self) -> Done<'o> + where + O: ReplyEntries<'o>, + { + O::end(self) + } + + pub fn all(self) -> Done<'o> + where + O: ReplyAll<'o>, + { + O::all(self) + } + + pub fn buffered<B>(self, buffer: B) -> Reply<'o, O::Buffered> + where + O: ReplyBuffered<'o, B>, + B: BufMut + AsRef<[u8]>, + { + O::buffered(self, buffer) + } + + pub fn blob(self, blob: impl AsRef<OsStr>) -> Done<'o> + where + O: ReplyGather<'o>, + { + O::blob(self, blob) + } + + pub fn slice(self, slice: impl AsRef<[u8]>) -> Done<'o> + where + O: ReplyGather<'o>, + { + O::slice(self, slice) + } + + pub fn gather(self, fragments: &[&[u8]]) -> Done<'o> + where + O: ReplyGather<'o>, + { + O::gather(self, fragments) + } + + pub fn info(self, info: &FsInfo) -> Done<'o> + where + O: ReplyFsInfo<'o>, + { + O::info(self, info) + } + + pub fn requires_size(self, size: u32) -> Done<'o> + where + O: ReplyXattrRead<'o>, + { + O::requires_size(self, size) + } + + pub fn buffer_too_small(self) -> Done<'o> + where + O: ReplyXattrRead<'o>, + { + O::buffer_too_small(self) + } +} |
