use std::io;
#[allow(unused)]
use std::{convert::TryInto, ffi::OsStr};
use crate::{
channel::ChannelSender,
ll::{fuse_abi::fuse_notify_code as notify_code, notify::Notification},
reply::ReplySender,
};
#[derive(Clone)]
pub struct PollHandle {
handle: u64,
notifier: Notifier,
}
impl PollHandle {
pub(crate) fn new(cs: ChannelSender, kh: u64) -> Self {
Self {
handle: kh,
notifier: Notifier::new(cs),
}
}
pub fn notify(self) -> io::Result<()> {
self.notifier.poll(self.handle)
}
}
impl From<PollHandle> for u64 {
fn from(value: PollHandle) -> Self {
value.handle
}
}
impl std::fmt::Debug for PollHandle {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_tuple("PollHandle").field(&self.handle).finish()
}
}
#[derive(Debug, Clone)]
pub struct Notifier(ChannelSender);
impl Notifier {
pub(crate) fn new(cs: ChannelSender) -> Self {
Self(cs)
}
pub fn poll(&self, kh: u64) -> io::Result<()> {
let notif = Notification::new_poll(kh);
self.send(notify_code::FUSE_POLL, ¬if)
}
pub fn inval_entry(&self, parent: u64, name: &OsStr) -> io::Result<()> {
let notif = Notification::new_inval_entry(parent, name).map_err(Self::too_big_err)?;
self.send_inval(notify_code::FUSE_NOTIFY_INVAL_ENTRY, ¬if)
}
pub fn inval_inode(&self, ino: u64, offset: i64, len: i64) -> io::Result<()> {
let notif = Notification::new_inval_inode(ino, offset, len);
self.send_inval(notify_code::FUSE_NOTIFY_INVAL_INODE, ¬if)
}
pub fn store(&self, ino: u64, offset: u64, data: &[u8]) -> io::Result<()> {
let notif = Notification::new_store(ino, offset, data).map_err(Self::too_big_err)?;
self.send_inval(notify_code::FUSE_NOTIFY_STORE, ¬if)
}
pub fn delete(&self, parent: u64, child: u64, name: &OsStr) -> io::Result<()> {
let notif = Notification::new_delete(parent, child, name).map_err(Self::too_big_err)?;
self.send_inval(notify_code::FUSE_NOTIFY_DELETE, ¬if)
}
#[allow(unused)]
fn send_inval(&self, code: notify_code, notification: &Notification<'_>) -> io::Result<()> {
match self.send(code, notification) {
Err(e) if e.kind() == io::ErrorKind::NotFound => Ok(()),
x => x,
}
}
fn send(&self, code: notify_code, notification: &Notification<'_>) -> io::Result<()> {
notification
.with_iovec(code, |iov| self.0.send(iov))
.map_err(Self::too_big_err)?
}
fn too_big_err(tfie: std::num::TryFromIntError) -> io::Error {
io::Error::new(io::ErrorKind::Other, format!("Data too large: {tfie:?}"))
}
}