diff options
Diffstat (limited to 'rola-bucket/src/protocol.rs')
| -rw-r--r-- | rola-bucket/src/protocol.rs | 169 |
1 files changed, 169 insertions, 0 deletions
diff --git a/rola-bucket/src/protocol.rs b/rola-bucket/src/protocol.rs new file mode 100644 index 0000000..949e6d4 --- /dev/null +++ b/rola-bucket/src/protocol.rs @@ -0,0 +1,169 @@ +use std::path::Path; + +mod error; +pub use error::*; + +/// Request used in [BucketTransferProtocol] or [AsyncBucketTransferProtocol] +pub struct UploadToBucketRequest<'a, Info> +where + Info: Clone + Sync + Send, +{ + /// Extra data to record during the transfer process + pub extra_info: &'a Info, + + /// The relative file path in the bucket to store the uploaded file + pub relative_file_path_to_receive: &'a Path, + + /// The absolute file path of the file to be uploaded to the remote bucket + pub absolute_file_path_to_upload: &'a Path, +} + +/// Request used in [BucketTransferProtocol] or [AsyncBucketTransferProtocol] +pub struct DownloadFromBucketRequest<'a, Info> +where + Info: Clone + Sync + Send, +{ + /// Extra data to record during the transfer process + pub extra_info: &'a Info, + + /// The relative file path in the bucket to download + pub relative_file_path_to_transfer: &'a Path, + + /// The absolute file path to download the file to locally + pub absolute_file_path_to_download: &'a Path, +} + +/// Request used in [BucketTransferProtocol] or [AsyncBucketTransferProtocol] +pub struct TransferToClientRequest<'a, Info> +where + Info: Clone + Sync + Send, +{ + /// Extra data to record during the transfer process + pub extra_info: &'a Info, + + /// The relative file path for the client to download from the bucket + pub relative_file_path_to_download: &'a Path, + + /// The absolute file path of the file to be transferred to the client + pub absolute_file_path_to_transfer: &'a Path, +} + +/// Request used in [BucketTransferProtocol] or [AsyncBucketTransferProtocol] +pub struct ReceiveFromClientRequest<'a, Info> +where + Info: Clone + Sync + Send, +{ + /// Extra data to record during the transfer process + pub extra_info: &'a Info, + + /// The relative file path in the bucket to store the uploaded file + pub relative_file_path_to_upload: &'a Path, + + /// The absolute file path to download the file to locally + pub absolute_file_path_to_receive: &'a Path, +} + +/// This trait is used to implement the specific workflow of file transfer +pub trait BucketTransferProtocol { + /// Structure used to record transfer information + type TransferInfo: Clone + Sync + Send; + + /// Upload a file to the storage bucket + /// The caller must ensure that this function performs the actual transfer operation + fn upload_to_bucket( + &self, + req: &UploadToBucketRequest<Self::TransferInfo>, + ) -> Result<(), BucketTransferProtocolError>; + + /// Download a file from the storage bucket + /// The caller must ensure that after this function executes, a file (and only a file, not a directory) exists at the `path_to_save_file` path + fn download_from_bucket( + &self, + req: &DownloadFromBucketRequest<Self::TransferInfo>, + ) -> Result<(), BucketTransferProtocolError>; + + /// Transfer a file to the client + /// The caller must ensure that this function performs the actual transfer operation + fn transfer_to_client( + &self, + req: &TransferToClientRequest<Self::TransferInfo>, + ) -> Result<(), BucketTransferProtocolError>; + + /// Receive a file from the client + /// The caller must ensure that after this function executes, a file (and only a file, not a directory) exists at the `path_to_save_file` path + fn receive_from_client( + &self, + req: &ReceiveFromClientRequest<Self::TransferInfo>, + ) -> Result<(), BucketTransferProtocolError>; +} + +/// This trait is used to implement the specific workflow of file transfer (asynchronous mode) +pub trait AsyncBucketTransferProtocol { + /// Structure used to record transfer information + type TransferInfo: Clone + Sync + Send; + + /// Asynchronously upload a file to the storage bucket + /// The caller must ensure that this function performs the actual transfer operation + fn upload_to_bucket_async( + &self, + req: &UploadToBucketRequest<Self::TransferInfo>, + ) -> impl Future<Output = Result<(), BucketTransferProtocolError>> + Send + Sync; + + /// Asynchronously download a file from the storage bucket + /// The caller must ensure that after this function executes, a file (and only a file, not a directory) exists at the `path_to_save_file` path + fn download_from_bucket_async( + &self, + req: &DownloadFromBucketRequest<Self::TransferInfo>, + ) -> impl Future<Output = Result<(), BucketTransferProtocolError>> + Send + Sync; + + /// Asynchronously transfer a file to the client + /// The caller must ensure that this function performs the actual transfer operation + fn transfer_to_client_async( + &self, + req: &TransferToClientRequest<Self::TransferInfo>, + ) -> impl Future<Output = Result<(), BucketTransferProtocolError>> + Send + Sync; + + /// Asynchronously receive a file from the client + /// The caller must ensure that after this function executes, a file (and only a file, not a directory) exists at the `path_to_save_file` path + fn receive_from_client_async( + &self, + req: &ReceiveFromClientRequest<Self::TransferInfo>, + ) -> impl Future<Output = Result<(), BucketTransferProtocolError>> + Send + Sync; +} + +/// Blanket implementation: automatically provides async versions of all +/// `BucketTransferProtocol` methods by wrapping them in `async {}` blocks. +impl<T: BucketTransferProtocol + Sync> AsyncBucketTransferProtocol for T +where + T::TransferInfo: Sync, +{ + type TransferInfo = T::TransferInfo; + + fn upload_to_bucket_async( + &self, + req: &UploadToBucketRequest<Self::TransferInfo>, + ) -> impl Future<Output = Result<(), BucketTransferProtocolError>> + Send + Sync { + async move { self.upload_to_bucket(req) } + } + + fn download_from_bucket_async( + &self, + req: &DownloadFromBucketRequest<Self::TransferInfo>, + ) -> impl Future<Output = Result<(), BucketTransferProtocolError>> + Send + Sync { + async move { self.download_from_bucket(req) } + } + + fn transfer_to_client_async( + &self, + req: &TransferToClientRequest<Self::TransferInfo>, + ) -> impl Future<Output = Result<(), BucketTransferProtocolError>> + Send + Sync { + async move { self.transfer_to_client(req) } + } + + fn receive_from_client_async( + &self, + req: &ReceiveFromClientRequest<Self::TransferInfo>, + ) -> impl Future<Output = Result<(), BucketTransferProtocolError>> + Send + Sync { + async move { self.receive_from_client(req) } + } +} |
