cloud_disk_sync/providers/
mod.rs

1pub mod aliyun;
2pub mod webdav;
3
4pub use aliyun::AliYunDriveProvider;
5pub use webdav::WebDavProvider;
6
7use crate::config::{AccountConfig, ProviderType, RateLimitConfig};
8use crate::core::rate_limit::TokenBucketRateLimiter;
9use crate::core::traits::RateLimiter;
10use crate::error::SyncError;
11use async_trait::async_trait;
12use std::path::Path;
13use std::sync::Arc;
14use std::time::Duration;
15
16#[async_trait]
17pub trait StorageProvider: Send + Sync {
18    async fn list(&self, path: &str) -> Result<Vec<FileInfo>, SyncError>;
19    async fn upload(&self, local_path: &Path, remote_path: &str)
20    -> Result<UploadResult, SyncError>;
21    async fn download(
22        &self,
23        remote_path: &str,
24        local_path: &Path,
25    ) -> Result<DownloadResult, SyncError>;
26    async fn delete(&self, path: &str) -> Result<(), SyncError>;
27    async fn mkdir(&self, path: &str) -> Result<(), SyncError>;
28    async fn stat(&self, path: &str) -> Result<FileInfo, SyncError>;
29    async fn exists(&self, path: &str) -> Result<bool, SyncError>;
30}
31
32pub async fn create_provider(
33    account: &AccountConfig,
34) -> Result<Box<dyn StorageProvider>, Box<dyn std::error::Error>> {
35    match account.provider {
36        ProviderType::AliYunDrive => {
37            let provider = AliYunDriveProvider::new(account).await?;
38            Ok(Box::new(provider))
39        }
40        ProviderType::WebDAV => {
41            let provider = WebDavProvider::new(account).await?;
42            Ok(Box::new(provider))
43        }
44        _ => Err(format!("Unsupported provider type: {:?}", account.provider).into()),
45    }
46}
47
48#[derive(Debug, Clone)]
49pub struct FileInfo {
50    pub path: String,
51    pub size: u64,
52    pub modified: i64,
53    pub hash: Option<String>,
54    pub is_dir: bool,
55}
56
57#[derive(Debug, Default)]
58pub struct UploadResult {
59    pub bytes_uploaded: u64,
60    pub file_size: u64,
61    pub checksum: Option<String>,
62    pub elapsed_time: Duration,
63}
64
65#[derive(Debug, Default)]
66pub struct DownloadResult {
67    pub bytes_downloaded: u64,
68    pub file_size: u64,
69    pub checksum: Option<String>,
70    pub elapsed_time: Duration,
71}
72
73pub struct RateLimitedProvider<T> {
74    inner: T,
75    limiter: Arc<dyn RateLimiter>,
76}
77
78impl<T: StorageProvider> RateLimitedProvider<T> {
79    pub fn new(inner: T, config: RateLimitConfig) -> Self {
80        let limiter = Arc::new(TokenBucketRateLimiter::new(
81            config.max_concurrent as u64,
82            config.requests_per_minute as f64 / 60.0, // 转换为每秒请求数
83        ));
84
85        Self { inner, limiter }
86    }
87}
88
89#[async_trait]
90impl<T: StorageProvider> StorageProvider for RateLimitedProvider<T> {
91    async fn list(&self, path: &str) -> Result<Vec<FileInfo>, SyncError> {
92        self.limiter.acquire().await?;
93        self.inner.list(path).await
94    }
95
96    async fn upload(
97        &self,
98        local_path: &Path,
99        remote_path: &str,
100    ) -> Result<UploadResult, SyncError> {
101        self.limiter.acquire().await?;
102        self.inner.upload(local_path, remote_path).await
103    }
104
105    async fn download(
106        &self,
107        remote_path: &str,
108        local_path: &Path,
109    ) -> Result<DownloadResult, SyncError> {
110        self.limiter.acquire().await?;
111        self.inner.download(remote_path, local_path).await
112    }
113
114    async fn delete(&self, path: &str) -> Result<(), SyncError> {
115        self.limiter.acquire().await?;
116        self.inner.delete(path).await
117    }
118
119    async fn mkdir(&self, path: &str) -> Result<(), SyncError> {
120        self.limiter.acquire().await?;
121        self.inner.mkdir(path).await
122    }
123
124    async fn stat(&self, path: &str) -> Result<FileInfo, SyncError> {
125        self.limiter.acquire().await?;
126        self.inner.stat(path).await
127    }
128
129    async fn exists(&self, path: &str) -> Result<bool, SyncError> {
130        self.limiter.acquire().await?;
131        self.inner.exists(path).await
132    }
133}