use std::future::Future;
use bytes::Bytes;
use chrono::DateTime;
use chrono::Utc;
use serde::Deserialize;
use serde::Serialize;
use tokio_util::sync::CancellationToken;
use crate::dynamic::BoxStream;
use crate::error::ProviderError;
use crate::shared::Headers;
use crate::shared::MediaType;
use crate::shared::ProviderId;
use crate::shared::ProviderMetadata;
use crate::shared::ProviderOptions;
use crate::shared::ProviderReference;
use crate::shared::Warning;
pub trait Files: Send + Sync + 'static {
fn provider(&self) -> &ProviderId;
fn upload_file(
&self,
options: UploadFileOptions,
) -> impl Future<Output = Result<UploadFileResult, ProviderError>> + Send;
fn supports_get_file_metadata(&self) -> bool {
false
}
fn get_file_metadata(
&self,
options: FileReferenceOptions,
) -> impl Future<Output = Result<FileMetadataResult, ProviderError>> + Send {
let _ = options;
std::future::ready(Err(ProviderError::unsupported("get_file_metadata")))
}
fn supports_download_file(&self) -> bool {
false
}
fn download_file(
&self,
options: FileReferenceOptions,
) -> impl Future<Output = Result<DownloadFileResult, ProviderError>> + Send {
let _ = options;
std::future::ready(Err(ProviderError::unsupported("download_file")))
}
fn supports_delete_file(&self) -> bool {
false
}
fn delete_file(
&self,
options: FileReferenceOptions,
) -> impl Future<Output = Result<DeleteFileResult, ProviderError>> + Send {
let _ = options;
std::future::ready(Err(ProviderError::unsupported("delete_file")))
}
}
pub enum UploadData {
Bytes(Bytes),
Text(String),
Stream(BoxStream<'static, Result<Bytes, ProviderError>>),
}
impl std::fmt::Debug for UploadData {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Bytes(bytes) => f.debug_tuple("Bytes").field(&bytes.len()).finish(),
Self::Text(text) => f.debug_tuple("Text").field(&text.len()).finish(),
Self::Stream(_) => f.write_str("Stream(<stream>)"),
}
}
}
impl From<Bytes> for UploadData {
fn from(bytes: Bytes) -> Self {
Self::Bytes(bytes)
}
}
impl From<Vec<u8>> for UploadData {
fn from(bytes: Vec<u8>) -> Self {
Self::Bytes(Bytes::from(bytes))
}
}
impl From<String> for UploadData {
fn from(text: String) -> Self {
Self::Text(text)
}
}
#[derive(Debug)]
pub struct UploadFileOptions {
pub data: UploadData,
pub media_type: MediaType,
pub filename: Option<String>,
pub headers: Headers,
pub provider_options: ProviderOptions,
pub cancellation: CancellationToken,
}
impl UploadFileOptions {
#[must_use]
pub fn new(data: impl Into<UploadData>, media_type: impl Into<MediaType>) -> Self {
Self {
data: data.into(),
media_type: media_type.into(),
filename: None,
headers: Headers::new(),
provider_options: ProviderOptions::new(),
cancellation: CancellationToken::new(),
}
}
}
#[derive(Debug, Clone)]
pub struct FileReferenceOptions {
pub file: ProviderReference,
pub headers: Headers,
pub provider_options: ProviderOptions,
pub cancellation: CancellationToken,
}
impl FileReferenceOptions {
#[must_use]
pub fn new(file: ProviderReference) -> Self {
Self {
file,
headers: Headers::new(),
provider_options: ProviderOptions::new(),
cancellation: CancellationToken::new(),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct UploadFileResult {
pub provider_reference: ProviderReference,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub media_type: Option<MediaType>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub filename: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub byte_size: Option<u64>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub created_at: Option<DateTime<Utc>>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub expires_at: Option<DateTime<Utc>>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub provider_metadata: Option<ProviderMetadata>,
#[serde(default)]
pub warnings: Vec<Warning>,
}
pub type FileMetadataResult = UploadFileResult;
pub struct DownloadFileResult {
pub content: BoxStream<'static, Result<Bytes, ProviderError>>,
pub media_type: Option<MediaType>,
pub provider_metadata: Option<ProviderMetadata>,
pub warnings: Vec<Warning>,
}
impl std::fmt::Debug for DownloadFileResult {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("DownloadFileResult")
.field("content", &"<stream>")
.field("media_type", &self.media_type)
.field("provider_metadata", &self.provider_metadata)
.field("warnings", &self.warnings)
.finish()
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct DeleteFileResult {
pub provider_reference: ProviderReference,
pub deleted: bool,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub provider_metadata: Option<ProviderMetadata>,
#[serde(default)]
pub warnings: Vec<Warning>,
}