qbit_api_rs/types/
mod.rs

1pub mod app;
2pub mod auth;
3pub mod log;
4pub mod search;
5pub mod sync;
6pub mod torrents;
7pub mod transfer;
8
9/// ### NOTE:
10/// this custom serializer module is written to solve the problem,
11/// that the serde_urlencoded cannot deserialize the nested struct,
12/// which is the default dependency of the reqwest
13mod preferences_serialize {
14
15    use serde::{self, Serialize, Serializer};
16
17    pub fn serialize<T, S>(value: &T, s: S) -> Result<S::Ok, S::Error>
18    where
19        T: ?Sized + Serialize,
20        S: Serializer,
21    {
22        match serde_json::to_string(value) {
23            Ok(json) => s.serialize_str(&json),
24            Err(_) => Err(serde::ser::Error::custom("Failed to serialize &T to json")),
25        }
26    }
27}
28
29/// serialize & deserialize between `Vec<String>` and String with vertical bar `|`
30///
31/// e.g. `"a|b|c" <=> vec!["a", "b", "c"]`
32pub mod string_saperated_with_vertical_bar {
33
34    use serde::{self, Deserialize, Deserializer, Serializer};
35
36    pub fn serialize<S>(string_items: &[String], s: S) -> Result<S::Ok, S::Error>
37    where
38        S: Serializer,
39    {
40        let string_line = string_items.join("|");
41        s.serialize_str(&string_line)
42    }
43
44    pub fn deserialize<'de, D>(deserializer: D) -> Result<Vec<String>, D::Error>
45    where
46        D: Deserializer<'de>,
47    {
48        let string_line = String::deserialize(deserializer)?;
49        let string_items: Vec<String> = string_line
50            .split('|')
51            .map(|s| s.trim().to_string())
52            .collect();
53        Ok(string_items)
54    }
55}
56
57/// module to serialize & deserialize between `Vec<String>` and String with `\n`
58///
59/// e.g. `"a\nb\nc" <=> vec!["a", "b", "c"]`
60mod string_saperated_with_backslash_n {
61
62    use serde::Serializer;
63
64    pub fn serialize<S>(string_items: &[String], s: S) -> Result<S::Ok, S::Error>
65    where
66        S: Serializer,
67    {
68        let string_line = string_items.join("\n");
69        s.serialize_str(&string_line)
70    }
71}
72
73/// module to serialize & deserialize between `Vec<String>` and String with `,`
74///
75/// e.g. `"a,b,c" <=> vec!["a", "b", "c"]`
76mod string_saperated_with_comma {
77
78    use serde::Serializer;
79
80    pub fn serialize<S>(string_items: &[String], s: S) -> Result<S::Ok, S::Error>
81    where
82        S: Serializer,
83    {
84        let string_line = string_items.join(",");
85        s.serialize_str(&string_line)
86    }
87}
88
89#[cfg(test)]
90mod tests {
91    use super::*;
92    use serde::{Deserialize, Serialize};
93    use std::fs::File;
94    use std::io::{BufReader, Read};
95    use std::path::Path;
96
97    fn read_json_file<P: AsRef<Path>>(path: P) -> String {
98        let mut file = BufReader::new(File::open(path).unwrap());
99        let mut buffer = String::new();
100        file.read_to_string(&mut buffer).unwrap();
101        buffer
102    }
103
104    #[test]
105    fn test_deserialize_preferences_response() {
106        let s = read_json_file("./tests/PreferencesResponse.json");
107        let _p: app::Preferences = serde_json::from_str(&s).unwrap();
108    }
109
110    #[test]
111    fn test_deserialize_maindata_response() {
112        let s = read_json_file("./tests/MaindataResponse.json");
113        let _p: sync::MaindataResponse = serde_json::from_str(&s).unwrap();
114    }
115
116    #[test]
117    fn test_serialize_deserialize_hashes() {
118        #[derive(Debug, PartialEq, Deserialize, Serialize)]
119        struct TestHash {
120            #[serde(with = "string_saperated_with_vertical_bar")]
121            hashes: Vec<String>,
122        }
123
124        let serialized = r#"{"hashes":"7e2fc0391f2d855affed3b0545927bddd5189bc6|a585051959d4e06e71da2f4306547a08348e5d34"}"#;
125
126        let deserialized = TestHash {
127            hashes: vec![
128                "7e2fc0391f2d855affed3b0545927bddd5189bc6".to_string(),
129                "a585051959d4e06e71da2f4306547a08348e5d34".to_string(),
130            ],
131        };
132        let de: TestHash = serde_json::from_str(serialized).unwrap();
133        assert_eq!(de, deserialized);
134
135        let se = serde_json::to_string(&deserialized).unwrap();
136        assert_eq!(se, serialized);
137    }
138
139    #[test]
140    fn test_set_share_limits_form() {
141        let limit = torrents::RatioLimit::Limit { ratio_limit: 5.5 };
142        let mut limit_form = torrents::SetShareLimitsForm {
143            hashes: vec!["7e2fc0391f2d855affed3b0545927bddd5189bc6".to_string()],
144            ratio_limit: limit,
145            seeding_time_limit: 0,
146        };
147
148        let s = serde_json::to_string(&limit_form).unwrap();
149        assert_eq!(
150            s,
151            r#"{"hashes":"7e2fc0391f2d855affed3b0545927bddd5189bc6","ratioLimit":5.5,"seedingTimeLimit":0}"#
152        );
153
154        let special = torrents::RatioLimit::Special { ratio_limit: -1 };
155        limit_form.ratio_limit = special;
156        let s = serde_json::to_string(&limit_form).unwrap();
157        assert_eq!(
158            s,
159            r#"{"hashes":"7e2fc0391f2d855affed3b0545927bddd5189bc6","ratioLimit":-1,"seedingTimeLimit":0}"#
160        );
161    }
162}