use std::{future::Future, mem::MaybeUninit, ops::Deref, path::PathBuf};
use crate::{
error::{CResult, CloudErrorKind},
request::Request,
utility::LocalBoxFuture,
};
use super::{info, ticket, SyncFilter};
pub trait Filter: Send + Sync {
fn fetch_data(
&self,
_request: Request,
_ticket: ticket::FetchData,
_info: info::FetchData,
) -> impl Future<Output = CResult<()>>;
fn cancel_fetch_data(
&self,
_request: Request,
_info: info::CancelFetchData,
) -> impl Future<Output = ()> {
async {}
}
fn validate_data(
&self,
_request: Request,
_ticket: ticket::ValidateData,
_info: info::ValidateData,
) -> impl Future<Output = CResult<()>> {
async { Err(CloudErrorKind::NotSupported) }
}
fn fetch_placeholders(
&self,
_request: Request,
_ticket: ticket::FetchPlaceholders,
_info: info::FetchPlaceholders,
) -> impl Future<Output = CResult<()>> {
async { Err(CloudErrorKind::NotSupported) }
}
fn cancel_fetch_placeholders(
&self,
_request: Request,
_info: info::CancelFetchPlaceholders,
) -> impl Future<Output = ()> {
async {}
}
fn opened(&self, _request: Request, _info: info::Opened) -> impl Future<Output = ()> {
async {}
}
fn closed(&self, _request: Request, _info: info::Closed) -> impl Future<Output = ()> {
async {}
}
fn dehydrate(
&self,
_request: Request,
_ticket: ticket::Dehydrate,
_info: info::Dehydrate,
) -> impl Future<Output = CResult<()>> {
async { Err(CloudErrorKind::NotSupported) }
}
fn dehydrated(&self, _request: Request, _info: info::Dehydrated) -> impl Future<Output = ()> {
async {}
}
fn delete(
&self,
_request: Request,
_ticket: ticket::Delete,
_info: info::Delete,
) -> impl Future<Output = CResult<()>> {
async { Err(CloudErrorKind::NotSupported) }
}
fn deleted(&self, _request: Request, _info: info::Deleted) -> impl Future<Output = ()> {
async {}
}
fn rename(
&self,
_request: Request,
_ticket: ticket::Rename,
_info: info::Rename,
) -> impl Future<Output = CResult<()>> {
async { Err(CloudErrorKind::NotSupported) }
}
fn renamed(&self, _request: Request, _info: info::Renamed) -> impl Future<Output = ()> {
async {}
}
fn state_changed(&self, _changes: Vec<PathBuf>) -> impl Future<Output = ()> {
async {}
}
}
pub struct AsyncBridge<F, B> {
filter: F,
block_on: B,
}
impl<F, B> AsyncBridge<F, B>
where
F: Filter,
B: Fn(LocalBoxFuture<'_, ()>) + Send + Sync,
{
pub(crate) fn new(filter: F, block_on: B) -> Self {
Self { filter, block_on }
}
}
impl<F, B> SyncFilter for AsyncBridge<F, B>
where
F: Filter,
B: Fn(LocalBoxFuture<'_, ()>) + Send + Sync,
{
fn fetch_data(
&self,
request: Request,
ticket: ticket::FetchData,
info: info::FetchData,
) -> CResult<()> {
let mut ret = MaybeUninit::zeroed();
(self.block_on)(Box::pin(async {
ret.write(self.filter.fetch_data(request, ticket, info).await);
}));
unsafe { ret.assume_init() }
}
fn cancel_fetch_data(&self, request: Request, info: info::CancelFetchData) {
(self.block_on)(Box::pin(self.filter.cancel_fetch_data(request, info)))
}
fn validate_data(
&self,
request: Request,
ticket: ticket::ValidateData,
info: info::ValidateData,
) -> CResult<()> {
let mut ret = MaybeUninit::zeroed();
(self.block_on)(Box::pin(async {
ret.write(self.filter.validate_data(request, ticket, info).await);
}));
unsafe { ret.assume_init() }
}
fn fetch_placeholders(
&self,
request: Request,
ticket: ticket::FetchPlaceholders,
info: info::FetchPlaceholders,
) -> CResult<()> {
let mut ret = MaybeUninit::zeroed();
(self.block_on)(Box::pin(async {
ret.write(self.filter.fetch_placeholders(request, ticket, info).await);
}));
unsafe { ret.assume_init() }
}
fn cancel_fetch_placeholders(&self, request: Request, info: info::CancelFetchPlaceholders) {
(self.block_on)(Box::pin(
self.filter.cancel_fetch_placeholders(request, info),
))
}
fn opened(&self, request: Request, info: info::Opened) {
(self.block_on)(Box::pin(self.filter.opened(request, info)))
}
fn closed(&self, request: Request, info: info::Closed) {
(self.block_on)(Box::pin(self.filter.closed(request, info)))
}
fn dehydrate(
&self,
request: Request,
ticket: ticket::Dehydrate,
info: info::Dehydrate,
) -> CResult<()> {
let mut ret = MaybeUninit::zeroed();
(self.block_on)(Box::pin(async {
ret.write(self.filter.dehydrate(request, ticket, info).await);
}));
unsafe { ret.assume_init() }
}
fn dehydrated(&self, request: Request, info: info::Dehydrated) {
(self.block_on)(Box::pin(self.filter.dehydrated(request, info)))
}
fn delete(&self, request: Request, ticket: ticket::Delete, info: info::Delete) -> CResult<()> {
let mut ret = MaybeUninit::zeroed();
(self.block_on)(Box::pin(async {
ret.write(self.filter.delete(request, ticket, info).await);
}));
unsafe { ret.assume_init() }
}
fn deleted(&self, request: Request, info: info::Deleted) {
(self.block_on)(Box::pin(self.filter.deleted(request, info)))
}
fn rename(&self, request: Request, ticket: ticket::Rename, info: info::Rename) -> CResult<()> {
let mut ret = MaybeUninit::zeroed();
(self.block_on)(Box::pin(async {
ret.write(self.filter.rename(request, ticket, info).await);
}));
unsafe { ret.assume_init() }
}
fn renamed(&self, request: Request, info: info::Renamed) {
(self.block_on)(Box::pin(self.filter.renamed(request, info)))
}
fn state_changed(&self, changes: Vec<PathBuf>) {
(self.block_on)(Box::pin(self.filter.state_changed(changes)))
}
}
impl<F, B> Deref for AsyncBridge<F, B>
where
F: Filter,
B: Fn(LocalBoxFuture<'_, ()>) + Send + Sync,
{
type Target = F;
fn deref(&self) -> &Self::Target {
&self.filter
}
}