pub(crate) mod usb;
#[cfg(windows)]
pub(crate) mod wpd;
use crate::cancel::CancelToken;
use crate::mtp::object::NewObjectInfo;
use crate::mtp::stream::Progress;
use crate::mtp::{
Capabilities, DeviceEvent, DeviceInfo, Error, ObjectHandle, ObjectInfo, StorageId, StorageInfo,
UploadError,
};
use async_trait::async_trait;
use bytes::Bytes;
use futures::Stream;
use std::ops::ControlFlow;
use std::pin::Pin;
use std::time::Duration;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum Backend {
#[default]
Auto,
Usb,
Wpd,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ByteRange {
Full,
From(u64),
Range {
offset: u64,
len: u64,
},
}
impl ByteRange {
#[must_use]
pub(crate) fn offset(self) -> u64 {
match self {
ByteRange::Full => 0,
ByteRange::From(offset) | ByteRange::Range { offset, .. } => offset,
}
}
}
pub(crate) type ProgressFn<'a> = Box<dyn FnMut(Progress) -> ControlFlow<()> + Send + 'a>;
pub(crate) type UploadStream<'a> =
Pin<Box<dyn Stream<Item = Result<Bytes, std::io::Error>> + Send + 'a>>;
#[async_trait]
pub(crate) trait DownloadBody: Send {
async fn next_chunk(&mut self) -> Option<Result<Bytes, Error>>;
async fn cancel(&mut self, idle_timeout: Duration) -> Result<(), Error>;
}
pub(crate) struct BackendDownload {
pub(crate) size: u64,
pub(crate) body: Box<dyn DownloadBody>,
}
pub(crate) type ObjectStream = Pin<Box<dyn Stream<Item = Result<ObjectInfo, Error>> + Send>>;
pub(crate) struct BackendListing {
pub(crate) total: usize,
pub(crate) items: ObjectStream,
}
#[async_trait]
pub(crate) trait MtpBackend: Send + Sync {
fn device_info(&self) -> &DeviceInfo;
fn capabilities(&self) -> &Capabilities;
async fn storages(&self) -> Result<Vec<StorageInfo>, Error>;
async fn storage_info(&self, storage: StorageId) -> Result<StorageInfo, Error>;
async fn list(
&self,
storage: StorageId,
parent: Option<ObjectHandle>,
cancel: Option<&CancelToken>,
) -> Result<BackendListing, Error>;
async fn object_info(&self, obj: ObjectHandle) -> Result<ObjectInfo, Error>;
async fn download(&self, obj: ObjectHandle, range: ByteRange)
-> Result<BackendDownload, Error>;
async fn read_range(
&self,
obj: ObjectHandle,
offset: u64,
len: Option<u32>,
) -> Result<Vec<u8>, Error>;
async fn thumbnail(&self, obj: ObjectHandle) -> Result<Vec<u8>, Error>;
async fn upload(
&self,
storage: StorageId,
parent: Option<ObjectHandle>,
info: NewObjectInfo,
data: UploadStream<'_>,
progress: Option<ProgressFn<'_>>,
) -> Result<ObjectHandle, UploadError>;
async fn create_folder(
&self,
storage: StorageId,
parent: Option<ObjectHandle>,
name: &str,
) -> Result<ObjectHandle, Error>;
async fn delete(&self, obj: ObjectHandle, cancel: Option<&CancelToken>) -> Result<(), Error>;
async fn move_object(
&self,
obj: ObjectHandle,
new_parent: ObjectHandle,
new_storage: StorageId,
) -> Result<(), Error>;
async fn copy_object(
&self,
obj: ObjectHandle,
new_parent: ObjectHandle,
new_storage: StorageId,
) -> Result<ObjectHandle, Error>;
async fn rename(&self, obj: ObjectHandle, new_name: &str) -> Result<(), Error>;
async fn next_event(&self) -> Result<DeviceEvent, Error>;
async fn close(&self) -> Result<(), Error>;
}