|
@@ -1 +1,268 @@
|
|
|
+use crate::msg::*;
|
|
|
|
|
|
+use btlib::{bterr, BlockMeta, Result};
|
|
|
+use btmsg::{DeserCallback, Transmitter};
|
|
|
+
|
|
|
+use core::future::{ready, Future, Ready};
|
|
|
+use paste::paste;
|
|
|
+
|
|
|
+macro_rules! extractor {
|
|
|
+ ($variant:ident) => {
|
|
|
+ paste! {
|
|
|
+ [<Extract $variant>]
|
|
|
+ }
|
|
|
+ };
|
|
|
+}
|
|
|
+
|
|
|
+macro_rules! reply {
|
|
|
+ ($variant:ident) => {
|
|
|
+ paste! {
|
|
|
+ [<$variant Reply>]
|
|
|
+ }
|
|
|
+ };
|
|
|
+}
|
|
|
+
|
|
|
+macro_rules! extractor_callback {
|
|
|
+ ($variant:ident) => {
|
|
|
+ paste! {
|
|
|
+ struct [<Extract $variant>];
|
|
|
+
|
|
|
+ impl DeserCallback for extractor!($variant) {
|
|
|
+ type Arg<'de> = FsReply<'de>;
|
|
|
+ type Return = Result<reply!($variant)>;
|
|
|
+ type CallFut<'de> = Ready<Self::Return>;
|
|
|
+ fn call<'de>(&'de mut self, arg: Self::Arg<'de>) -> Self::CallFut<'de> {
|
|
|
+ let result = if let FsReply::$variant(value) = arg {
|
|
|
+ Ok(value)
|
|
|
+ } else {
|
|
|
+ Err(bterr!("wrong message type sent as reply"))
|
|
|
+ };
|
|
|
+ ready(result)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ };
|
|
|
+}
|
|
|
+
|
|
|
+extractor_callback!(Lookup);
|
|
|
+extractor_callback!(Create);
|
|
|
+extractor_callback!(Open);
|
|
|
+extractor_callback!(Write);
|
|
|
+extractor_callback!(Link);
|
|
|
+
|
|
|
+struct AckCallback;
|
|
|
+
|
|
|
+impl DeserCallback for AckCallback {
|
|
|
+ type Arg<'de> = FsReply<'de>;
|
|
|
+ type Return = Result<()>;
|
|
|
+ type CallFut<'de> = Ready<Self::Return>;
|
|
|
+ fn call<'de>(&'de mut self, arg: Self::Arg<'de>) -> Self::CallFut<'de> {
|
|
|
+ let result = if let FsReply::Ack(_) = arg {
|
|
|
+ Ok(())
|
|
|
+ } else {
|
|
|
+ Err(bterr!("wrong message type sent as reply"))
|
|
|
+ };
|
|
|
+ ready(result)
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+struct ExtractReadMeta;
|
|
|
+
|
|
|
+impl DeserCallback for ExtractReadMeta {
|
|
|
+ type Arg<'de> = FsReply<'de>;
|
|
|
+ type Return = Result<BlockMeta>;
|
|
|
+ type CallFut<'de> = Ready<Self::Return>;
|
|
|
+ fn call<'de>(&'de mut self, arg: Self::Arg<'de>) -> Self::CallFut<'de> {
|
|
|
+ let result = if let FsReply::ReadMeta(value) = arg {
|
|
|
+ Ok(value)
|
|
|
+ } else {
|
|
|
+ Err(bterr!("wrong message type sent as reply"))
|
|
|
+ };
|
|
|
+ ready(result)
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+struct ExtractRead<F> {
|
|
|
+ callback: Option<F>,
|
|
|
+}
|
|
|
+
|
|
|
+impl<F> ExtractRead<F> {
|
|
|
+ fn new(callback: F) -> Self {
|
|
|
+ Self {
|
|
|
+ callback: Some(callback),
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+impl<R, Fut, F> DeserCallback for ExtractRead<F>
|
|
|
+where
|
|
|
+ F: 'static + Send + FnOnce(ReadReply<'_>) -> Fut,
|
|
|
+ Fut: Send + Future<Output = R>,
|
|
|
+{
|
|
|
+ type Arg<'de> = FsReply<'de> where F: 'de;
|
|
|
+ type Return = Result<R>;
|
|
|
+ type CallFut<'de> = impl 'de + Send + Future<Output = Self::Return>;
|
|
|
+ fn call<'de>(&'de mut self, arg: Self::Arg<'de>) -> Self::CallFut<'de> {
|
|
|
+ let callback = self.callback.take().unwrap();
|
|
|
+ async move {
|
|
|
+ if let FsReply::Read(reply) = arg {
|
|
|
+ Ok(callback(reply).await)
|
|
|
+ } else {
|
|
|
+ Err(bterr!("wrong variant sent in reply to Read message"))
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+pub struct FsClient<T> {
|
|
|
+ tx: T,
|
|
|
+}
|
|
|
+
|
|
|
+impl<T> FsClient<T> {
|
|
|
+ pub fn new(tx: T) -> Self {
|
|
|
+ Self { tx }
|
|
|
+ }
|
|
|
+
|
|
|
+ pub fn into_inner(self) -> T {
|
|
|
+ self.tx
|
|
|
+ }
|
|
|
+
|
|
|
+ pub fn get_ref(&self) -> &T {
|
|
|
+ &self.tx
|
|
|
+ }
|
|
|
+
|
|
|
+ pub fn get_mut(&mut self) -> &mut T {
|
|
|
+ &mut self.tx
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+impl<T: Transmitter> FsClient<T> {
|
|
|
+ /// Lookup up the given name under the given inode.
|
|
|
+ pub async fn lookup(&self, parent: Inode, name: &str) -> Result<LookupReply> {
|
|
|
+ let msg = FsMsg::Lookup(Lookup { parent, name });
|
|
|
+ self.tx.call(msg, extractor!(Lookup)).await?
|
|
|
+ }
|
|
|
+
|
|
|
+ pub async fn create(
|
|
|
+ &self,
|
|
|
+ parent: Inode,
|
|
|
+ name: &str,
|
|
|
+ flags: u32,
|
|
|
+ mode: u32,
|
|
|
+ umask: u32,
|
|
|
+ ) -> Result<CreateReply> {
|
|
|
+ let msg = FsMsg::Create(Create {
|
|
|
+ parent,
|
|
|
+ name,
|
|
|
+ flags,
|
|
|
+ mode,
|
|
|
+ umask,
|
|
|
+ });
|
|
|
+ self.tx.call(msg, extractor!(Create)).await?
|
|
|
+ }
|
|
|
+
|
|
|
+ pub async fn open(&self, inode: Inode, flags: u32) -> Result<OpenReply> {
|
|
|
+ let msg = FsMsg::Open(Open { inode, flags });
|
|
|
+ self.tx.call(msg, extractor!(Open)).await?
|
|
|
+ }
|
|
|
+
|
|
|
+ pub async fn read<R, Fut, F>(&self, read: Read, callback: F) -> Result<R>
|
|
|
+ where
|
|
|
+ F: 'static + Send + FnOnce(ReadReply<'_>) -> Fut,
|
|
|
+ Fut: Send + Future<Output = R>,
|
|
|
+ {
|
|
|
+ let callback = ExtractRead::new(callback);
|
|
|
+ self.tx.call(FsMsg::Read(read), callback).await?
|
|
|
+ }
|
|
|
+
|
|
|
+ pub async fn write(
|
|
|
+ &self,
|
|
|
+ inode: Inode,
|
|
|
+ handle: Handle,
|
|
|
+ offset: u64,
|
|
|
+ data: &[u8],
|
|
|
+ ) -> Result<WriteReply> {
|
|
|
+ let msg = FsMsg::Write(Write {
|
|
|
+ inode,
|
|
|
+ handle,
|
|
|
+ offset,
|
|
|
+ data,
|
|
|
+ });
|
|
|
+ self.tx.call(msg, extractor!(Write)).await?
|
|
|
+ }
|
|
|
+
|
|
|
+ pub async fn flush(&self, inode: Inode, handle: Handle) -> Result<()> {
|
|
|
+ let msg = FsMsg::Flush(Flush { inode, handle });
|
|
|
+ self.tx.call(msg, AckCallback).await?
|
|
|
+ }
|
|
|
+
|
|
|
+ pub async fn link(&self, inode: Inode, new_parent: Inode, name: &str) -> Result<LinkReply> {
|
|
|
+ let msg = FsMsg::Link(Link {
|
|
|
+ inode,
|
|
|
+ new_parent,
|
|
|
+ name,
|
|
|
+ });
|
|
|
+ self.tx.call(msg, extractor!(Link)).await?
|
|
|
+ }
|
|
|
+
|
|
|
+ pub async fn unlink(&self, parent: Inode, name: &str) -> Result<()> {
|
|
|
+ let msg = FsMsg::Unlink(Unlink { parent, name });
|
|
|
+ self.tx.call(msg, AckCallback).await?
|
|
|
+ }
|
|
|
+
|
|
|
+ pub async fn read_meta(&self, inode: Inode) -> Result<BlockMeta> {
|
|
|
+ let msg = FsMsg::ReadMeta(ReadMeta { inode });
|
|
|
+ self.tx.call(msg, ExtractReadMeta).await?
|
|
|
+ }
|
|
|
+
|
|
|
+ pub async fn write_meta(&self, inode: Inode, handle: Handle, meta: BlockMeta) -> Result<()> {
|
|
|
+ let msg = FsMsg::WriteMeta(WriteMeta {
|
|
|
+ inode,
|
|
|
+ handle,
|
|
|
+ meta,
|
|
|
+ });
|
|
|
+ self.tx.call(msg, AckCallback).await?
|
|
|
+ }
|
|
|
+
|
|
|
+ pub async fn close(&self, inode: Inode, handle: Handle) -> Result<()> {
|
|
|
+ let msg = FsMsg::Close(Close { inode, handle });
|
|
|
+ self.tx.call(msg, AckCallback).await?
|
|
|
+ }
|
|
|
+
|
|
|
+ pub async fn forget(&self, inode: Inode, count: u64) -> Result<()> {
|
|
|
+ let msg = FsMsg::Forget(Forget { inode, count });
|
|
|
+ self.tx.call(msg, AckCallback).await?
|
|
|
+ }
|
|
|
+
|
|
|
+ pub async fn lock(&self, inode: Inode, handle: Handle, desc: LockDesc) -> Result<()> {
|
|
|
+ let msg = FsMsg::Lock(Lock {
|
|
|
+ inode,
|
|
|
+ handle,
|
|
|
+ desc,
|
|
|
+ });
|
|
|
+ self.tx.call(msg, AckCallback).await?
|
|
|
+ }
|
|
|
+
|
|
|
+ pub async fn unlock(&self, inode: Inode, handle: Handle) -> Result<()> {
|
|
|
+ let msg = FsMsg::Unlock(Unlock { inode, handle });
|
|
|
+ self.tx.call(msg, AckCallback).await?
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+impl<T> AsRef<T> for FsClient<T> {
|
|
|
+ fn as_ref(&self) -> &T {
|
|
|
+ self.get_ref()
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+impl<T> AsMut<T> for FsClient<T> {
|
|
|
+ fn as_mut(&mut self) -> &mut T {
|
|
|
+ self.get_mut()
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+impl<T> From<T> for FsClient<T> {
|
|
|
+ fn from(value: T) -> Self {
|
|
|
+ Self::new(value)
|
|
|
+ }
|
|
|
+}
|