1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
//! Module for searching specific symbol or companies
//!
//! Looking for some specific symbols or companies? Trying to build a search box
//! similar to the one below?
//!
//! You can read about [Symbol][symbol_search] API and what it returns
//! on alphavantage documentation
//!
//! [symbol_search]: https://www.alphavantage.co/documentation/#symbolsearch

use crate::user::APIKey;
use serde_derive::Deserialize;

/// struct for storing search method data
#[derive(Debug, Deserialize)]
pub struct Search {
    #[serde(rename = "Information")]
    information: Option<String>,
    #[serde(rename = "bestMatches")]
    matches: Option<Vec<DataValue>>,
}

/// Struct which stores matches data for search keyword
#[derive(Debug, Clone, Deserialize)]
pub struct DataValue {
    #[serde(rename = "1. symbol")]
    symbol: String,
    #[serde(rename = "2. name")]
    name: String,
    #[serde(rename = "3. type")]
    data_type: String,
    #[serde(rename = "4. region")]
    region: String,
    #[serde(rename = "5. marketOpen")]
    market_open: String,
    #[serde(rename = "6. marketClose")]
    market_close: String,
    #[serde(rename = "7. timezone")]
    time_zone: String,
    #[serde(rename = "8. currency")]
    currency: String,
    #[serde(rename = "9. matchScore")]
    match_score: String,
}

impl DataValue {
    /// Return symbol
    pub fn symbol(&self) -> String {
        self.symbol.to_string()
    }

    /// Return name for symbol
    pub fn name(&self) -> String {
        self.name.to_string()
    }

    /// Return data type
    pub fn data_type(&self) -> String {
        self.data_type.to_string()
    }

    /// Return region of search entry
    pub fn region(&self) -> String {
        self.region.to_string()
    }

    /// Return open value
    pub fn market_open(&self) -> String {
        self.market_open.to_string()
    }

    /// Return close value
    pub fn market_close(&self) -> String {
        self.market_close.to_string()
    }

    /// Return time zone of symbol
    pub fn time_zone(&self) -> String {
        self.time_zone.to_string()
    }

    /// Return currency
    pub fn currency(&self) -> String {
        self.currency.to_string()
    }

    /// Return match score
    pub fn match_score(&self) -> f64 {
        self.match_score.trim().parse::<f64>().unwrap()
    }
}

impl Search {
    /// Return result of search
    pub fn result(&self) -> Result<Vec<DataValue>, String> {
        if let Some(entry) = &self.matches {
            Ok(entry.to_vec())
        } else {
            Err(format!(
                "Information : {}",
                self.information.clone().unwrap()
            ))
        }
    }
}

/// Function used to create a [Search][Search] struct.
///
/// Instead of using this function directly calling through [APIKey][APIKey]
/// method is recommended
pub fn search(keyword: &str, api_data: (&str, Option<u64>)) -> Search {
    let api;
    if let Some(timeout) = api_data.1 {
        api = APIKey::set_with_timeout(api_data.0, timeout);
    } else {
        api = APIKey::set_api(api_data.0);
    }
    api.search(keyword)
}