financeapi/
autocomplete.rs

1use crate::FinanceapiError;
2use serde::Deserialize;
3
4#[derive(Deserialize, Debug, Default)]
5#[serde(rename_all = "camelCase")]
6pub struct FinanceapiAutocomplete {
7    pub symbol: String,
8    pub name: String,
9    pub exch: String,
10    #[serde(rename(deserialize = "type"))]
11    pub exch_type: String,
12    pub exch_disp: String,
13    pub type_disp: String,
14}
15
16#[derive(Deserialize, Debug)]
17#[serde(rename_all = "PascalCase")]
18struct ResultSet {
19    _query: Option<String>,
20    result: Vec<FinanceapiAutocomplete>,
21}
22
23impl FinanceapiAutocomplete {
24    /// Build a `FinanceapiAutocomplete` object from JSON
25    pub fn from_json(
26        json: serde_json::Value,
27    ) -> Result<Vec<FinanceapiAutocomplete>, FinanceapiError> {
28        let rs: ResultSet = serde_json::from_value(
29            json.get("ResultSet")
30                .ok_or(FinanceapiError::JsonParseError)?
31                .to_owned(),
32        )?;
33
34        if rs.result.is_empty() {
35            return Err(FinanceapiError::SymbolNotFoundError);
36        }
37
38        Ok(rs.result)
39    }
40}
41
42#[cfg(test)]
43mod tests {
44    use super::*;
45    use serde_json::json;
46
47    #[test]
48    #[should_panic(expected = "JsonParseError")]
49    fn wrong_json() {
50        let j = json!({ "var": 200 });
51        FinanceapiAutocomplete::from_json(j).unwrap();
52    }
53
54    #[test]
55    #[should_panic(expected = "SymbolNotFoundError")]
56    fn wrong_symbol() {
57        let j = json!({
58          "ResultSet": {
59            "Query": "unknown",
60            "Result": []
61          }
62        });
63        FinanceapiAutocomplete::from_json(j).unwrap();
64    }
65
66    #[test]
67    #[should_panic(expected = "JsonSerdeError")]
68    fn wrong_json_serde() {
69        let j = json!({
70          "ResultSet": {
71            "Query": "VWCE.MI",
72            "Result": [
73              {
74                "symbol": "VWCE.MI",
75              }
76            ]
77          }
78        });
79        FinanceapiAutocomplete::from_json(j).unwrap();
80    }
81
82    #[test]
83    fn check_parsing() {
84        let j = json!({
85          "ResultSet": {
86            "Query": "VWCE.MI",
87            "Result": [
88              {
89                "symbol": "VWCE.MI",
90                "name": "Vanguard FTSE All-World UCITS ETF USD Accumulation",
91                "exch": "MIL",
92                "type": "E",
93                "exchDisp": "Milan",
94                "typeDisp": "ETF"
95              }
96            ]
97          }
98        });
99
100        let vq = FinanceapiAutocomplete::from_json(j).unwrap();
101        assert_eq!(vq.len(), 1);
102
103        let query = &vq[0];
104        assert_eq!(query.symbol, "VWCE.MI");
105        assert_eq!(query.exch, "MIL");
106    }
107}