use serde_json::{Value, json};
use tushare_api::{
DeriveFromTushareData, FromOptionalTushareValue, FromTushareValue, TushareError,
};
#[derive(Debug, Clone, PartialEq)]
pub struct SimpleDecimal(f64);
impl FromTushareValue for SimpleDecimal {
fn from_tushare_value(value: &Value) -> Result<Self, TushareError> {
match value {
Value::String(s) => s
.parse::<f64>()
.map(SimpleDecimal)
.map_err(|e| TushareError::ParseError(format!("Failed to parse: {}", e))),
Value::Number(n) => {
if let Some(f) = n.as_f64() {
Ok(SimpleDecimal(f))
} else {
Err(TushareError::ParseError("Invalid number".to_string()))
}
}
_ => Err(TushareError::ParseError("Invalid value".to_string())),
}
}
}
impl FromOptionalTushareValue for SimpleDecimal {
fn from_optional_tushare_value(value: &Value) -> Result<Option<Self>, TushareError> {
if value.is_null() {
Ok(None)
} else {
SimpleDecimal::from_tushare_value(value).map(Some)
}
}
}
#[derive(Debug, Clone, DeriveFromTushareData)]
pub struct SimpleStock {
#[tushare(field = "code")]
stock_code: String,
#[tushare(field = "price")]
stock_price: SimpleDecimal,
#[tushare(field = "volume")]
stock_volume: Option<SimpleDecimal>,
}
#[cfg(test)]
mod tests {
use super::*;
use tushare_api::traits::FromTushareData;
#[test]
fn test_simple_custom_type() {
let fields = vec![
"code".to_string(),
"price".to_string(),
"volume".to_string(),
];
let values = vec![json!("000001.SZ"), json!("10.50"), json!("1000000")];
let stock = SimpleStock::from_row(&fields, &values).unwrap();
assert_eq!(stock.stock_code, "000001.SZ");
assert_eq!(stock.stock_price.0, 10.50);
assert!(stock.stock_volume.is_some());
assert_eq!(stock.stock_volume.unwrap().0, 1000000.0);
}
#[test]
fn test_missing_optional_field() {
let fields = vec![
"code".to_string(),
"price".to_string(),
];
let values = vec![json!("000001.SZ"), json!("10.50")];
let stock = SimpleStock::from_row(&fields, &values).unwrap();
assert_eq!(stock.stock_code, "000001.SZ");
assert_eq!(stock.stock_price.0, 10.50);
assert!(stock.stock_volume.is_none());
}
}
fn main() {
println!("Debug test for custom types");
}