use std::path::{Path, PathBuf};
use serde::{Deserialize, Serialize};
use crate::{ZaiResult, client::ZaiClient};
pub type FileResponse = crate::tool::FileParseResultResponse;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(rename_all = "UPPERCASE")]
pub enum FileParseSyncFileType {
WPS,
PDF,
DOCX,
DOC,
XLS,
XLSX,
PPT,
PPTX,
PNG,
JPG,
JPEG,
CSV,
TXT,
MD,
HTML,
BMP,
GIF,
WEBP,
HEIC,
EPS,
ICNS,
IM,
PCX,
PPM,
TIFF,
XBM,
HEIF,
JP2,
}
impl FileParseSyncFileType {
pub const fn as_str(self) -> &'static str {
match self {
Self::WPS => "WPS",
Self::PDF => "PDF",
Self::DOCX => "DOCX",
Self::DOC => "DOC",
Self::XLS => "XLS",
Self::XLSX => "XLSX",
Self::PPT => "PPT",
Self::PPTX => "PPTX",
Self::PNG => "PNG",
Self::JPG => "JPG",
Self::JPEG => "JPEG",
Self::CSV => "CSV",
Self::TXT => "TXT",
Self::MD => "MD",
Self::HTML => "HTML",
Self::BMP => "BMP",
Self::GIF => "GIF",
Self::WEBP => "WEBP",
Self::HEIC => "HEIC",
Self::EPS => "EPS",
Self::ICNS => "ICNS",
Self::IM => "IM",
Self::PCX => "PCX",
Self::PPM => "PPM",
Self::TIFF => "TIFF",
Self::XBM => "XBM",
Self::HEIF => "HEIF",
Self::JP2 => "JP2",
}
}
}
pub struct FileParseSyncRequest {
file_path: PathBuf,
file_type: Option<FileParseSyncFileType>,
}
impl std::fmt::Debug for FileParseSyncRequest {
fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
formatter
.debug_struct("FileParseSyncRequest")
.field("file_path", &"[REDACTED]")
.field("file_type", &self.file_type)
.finish()
}
}
impl FileParseSyncRequest {
pub fn new(file_path: impl Into<PathBuf>) -> Self {
Self {
file_path: file_path.into(),
file_type: None,
}
}
pub fn with_file_type(mut self, file_type: FileParseSyncFileType) -> Self {
self.file_type = Some(file_type);
self
}
pub fn file_path(&self) -> &Path {
&self.file_path
}
pub const fn tool_type(&self) -> &'static str {
"prime-sync"
}
pub const fn file_type(&self) -> Option<FileParseSyncFileType> {
self.file_type
}
pub async fn send_via(&self, client: &ZaiClient) -> ZaiResult<FileResponse> {
let file_part = crate::client::transport::multipart::FilePart::from_path(&self.file_path)?;
let route = crate::client::routes::FILES_PARSE_SYNC;
let url = client.endpoints().resolve_route(route, &[])?;
let mut factory = crate::client::transport::multipart::MultipartBodyFactory::new()
.field("tool_type", self.tool_type())?;
if let Some(file_type) = self.file_type {
factory = factory.field("file_type", file_type.as_str())?;
}
factory = factory.file_named("file", file_part)?;
client
.send_multipart::<FileResponse>(route.method(), url, &factory)
.await
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn file_type_values_match_the_frozen_enum() {
let values = [
FileParseSyncFileType::WPS,
FileParseSyncFileType::PDF,
FileParseSyncFileType::DOCX,
FileParseSyncFileType::DOC,
FileParseSyncFileType::XLS,
FileParseSyncFileType::XLSX,
FileParseSyncFileType::PPT,
FileParseSyncFileType::PPTX,
FileParseSyncFileType::PNG,
FileParseSyncFileType::JPG,
FileParseSyncFileType::JPEG,
FileParseSyncFileType::CSV,
FileParseSyncFileType::TXT,
FileParseSyncFileType::MD,
FileParseSyncFileType::HTML,
FileParseSyncFileType::BMP,
FileParseSyncFileType::GIF,
FileParseSyncFileType::WEBP,
FileParseSyncFileType::HEIC,
FileParseSyncFileType::EPS,
FileParseSyncFileType::ICNS,
FileParseSyncFileType::IM,
FileParseSyncFileType::PCX,
FileParseSyncFileType::PPM,
FileParseSyncFileType::TIFF,
FileParseSyncFileType::XBM,
FileParseSyncFileType::HEIF,
FileParseSyncFileType::JP2,
];
let expected = [
"WPS", "PDF", "DOCX", "DOC", "XLS", "XLSX", "PPT", "PPTX", "PNG", "JPG", "JPEG", "CSV",
"TXT", "MD", "HTML", "BMP", "GIF", "WEBP", "HEIC", "EPS", "ICNS", "IM", "PCX", "PPM",
"TIFF", "XBM", "HEIF", "JP2",
];
assert_eq!(values.map(FileParseSyncFileType::as_str), expected);
for value in values {
assert_eq!(
serde_json::to_value(value).unwrap(),
serde_json::Value::String(value.as_str().to_owned())
);
}
}
#[test]
fn response_required_fields_do_not_default() {
assert!(
serde_json::from_value::<FileResponse>(serde_json::json!({
"status": "succeeded",
"message": "ok"
}))
.is_err()
);
}
}