1use std::borrow::Cow;
2
3use serde::{de::DeserializeOwned, ser::SerializeSeq as _, Deserialize, Serializer};
4use serde_json::Value;
5
6use crate::{options::TaskOptions, SmallString, SmallVec};
7
8type SerializeSeq = <serde_json::value::Serializer as serde::ser::Serializer>::SerializeSeq;
9type JsonError = serde_json::Error;
10
11macro_rules! option {
12 ($opt: expr, $serializer: expr) => {
13 if let Some(value) = $opt {
14 $serializer.serialize_element(value)?;
15 }
16 };
17}
18macro_rules! empty {
19 ($map: expr, $serializer: expr) => {
20 if !$map.is_empty() {
21 $serializer.serialize_element($map)?;
22 }
23 };
24}
25
26pub trait Reply {
27 type Reply: DeserializeOwned;
28 #[inline]
29 #[allow(clippy::result_large_err)]
30 fn to_reply(value: Value) -> crate::Result<Self::Reply> {
31 serde_json::from_value::<Self::Reply>(value).map_err(crate::Error::Decode)
32 }
33}
34
35pub trait Call {
36 fn method(&self) -> &'static str;
38 fn serialize_params(
39 &self,
40 serializer: &mut SerializeSeq,
41 token: Option<&str>,
42 ) -> Result<(), JsonError>;
43
44 fn to_param(&self, token: Option<&str>) -> std::result::Result<Value, serde_json::Error> {
45 let mut serializer = serde_json::value::Serializer.serialize_seq(None)?;
46 self.serialize_params(&mut serializer, token)?;
47 serializer.end()
48 }
49}
50
51pub struct AddUriCall {
52 pub uris: SmallVec<String>,
53 pub options: Option<TaskOptions>,
54}
55
56impl Reply for AddUriCall {
57 type Reply = GidReply;
58}
59
60#[derive(Deserialize, Debug, Clone)]
61#[serde(transparent)]
62pub struct GidReply(pub SmallString);
63
64impl Call for AddUriCall {
65 fn method(&self) -> &'static str {
66 "aria2.addUri"
67 }
68 fn serialize_params(
69 &self,
70 serializer: &mut SerializeSeq,
71 token: Option<&str>,
72 ) -> Result<(), JsonError> {
73 option!(token, serializer);
74 serializer.serialize_element(&self.uris)?;
75 option!(&self.options, serializer);
76 Ok(())
77 }
78}
79
80pub struct AddTorrentCall<'a> {
81 pub torrent: Cow<'a, [u8]>,
82 pub uris: SmallVec<Cow<'a, str>>,
83 pub options: Option<TaskOptions>,
84}
85
86impl Reply for AddTorrentCall<'_> {
87 type Reply = GidReply;
88}
89
90impl Call for AddTorrentCall<'_> {
91 fn method(&self) -> &'static str {
92 "aria2.addTorrent"
93 }
94 fn serialize_params(
95 &self,
96 serializer: &mut SerializeSeq,
97 token: Option<&str>,
98 ) -> Result<(), JsonError> {
99 use base64::{engine::general_purpose, Engine as _};
100 let encoded: String = general_purpose::STANDARD.encode(&self.torrent);
101
102 option!(token, serializer);
103 serializer.serialize_element(&encoded)?;
104 serializer.serialize_element(&self.uris)?;
105 option!(&self.options, serializer);
106 Ok(())
107 }
108}
109
110pub struct AddMetalinkCall<'a> {
111 pub metalink: Cow<'a, str>,
112 pub options: Option<TaskOptions>,
113}
114
115impl Reply for AddMetalinkCall<'_> {
116 type Reply = Vec<GidReply>;
117}
118
119impl Call for AddMetalinkCall<'_> {
120 fn method(&self) -> &'static str {
121 "aria2.addMetalink"
122 }
123 fn serialize_params(
124 &self,
125 serializer: &mut SerializeSeq,
126 token: Option<&str>,
127 ) -> Result<(), JsonError> {
128 option!(token, serializer);
129 serializer.serialize_element(&self.metalink)?;
130 option!(&self.options, serializer);
131 Ok(())
132 }
133}
134
135pub struct RemoveCall<'a> {
136 pub gid: Cow<'a, str>,
137}
138
139impl Reply for RemoveCall<'_> {
140 type Reply = GidReply;
141}
142
143impl Call for RemoveCall<'_> {
144 fn method(&self) -> &'static str {
145 "aria2.remove"
146 }
147 fn serialize_params(
148 &self,
149 serializer: &mut SerializeSeq,
150 token: Option<&str>,
151 ) -> Result<(), JsonError> {
152 option!(token, serializer);
153 serializer.serialize_element(&self.gid)?;
154 Ok(())
155 }
156}
157
158pub struct ForceRemoveCall<'a> {
159 pub gid: Cow<'a, str>,
160}
161
162impl Reply for ForceRemoveCall<'_> {
163 type Reply = GidReply;
164}
165
166impl Call for ForceRemoveCall<'_> {
167 fn method(&self) -> &'static str {
168 "aria2.forceRemove"
169 }
170 fn serialize_params(
171 &self,
172 serializer: &mut SerializeSeq,
173 token: Option<&str>,
174 ) -> Result<(), JsonError> {
175 option!(token, serializer);
176 serializer.serialize_element(&self.gid)?;
177 Ok(())
178 }
179}
180
181pub struct PauseCall<'a> {
182 pub gid: Cow<'a, str>,
183}
184
185impl Reply for PauseCall<'_> {
186 type Reply = GidReply;
187}
188
189impl Call for PauseCall<'_> {
190 fn method(&self) -> &'static str {
191 "aria2.pause"
192 }
193 fn serialize_params(
194 &self,
195 serializer: &mut SerializeSeq,
196 token: Option<&str>,
197 ) -> Result<(), JsonError> {
198 option!(token, serializer);
199 serializer.serialize_element(&self.gid)?;
200 Ok(())
201 }
202}
203
204pub struct ForcePauseCall<'a> {
205 pub gid: Cow<'a, str>,
206}
207
208impl Reply for ForcePauseCall<'_> {
209 type Reply = GidReply;
210}
211
212impl Call for ForcePauseCall<'_> {
213 fn method(&self) -> &'static str {
214 "aria2.forcePause"
215 }
216 fn serialize_params(
217 &self,
218 serializer: &mut SerializeSeq,
219 token: Option<&str>,
220 ) -> Result<(), JsonError> {
221 option!(token, serializer);
222 serializer.serialize_element(&self.gid)?;
223 Ok(())
224 }
225}
226
227pub struct UnpauseCall<'a> {
228 pub gid: Cow<'a, str>,
229}
230
231impl Reply for UnpauseCall<'_> {
232 type Reply = GidReply;
233}
234
235impl Call for UnpauseCall<'_> {
236 fn method(&self) -> &'static str {
237 "aria2.unpause"
238 }
239 fn serialize_params(
240 &self,
241 serializer: &mut SerializeSeq,
242 token: Option<&str>,
243 ) -> Result<(), JsonError> {
244 option!(token, serializer);
245 serializer.serialize_element(&self.gid)?;
246 Ok(())
247 }
248}
249
250pub struct TellStatusCall<'a> {
251 pub gid: Cow<'a, str>,
252 pub keys: SmallVec<crate::status::StatusKey>,
253}
254
255impl Reply for TellStatusCall<'_> {
256 type Reply = crate::status::Status;
257}
258
259impl Call for TellStatusCall<'_> {
260 fn method(&self) -> &'static str {
261 "aria2.tellStatus"
262 }
263 fn serialize_params(
264 &self,
265 serializer: &mut SerializeSeq,
266 token: Option<&str>,
267 ) -> Result<(), JsonError> {
268 option!(token, serializer);
269 serializer.serialize_element(&self.gid)?;
270 empty!(&self.keys, serializer);
271 Ok(())
272 }
273}
274
275#[derive(Debug, Default, Clone)]
276pub struct TellActiveCall {
277 pub keys: SmallVec<crate::status::StatusKey>,
278}
279
280impl Reply for TellActiveCall {
281 type Reply = Vec<crate::status::Status>;
282}
283
284impl Call for TellActiveCall {
285 fn method(&self) -> &'static str {
286 "aria2.tellActive"
287 }
288 fn serialize_params(
289 &self,
290 serializer: &mut SerializeSeq,
291 token: Option<&str>,
292 ) -> Result<(), JsonError> {
293 option!(token, serializer);
294 empty!(&self.keys, serializer);
295 Ok(())
296 }
297}
298
299#[derive(Debug, Default, Clone)]
300pub struct TellWaitingCall {
301 pub offset: i32,
302 pub num: i32,
303 pub keys: SmallVec<crate::status::StatusKey>,
304}
305
306impl Reply for TellWaitingCall {
307 type Reply = Vec<crate::status::Status>;
308}
309
310impl Call for TellWaitingCall {
311 fn method(&self) -> &'static str {
312 "aria2.tellWaiting"
313 }
314 fn serialize_params(
315 &self,
316 serializer: &mut SerializeSeq,
317 token: Option<&str>,
318 ) -> Result<(), JsonError> {
319 option!(token, serializer);
320 serializer.serialize_element(&self.offset)?;
321 serializer.serialize_element(&self.num)?;
322 empty!(&self.keys, serializer);
323 Ok(())
324 }
325}
326
327#[derive(Debug, Default, Clone)]
328pub struct TellStoppedCall {
329 pub offset: i32,
330 pub num: i32,
331 pub keys: SmallVec<crate::status::StatusKey>,
332}
333
334impl Reply for TellStoppedCall {
335 type Reply = Vec<crate::status::Status>;
336}
337
338impl Call for TellStoppedCall {
339 fn method(&self) -> &'static str {
340 "aria2.tellStopped"
341 }
342 fn serialize_params(
343 &self,
344 serializer: &mut SerializeSeq,
345 token: Option<&str>,
346 ) -> Result<(), JsonError> {
347 option!(token, serializer);
348 serializer.serialize_element(&self.offset)?;
349 serializer.serialize_element(&self.num)?;
350 empty!(&self.keys, serializer);
351 Ok(())
352 }
353}
354
355#[derive(Debug, Default, Clone)]
356pub struct GetGlobalStatCall {
357 pub keys: SmallVec<crate::status::StatKey>,
358}
359
360impl Reply for GetGlobalStatCall {
361 type Reply = crate::status::Stat;
362}
363
364impl Call for GetGlobalStatCall {
365 fn method(&self) -> &'static str {
366 "aria2.getGlobalStat"
367 }
368 fn serialize_params(
369 &self,
370 serializer: &mut SerializeSeq,
371 token: Option<&str>,
372 ) -> Result<(), JsonError> {
373 option!(token, serializer);
374 empty!(&self.keys, serializer);
375 Ok(())
376 }
377}
378
379#[derive(Debug, Default, Clone, Copy)]
380pub struct PurgeDownloadResultCall;
381
382#[derive(Debug, Clone)]
383pub enum OK {
384 Ok,
385 Err(String),
386}
387
388impl<'de> serde::de::Deserialize<'de> for OK {
389 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
390 where
391 D: serde::Deserializer<'de>,
392 {
393 String::deserialize(deserializer).map(|s| if s == "OK" { OK::Ok } else { OK::Err(s) })
394 }
395}
396
397impl Reply for PurgeDownloadResultCall {
398 type Reply = OK;
399}
400
401impl Call for PurgeDownloadResultCall {
402 fn method(&self) -> &'static str {
403 "aria2.purgeDownloadResult"
404 }
405 fn serialize_params(
406 &self,
407 serializer: &mut SerializeSeq,
408 token: Option<&str>,
409 ) -> Result<(), JsonError> {
410 option!(token, serializer);
411 Ok(())
412 }
413}
414
415#[derive(Default)]
416pub struct MultiCall<'a> {
417 pub calls: Vec<Box<dyn Call + Send + Sync + 'a>>,
418}
419
420#[derive(Debug, Clone)]
421pub struct MultiResponse(pub SmallVec<Value>);
422
423impl<'de> Deserialize<'de> for MultiResponse {
424 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
425 where
426 D: serde::Deserializer<'de>,
427 {
428 let inner = SmallVec::<SmallVec<Value>>::deserialize(deserializer)?;
429 Ok(MultiResponse(inner.into_iter().flatten().collect()))
430 }
431}
432
433impl Reply for MultiCall<'_> {
434 type Reply = MultiResponse;
435}
436
437impl<'a> MultiCall<'a> {
438 pub const fn new() -> Self {
439 Self { calls: Vec::new() }
440 }
441 pub fn push<T: Call + Send + Sync + 'a>(&mut self, call: T) {
442 self.calls.push(Box::new(call));
443 }
444}
445
446impl Call for MultiCall<'_> {
447 fn method(&self) -> &'static str {
448 "system.multicall"
449 }
450 fn serialize_params(
451 &self,
452 serializer: &mut SerializeSeq,
453 token: Option<&str>,
454 ) -> Result<(), JsonError> {
455 #[derive(serde::Serialize)]
456 struct MultiCallParam {
457 #[serde(rename = "methodName")]
458 method_name: &'static str,
459 params: Value,
460 }
461
462 let mut values = SmallVec::with_capacity(self.calls.len());
463 for call in &self.calls {
464 let param = MultiCallParam {
465 method_name: call.method(),
466 params: call.to_param(token)?,
467 };
468 values.push(param);
469 }
470 serializer.serialize_element(&values)?;
471 Ok(())
472 }
473}