quotes 0.1.2

Request tick、stock_list msgs
Documentation
use chrono::NaiveTime;
use http_client::isahc::IsahcClient;
use isahc::prelude::*;

use crate::quote;
use quote::{Quote, Tick};

pub struct TencentQuote {
    pub client: surf::Client,
}

impl Quote for TencentQuote {
    fn new() -> Result<Self, isahc::Error> {
        let http_client = HttpClient::new()?;
        let isahc_client = IsahcClient::from_client(http_client);
        Ok(Self {
            client: surf::Client::with_http_client(isahc_client),
        })
    }

    fn base_url() -> String {
        "http://qt.gtimg.cn/q=".to_string()
    }

    fn client(&self) -> &surf::Client {
        &self.client
    }

    fn parse_out_tick(msg: &str) -> Option<Tick> {
        let field_list: Vec<&str> = msg.split('~').collect();
        if field_list.len() < 30 {
            return None;
        }
        let time_str = match field_list[30].get(8..) {
            Some(s) => s,
            None => return None,
        };
        let time = match NaiveTime::parse_from_str(time_str, "%H%M%S") {
            Ok(t) => t,
            Err(_) => return None,
        };
        let name = field_list[1].to_string();
        let code = field_list[2].to_string();
        let current_price: f64 = match field_list[3].parse() {
            Ok(v) => v,
            Err(_) => return None,
        };
        let pre_close: f64 = match field_list[4].parse() {
            Ok(v) => v,
            Err(_) => return None,
        };
        let open: f64 = match field_list[5].parse() {
            Ok(v) => v,
            Err(_) => return None,
        };
        let high: f64 = match field_list[33].parse() {
            Ok(v) => v,
            Err(_) => return None,
        };
        let low: f64 = match field_list[34].parse() {
            Ok(v) => v,
            Err(_) => return None,
        };
        let total_amount: f64 = match field_list[37].parse::<f64>() {
            Ok(v) => v * 10000.0,
            Err(_) => return None,
        };
        let total_vol: f64 = match field_list[6].parse::<f64>() {
            Ok(v) => v * 100.0,
            Err(_) => return None,
        };
        let mut ask: [f64; 5] = [0.0; 5];
        let mut bid: [f64; 5] = [0.0; 5];
        let mut ask_vol: [i32; 5] = [0; 5];
        let mut bid_vol: [i32; 5] = [0; 5];
        for i in 0..5usize {
            ask[i] = match field_list[19 + i * 2].parse() {
                Ok(v) => v,
                Err(_) => return None,
            };
            bid[i] = match field_list[9 + i * 2].parse() {
                Ok(v) => v,
                Err(_) => return None,
            };
            ask_vol[i] = match field_list[20 + i * 2].parse::<i32>() {
                Ok(v) => v * 100,
                Err(_) => return None,
            };
            bid_vol[i] = match field_list[10 + i * 2].parse::<i32>() {
                Ok(v) => v * 100,
                Err(_) => return None,
            };
        }
        Some(Tick {
            time,
            code,
            name,
            current_price,
            pre_close,
            open,
            high,
            low,
            total_amount,
            total_vol,
            ask,
            bid,
            ask_vol,
            bid_vol,
        })
    }
}