stock-rust 0.1.0

Rust version of stock-api
Documentation
use anyhow::{anyhow, Result};

use crate::stocks::base::{COMMON_HK, COMMON_SH, COMMON_SZ, COMMON_US};

use super::base::{ApiCodeTransform, CommonCodeTransform};

const NETEASE_SZ: &str = "1";
const NETEASE_SH: &str = "0";
const NETEASE_HK: &str = "hk";
const NETEASE_US: &str = "US_";

pub struct NeteaseCommonCodeTransform;

impl CommonCodeTransform for NeteaseCommonCodeTransform {
    fn transform(&self, code: &str) -> Result<String> {
        if code.starts_with(COMMON_SH) {
            return self.sh_transform(code);
        }
        if code.starts_with(COMMON_SZ) {
            return self.sz_transform(code);
        }
        if code.starts_with(COMMON_HK) {
            return self.hk_transform(code);
        }
        if code.starts_with(COMMON_US) {
            return self.us_transform(code);
        }

        Err(anyhow!("请检查统一代码是否正确"))
    }

    fn sz_transform(&self, code: &str) -> Result<String> {
        if !code.contains(COMMON_SZ) {
            return Err(anyhow!("请检查统一代码是否正确"));
        }
        Ok(format!("{}{}", NETEASE_SZ, code.replacen(COMMON_SZ, "", 1)))
    }

    fn sh_transform(&self, code: &str) -> Result<String> {
        if !code.contains(COMMON_SH) {
            return Err(anyhow!("请检查统一代码是否正确"));
        }
        Ok(format!("{}{}", NETEASE_SH, code.replacen(COMMON_SH, "", 1)))
    }

    fn hk_transform(&self, code: &str) -> Result<String> {
        if !code.contains(COMMON_HK) {
            return Err(anyhow!("请检查统一代码是否正确"));
        }
        Ok(format!("{}{}", NETEASE_HK, code.replacen(COMMON_HK, "", 1)))
    }

    fn us_transform(&self, code: &str) -> Result<String> {
        if !code.contains(COMMON_US) {
            return Err(anyhow!("请检查统一代码是否正确"));
        }
        Ok(format!("{}{}", NETEASE_US, code.replacen(COMMON_US, "", 1)))
    }
}

pub struct NeteaseApiCodeTransform;

impl ApiCodeTransform for NeteaseApiCodeTransform {
    fn transform(&self, code: &str) -> Result<String> {
        if code.starts_with(NETEASE_SZ) {
            return self.sz_transform(code);
        }
        if code.starts_with(NETEASE_SH) {
            return self.sh_transform(code);
        }
        if code.starts_with(NETEASE_HK) {
            return self.hk_transform(code);
        }
        if code.starts_with(NETEASE_US) {
            return self.us_transform(code);
        }

        Err(anyhow!("请检查股票代码是否正确"))
    }

    fn sz_transform(&self, code: &str) -> Result<String> {
        if !code.starts_with(NETEASE_SZ) {
            return Err(anyhow!("请检查股票代码是否正确"));
        }
        Ok(format!("{}{}", COMMON_SZ, code.replacen(NETEASE_SZ, "", 1)))
    }

    fn sh_transform(&self, code: &str) -> Result<String> {
        if !code.contains(NETEASE_SH) {
            return Err(anyhow!("请检查股票代码是否正确"));
        }
        Ok(format!("{}{}", COMMON_SH, code.replacen(NETEASE_SH, "", 1)))
    }

    fn hk_transform(&self, code: &str) -> Result<String> {
        if !code.contains(NETEASE_HK) {
            return Err(anyhow!("请检查股票代码是否正确"));
        }
        Ok(format!("{}{}", COMMON_HK, code.replacen(NETEASE_HK, "", 1)))
    }

    fn us_transform(&self, code: &str) -> Result<String> {
        if !code.contains(NETEASE_US) {
            return Err(anyhow!("请检查股票代码是否正确"));
        }
        Ok(format!("{}{}", COMMON_US, code.replacen(NETEASE_US, "", 1)))
    }
}

pub struct NeteaseSearchCodeTransform;

impl NeteaseSearchCodeTransform {
    pub fn transform(&self, tag: &str, tp: &str, symbol: &str) -> String {
        if tag.contains(COMMON_SZ) || tp.contains(COMMON_SZ) {
            return format!("{}{}", COMMON_SZ, symbol);
        }
        if tag.contains(COMMON_SH) || tp.contains(COMMON_SH) {
            return format!("{}{}", COMMON_SH, symbol);
        }
        String::new()
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_common_code_transform() {
        let t = NeteaseCommonCodeTransform;
        assert_eq!(t.transform("SH510500").unwrap(), "0510500");
        assert_eq!(t.transform("SZ399001").unwrap(), "1399001");
        assert_eq!(t.transform("HKHSI").unwrap(), "hkHSI");
        assert_eq!(t.transform("USDJI").unwrap(), "US_DJI");
    }

    #[test]
    fn test_api_code_transform() {
        let t = NeteaseApiCodeTransform;
        assert_eq!(t.transform("0510500").unwrap(), "SH510500");
        assert_eq!(t.transform("1399001").unwrap(), "SZ399001");
        assert_eq!(t.transform("hkHSI").unwrap(), "HKHSI");
        assert_eq!(t.transform("US_DJI").unwrap(), "USDJI");
    }

    #[test]
    fn test_search_code_transform() {
        let t = NeteaseSearchCodeTransform;
        assert_eq!(t.transform("", "SZ", "399001"), "SZ399001");
        assert_eq!(t.transform("SH", "", "510500"), "SH510500");
        assert_eq!(t.transform("", "US", "DJI"), "");
    }
}