use async_trait::async_trait;
use serde::{Deserialize, Serialize};
use crate::error::Result;
use crate::shared::{FileBytes, ProviderMetadata, ProviderOptions, ProviderReference, Warning};
#[async_trait]
pub trait FilesModel: Send + Sync + std::fmt::Debug {
fn provider(&self) -> &str;
fn specification_version(&self) -> &'static str {
"v4"
}
async fn upload_file(&self, options: UploadFileOptions) -> Result<UploadFileResult>;
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct UploadFileOptions {
pub data: UploadFileData,
#[serde(rename = "mediaType")]
pub media_type: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub filename: Option<String>,
#[serde(
default,
rename = "providerOptions",
skip_serializing_if = "Option::is_none"
)]
pub provider_options: Option<ProviderOptions>,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
#[serde(tag = "type", rename_all = "kebab-case")]
pub enum UploadFileData {
Data {
data: FileBytes,
},
Text {
text: String,
},
}
#[derive(Debug, Clone)]
pub struct UploadFileResult {
pub provider_reference: ProviderReference,
pub media_type: Option<String>,
pub filename: Option<String>,
pub provider_metadata: Option<ProviderMetadata>,
pub warnings: Vec<Warning>,
}
#[cfg(test)]
mod tests {
use super::*;
use serde_json::json;
#[test]
fn options_serde_roundtrip_data() {
let opts = UploadFileOptions {
data: UploadFileData::Data {
data: FileBytes::Base64("aGVsbG8=".into()),
},
media_type: "text/plain".into(),
filename: Some("hi.txt".into()),
provider_options: None,
};
let json = serde_json::to_value(&opts).unwrap();
assert_eq!(json["mediaType"], "text/plain");
assert_eq!(json["data"]["type"], "data");
assert_eq!(json["data"]["data"], "aGVsbG8=");
let back: UploadFileOptions = serde_json::from_value(json).unwrap();
assert_eq!(back.media_type, "text/plain");
}
#[test]
fn options_serde_roundtrip_text() {
let opts = UploadFileOptions {
data: UploadFileData::Text {
text: "hello".into(),
},
media_type: "text/plain".into(),
filename: None,
provider_options: None,
};
let json = serde_json::to_value(&opts).unwrap();
assert_eq!(json["data"], json!({ "type": "text", "text": "hello" }));
}
#[test]
fn upload_data_tagged_correctly() {
let v = serde_json::to_value(UploadFileData::Data {
data: FileBytes::Bytes(vec![1, 2, 3]),
})
.unwrap();
assert_eq!(v["type"], "data");
}
}