use serde::{Deserialize, Serialize};
use std::path::PathBuf;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct UploadResult {
pub file_id: String,
pub name: String,
pub size: u64,
pub md5_checksum: Option<String>,
pub web_view_link: Option<String>,
pub upload_duration_secs: f64,
}
#[derive(Debug, Clone)]
pub struct LocalFileMetadata {
pub path: PathBuf,
pub name: String,
pub size: u64,
pub mime_type: String,
pub md5_hash: Option<String>,
}
#[derive(Debug, Clone)]
pub struct UploadProgress {
pub bytes_uploaded: u64,
pub total_bytes: u64,
pub percentage: f32,
pub bytes_per_second: f64,
}
impl UploadProgress {
pub fn new(bytes_uploaded: u64, total_bytes: u64) -> Self {
let percentage = if total_bytes > 0 {
(bytes_uploaded as f32 / total_bytes as f32) * 100.0
} else {
0.0
};
Self {
bytes_uploaded,
total_bytes,
percentage,
bytes_per_second: 0.0,
}
}
pub fn is_complete(&self) -> bool {
self.bytes_uploaded >= self.total_bytes
}
}
pub struct UploadOptions {
pub parent_folder_id: Option<String>,
pub use_resumable: bool,
pub chunk_size: usize,
pub verify_checksum: bool,
pub progress_callback: Option<Box<dyn Fn(UploadProgress) + Send + Sync>>,
}
impl Default for UploadOptions {
fn default() -> Self {
Self {
parent_folder_id: None,
use_resumable: true,
chunk_size: 5 * 1024 * 1024, verify_checksum: true,
progress_callback: None,
}
}
}
impl UploadOptions {
pub fn with_parent(parent_folder_id: String) -> Self {
Self {
parent_folder_id: Some(parent_folder_id),
..Default::default()
}
}
pub fn with_chunk_size(mut self, size: usize) -> Self {
const CHUNK_MULTIPLE: usize = 256 * 1024;
self.chunk_size = (size / CHUNK_MULTIPLE) * CHUNK_MULTIPLE;
if self.chunk_size == 0 {
self.chunk_size = CHUNK_MULTIPLE;
}
self
}
pub fn with_resumable(mut self, resumable: bool) -> Self {
self.use_resumable = resumable;
self
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FolderInfo {
pub id: String,
pub name: String,
pub parent_id: Option<String>,
}
#[derive(Debug, Clone, Default)]
pub struct ListFilesFilter {
pub parent_folder_id: Option<String>,
pub name_contains: Option<String>,
pub mime_type: Option<String>,
pub max_results: Option<i32>,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_upload_progress_calculation() {
let progress = UploadProgress::new(50, 100);
assert_eq!(progress.percentage, 50.0);
assert!(!progress.is_complete());
let complete = UploadProgress::new(100, 100);
assert_eq!(complete.percentage, 100.0);
assert!(complete.is_complete());
}
#[test]
fn test_chunk_size_rounding() {
let options = UploadOptions::default().with_chunk_size(1_000_000);
assert_eq!(options.chunk_size % (256 * 1024), 0);
}
}