cloud_disk_sync/providers/
mod.rs1pub 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, ));
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}