1use serde::ser::{SerializeSeq, Serializer};
2use serde_with::{serde_as, DisplayFromStr};
3
4use crate::options::Aria2Options;
5
6pub trait Call {
7 type Response: serde::de::DeserializeOwned;
8
9 fn method(&self) -> &'static str;
10 fn serialize_params<S: SerializeSeq>(&self, _serializer: &mut S) -> Result<(), S::Error> {
11 Ok(())
12 }
13 fn to_params(self, token: Option<&str>) -> Option<Aria2Params<'_, Self>>
14 where
15 Self: Sized,
16 {
17 Some(Aria2Params::new(token, self))
18 }
19}
20
21macro_rules! option_element {
22 ($opt: expr, $serializer: expr) => {
23 if let Some(ref value) = $opt {
24 $serializer.serialize_element(value)?;
25 }
26 };
27}
28
29#[derive(Debug)]
31pub struct Aria2Params<'a, T> {
32 token: Option<&'a str>,
33 params: T,
34}
35
36impl<'a, T> Aria2Params<'a, T> {
37 pub fn new(token: Option<&'a str>, params: T) -> Self {
39 Self { token, params }
40 }
41}
42
43impl<T> serde::Serialize for Aria2Params<'_, T>
44where
45 T: Call,
46{
47 fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
48 where
49 S: Serializer,
50 {
51 let mut seq = serializer.serialize_seq(Some(2))?;
52 option_element!(self.token, seq);
53 self.params.serialize_params(&mut seq)?;
54 seq.end()
55 }
56}
57
58#[derive(Debug)]
59pub struct SystemListMethods;
60impl Call for SystemListMethods {
61 type Response = Vec<String>;
62
63 fn method(&self) -> &'static str {
64 "system.listMethods"
65 }
66
67 fn to_params(self, _: Option<&str>) -> Option<Aria2Params<'_, Self>>
68 where
69 Self: Sized,
70 {
71 None
72 }
73}
74
75#[derive(Debug)]
76pub struct AddUri {
77 pub uris: Vec<String>,
78 pub options: Option<Aria2Options>,
79 pub position: Option<i32>,
80}
81
82impl AddUri {
83 pub fn new<S: Into<String>>(
84 uris: Vec<S>,
85 options: Option<Aria2Options>,
86 position: Option<i32>,
87 ) -> Self {
88 Self::uris(uris).options(options).position(position)
89 }
90
91 pub fn uris<S: Into<String>>(uris: Vec<S>) -> Self {
92 Self {
93 uris: uris.into_iter().map(|s| s.into()).collect(),
94 options: None,
95 position: None,
96 }
97 }
98
99 pub fn options(mut self, options: Option<Aria2Options>) -> Self {
100 self.options = options;
101 self
102 }
103
104 pub fn position(mut self, position: Option<i32>) -> Self {
105 self.position = position;
106 self
107 }
108}
109
110impl Call for AddUri {
111 type Response = GidReply;
112
113 fn method(&self) -> &'static str {
114 "aria2.addUri"
115 }
116
117 fn serialize_params<S: SerializeSeq>(&self, serializer: &mut S) -> Result<(), S::Error> {
118 serializer.serialize_element(&self.uris)?;
119 option_element!(self.options, serializer);
120 option_element!(self.position, serializer);
121 Ok(())
122 }
123}
124
125#[derive(serde::Deserialize, Debug, Clone)]
126#[serde(transparent)]
127pub struct GidReply(pub String);
128
129impl From<GidReply> for String {
130 fn from(gid: GidReply) -> Self {
131 gid.0
132 }
133}
134
135#[derive(Debug)]
136pub struct GetVersion;
137impl Call for GetVersion {
138 type Response = VersionReply;
139
140 fn method(&self) -> &'static str {
141 "aria2.getVersion"
142 }
143}
144
145#[derive(serde::Deserialize, Debug, Clone)]
146pub struct VersionReply {
147 pub version: String,
148 #[serde(rename = "enabledFeatures")]
149 pub enabled_features: Vec<String>,
150}
151
152#[derive(Debug, serde::Serialize, PartialEq, Eq, Hash)]
153#[serde(rename_all = "camelCase")]
154pub enum TellStatusField {
155 Gid,
156 Status,
157 TotalLength,
158 CompletedLength,
159 UploadedLength,
160 BitField,
161 DownloadSpeed,
162 UploadSpeed,
163 InfoHash,
164 NumSeeders,
165 Seeder,
166 PieceLength,
167 NumPieces,
168 Connections,
169 ErrorCode,
170 ErrorMessage,
171 FollowedBy,
172 Following,
173 BelongsTo,
174 Dir,
175 Files,
176 VerifiedLength,
179 VeriyIntegrityPending,
180}
181
182impl TryFrom<&str> for TellStatusField {
183 type Error = &'static str;
184
185 fn try_from(value: &str) -> Result<Self, Self::Error> {
186 match value {
187 "gid" => Ok(Self::Gid),
188 "status" => Ok(Self::Status),
189 "totalLength" => Ok(Self::TotalLength),
190 "completedLength" => Ok(Self::CompletedLength),
191 "uploadedLength" => Ok(Self::UploadedLength),
192 "bitField" => Ok(Self::BitField),
193 "downloadSpeed" => Ok(Self::DownloadSpeed),
194 "uploadSpeed" => Ok(Self::UploadSpeed),
195 "infoHash" => Ok(Self::InfoHash),
196 "numSeeders" => Ok(Self::NumSeeders),
197 "seeder" => Ok(Self::Seeder),
198 "pieceLength" => Ok(Self::PieceLength),
199 "numPieces" => Ok(Self::NumPieces),
200 "connections" => Ok(Self::Connections),
201 "errorCode" => Ok(Self::ErrorCode),
202 "errorMessage" => Ok(Self::ErrorMessage),
203 "followedBy" => Ok(Self::FollowedBy),
204 "following" => Ok(Self::Following),
205 "belongsTo" => Ok(Self::BelongsTo),
206 "dir" => Ok(Self::Dir),
207 "files" => Ok(Self::Files),
208 "verifiedLength" => Ok(Self::VerifiedLength),
210 "veriyIntegrityPending" => Ok(Self::VeriyIntegrityPending),
211 _ => Err("Invalid TellStatusField"),
212 }
213 }
214}
215
216#[derive(Debug, Clone, Copy, PartialEq, serde::Deserialize)]
217#[serde(rename_all = "lowercase")]
218pub enum TaskStatus {
219 Active,
220 Waiting,
221 Paused,
222 Error,
223 Complete,
224 Removed,
225}
226
227#[derive(Debug)]
229pub struct TellStatus {
230 pub gid: String,
231 pub keys: Option<std::collections::HashSet<TellStatusField>>,
232}
233
234macro_rules! tell_star {
235 ($name: ident) => {
236 impl $name {
237 pub fn keys<I, F>(mut self, keys: Option<I>) -> Result<Self, F::Error>
239 where
240 I: IntoIterator<Item = F>,
241 F: TryInto<TellStatusField, Error = &'static str>,
242 {
243 self.keys = None;
244
245 if let Some(keys) = keys {
246 let mut temp = std::collections::HashSet::new();
247 for field in keys.into_iter() {
248 match field.try_into() {
249 Ok(f) => {
250 temp.insert(f);
251 }
252 Err(e) => return Err(e),
253 }
254 }
255 self.keys = Some(temp);
256 }
257 Ok(self)
258 }
259
260 pub fn key<F>(self, key: F) -> Result<Self, F::Error>
262 where
263 F: TryInto<TellStatusField, Error = &'static str>,
264 {
265 let field = key.try_into()?;
266 Ok(self.field(field))
267 }
268
269 pub fn field<F>(mut self, field: F) -> Self
270 where
271 F: Into<TellStatusField>,
272 {
273 if let Some(ref mut keys) = self.keys {
274 keys.insert(field.into());
275 } else {
276 let mut keys = std::collections::HashSet::new();
277 keys.insert(field.into());
278 self.keys = Some(keys);
279 }
280 self
281 }
282
283 pub fn fields<I, F>(mut self, fields: Option<I>) -> Self
284 where
285 I: IntoIterator<Item = F>,
286 F: Into<TellStatusField>,
287 {
288 self.keys = None;
289 if let Some(fields) = fields {
290 let mut keys = std::collections::HashSet::new();
291 for field in fields.into_iter() {
292 keys.insert(field.into());
293 }
294 self.keys = Some(keys);
295 }
296 self
297 }
298 }
299 };
300}
301
302impl TellStatus {
303 pub fn new<G: Into<String>>(gid: G) -> Self {
305 Self {
306 gid: gid.into(),
307 keys: None,
308 }
309 }
310
311 pub fn new_with_fields<G, I, F>(gid: G, fields: I) -> Self
312 where
313 G: Into<String>,
314 I: IntoIterator<Item = F>,
315 F: Into<TellStatusField>,
316 {
317 Self::new(gid).fields(Some(fields))
318 }
319}
320
321tell_star!(TellStatus);
322
323#[serde_as]
324#[derive(Debug, Clone, serde::Deserialize)]
325#[serde(rename_all = "camelCase")]
326pub struct TellStatusReply {
327 pub gid: Option<String>,
328 pub status: Option<TaskStatus>,
329 #[serde_as(as = "Option<DisplayFromStr>")]
330 pub total_length: Option<u64>,
331 #[serde_as(as = "Option<DisplayFromStr>")]
332 pub completed_length: Option<u64>,
333 #[serde_as(as = "Option<DisplayFromStr>")]
334 pub upload_length: Option<u64>,
335 pub bitfield: Option<String>,
336 #[serde_as(as = "Option<DisplayFromStr>")]
337 pub download_speed: Option<u64>,
338 #[serde_as(as = "Option<DisplayFromStr>")]
339 pub upload_speed: Option<u64>,
340 #[serde_as(as = "Option<DisplayFromStr>")]
341 pub piece_length: Option<u64>,
342 #[serde_as(as = "Option<DisplayFromStr>")]
343 pub num_pieces: Option<u64>,
344 #[serde_as(as = "Option<DisplayFromStr>")]
345 pub connections: Option<u64>,
346 pub dir: Option<String>,
347 pub files: Option<Vec<TellStatusReplyFile>>,
348}
349
350#[serde_as]
351#[derive(Debug, Clone, serde::Deserialize)]
352#[serde(rename_all = "camelCase")]
353pub struct TellStatusReplyFile {
354 pub index: String,
355 #[serde_as(as = "DisplayFromStr")]
356 pub length: u64,
357 #[serde_as(as = "DisplayFromStr")]
358 pub completed_length: u64,
359 pub path: String,
360 #[serde_as(as = "DisplayFromStr")]
361 pub selected: bool,
362 pub uris: Vec<TellStatusReplyUri>,
363}
364
365#[derive(Debug, Clone, Copy, PartialEq, serde::Deserialize)]
366#[serde(rename_all = "lowercase")]
367pub enum URIStatus {
368 Used,
369 Waiting,
370}
371#[derive(Debug, Clone, serde::Deserialize)]
372#[serde(rename_all = "camelCase")]
373pub struct TellStatusReplyUri {
374 pub status: URIStatus,
375 pub uri: String,
376}
377
378impl Call for TellStatus {
379 type Response = TellStatusReply;
380
381 fn method(&self) -> &'static str {
382 "aria2.tellStatus"
383 }
384
385 fn serialize_params<S: SerializeSeq>(&self, serializer: &mut S) -> Result<(), S::Error> {
386 serializer.serialize_element(&self.gid)?;
387 option_element!(self.keys, serializer);
388 Ok(())
389 }
390}
391
392#[derive(Debug)]
393pub struct TellActive {
394 keys: Option<std::collections::HashSet<TellStatusField>>,
395}
396
397impl TellActive {
398 pub fn new() -> Self {
399 Self { keys: None }
400 }
401
402 pub fn new_with_fields<I, F>(fields: I) -> Self
403 where
404 I: IntoIterator<Item = F>,
405 F: Into<TellStatusField>,
406 {
407 Self::new().fields(Some(fields))
408 }
409}
410
411tell_star!(TellActive);
412
413
414impl Call for TellActive {
415 type Response = Vec<TellStatusReply>;
416
417 fn method(&self) -> &'static str {
418 "aria2.tellActive"
419 }
420
421 fn serialize_params<S: SerializeSeq>(&self, serializer: &mut S) -> Result<(), S::Error> {
422 option_element!(self.keys, serializer);
423 Ok(())
424 }
425}
426
427#[derive(Debug)]
428pub struct TellWaiting {
429 pub offset: i32,
434 pub num: i32,
435 keys: Option<std::collections::HashSet<TellStatusField>>,
436}
437impl TellWaiting {
438 pub fn new(offset: i32, num: i32) -> Self {
439 Self {
440 offset,
441 num,
442 keys: None,
443 }
444 }
445
446 pub fn new_with_fields<I, F>(offset: i32, num: i32, fields: I) -> Self
447 where
448 I: IntoIterator<Item = F>,
449 F: Into<TellStatusField>,
450 {
451 Self::new(offset, num).fields(Some(fields))
452 }
453}
454
455tell_star!(TellWaiting);
456
457
458impl Call for TellWaiting {
459 type Response = Vec<TellStatusReply>;
460
461 fn method(&self) -> &'static str {
462 "aria2.tellWaiting"
463 }
464
465 fn serialize_params<S: SerializeSeq>(&self, serializer: &mut S) -> Result<(), S::Error> {
466 serializer.serialize_element(&self.offset)?;
467 serializer.serialize_element(&self.num)?;
468 option_element!(self.keys, serializer);
469 Ok(())
470 }
471}
472
473#[derive(Debug)]
474pub struct TellStopped {
475 pub offset: i32,
476 pub num: i32,
477 keys: Option<std::collections::HashSet<TellStatusField>>,
478}
479
480impl TellStopped {
481 pub fn new(offset: i32, num: i32) -> Self {
482 Self {
483 offset,
484 num,
485 keys: None,
486 }
487 }
488
489 pub fn new_with_fields<I, F>(offset: i32, num: i32, fields: I) -> Self
490 where
491 I: IntoIterator<Item = F>,
492 F: Into<TellStatusField>,
493 {
494 Self::new(offset, num).fields(Some(fields))
495 }
496}
497tell_star!(TellStopped);
498
499
500impl Call for TellStopped {
501 type Response = Vec<TellStatusReply>;
502
503 fn method(&self) -> &'static str {
504 "aria2.tellStopped"
505 }
506
507 fn serialize_params<S: SerializeSeq>(&self, serializer: &mut S) -> Result<(), S::Error> {
508 serializer.serialize_element(&self.offset)?;
509 serializer.serialize_element(&self.num)?;
510 option_element!(self.keys, serializer);
511 Ok(())
512 }
513}
514
515#[derive(Debug)]
516pub struct GetUris {
517 pub gid: String,
518}
519
520impl GetUris {
521 pub fn new<G: Into<String>>(gid: G) -> Self {
522 Self { gid: gid.into() }
523 }
524}
525impl Call for GetUris {
526 type Response = Vec<TellStatusReplyUri>;
527
528 fn method(&self) -> &'static str {
529 "aria2.getUris"
530 }
531
532 fn serialize_params<S: SerializeSeq>(&self, serializer: &mut S) -> Result<(), S::Error> {
533 serializer.serialize_element(&self.gid)?;
534 Ok(())
535 }
536}
537
538#[derive(Debug)]
539pub struct GetFiles {
540 pub gid: String,
541}
542impl GetFiles {
543 pub fn new<G: Into<String>>(gid: G) -> Self {
544 Self { gid: gid.into() }
545 }
546}
547impl Call for GetFiles {
548 type Response = Vec<TellStatusReplyFile>;
549
550 fn method(&self) -> &'static str {
551 "aria2.getFiles"
552 }
553
554 fn serialize_params<S: SerializeSeq>(&self, serializer: &mut S) -> Result<(), S::Error> {
555 serializer.serialize_element(&self.gid)?;
556 Ok(())
557 }
558}