ccxt_core/
parser_utils.rs1use rust_decimal::Decimal;
7use rust_decimal::prelude::{FromPrimitive, FromStr};
8use serde_json::Value;
9use std::collections::HashMap;
10
11pub fn parse_decimal(data: &Value, key: &str) -> Option<Decimal> {
15 data.get(key).and_then(|v| {
16 if let Some(num) = v.as_f64() {
17 Decimal::from_f64(num)
18 } else if let Some(s) = v.as_str() {
19 if s.is_empty() {
20 None
21 } else {
22 Decimal::from_str(s).ok()
23 }
24 } else {
25 None
26 }
27 })
28}
29
30pub fn parse_timestamp(data: &Value, key: &str) -> Option<i64> {
32 data.get(key).and_then(|v| {
33 v.as_i64()
34 .or_else(|| v.as_str().and_then(|s| s.parse::<i64>().ok()))
35 })
36}
37
38pub fn value_to_hashmap(data: &Value) -> HashMap<String, Value> {
40 data.as_object()
41 .map(|obj| obj.iter().map(|(k, v)| (k.clone(), v.clone())).collect())
42 .unwrap_or_default()
43}
44
45pub fn timestamp_to_datetime(timestamp: i64) -> Option<String> {
47 chrono::DateTime::from_timestamp_millis(timestamp)
48 .map(|dt| dt.format("%Y-%m-%dT%H:%M:%S%.3fZ").to_string())
49}
50
51pub fn datetime_to_timestamp(datetime: &str) -> Option<i64> {
53 chrono::DateTime::parse_from_rfc3339(datetime)
54 .ok()
55 .map(|dt| dt.timestamp_millis())
56}
57
58#[cfg(test)]
59mod tests {
60 use super::*;
61 use serde_json::json;
62
63 #[test]
64 fn test_parse_decimal_from_string() {
65 let data = json!({"price": "123.45"});
66 assert_eq!(
67 parse_decimal(&data, "price"),
68 Some(Decimal::from_str("123.45").unwrap())
69 );
70 }
71
72 #[test]
73 fn test_parse_decimal_from_number() {
74 let data = json!({"price": 123.45});
75 assert!(parse_decimal(&data, "price").is_some());
76 }
77
78 #[test]
79 fn test_parse_decimal_empty_string() {
80 let data = json!({"price": ""});
81 assert_eq!(parse_decimal(&data, "price"), None);
82 }
83
84 #[test]
85 fn test_parse_decimal_missing_key() {
86 let data = json!({"other": "123"});
87 assert_eq!(parse_decimal(&data, "price"), None);
88 }
89
90 #[test]
91 fn test_parse_timestamp_from_number() {
92 let data = json!({"time": 1704110400000i64});
93 assert_eq!(parse_timestamp(&data, "time"), Some(1704110400000));
94 }
95
96 #[test]
97 fn test_parse_timestamp_from_string() {
98 let data = json!({"time": "1704110400000"});
99 assert_eq!(parse_timestamp(&data, "time"), Some(1704110400000));
100 }
101
102 #[test]
103 fn test_value_to_hashmap() {
104 let data = json!({"a": 1, "b": "two"});
105 let map = value_to_hashmap(&data);
106 assert_eq!(map.len(), 2);
107 assert_eq!(map.get("a"), Some(&json!(1)));
108 }
109
110 #[test]
111 fn test_timestamp_to_datetime() {
112 let result = timestamp_to_datetime(1704110400000);
113 assert!(result.is_some());
114 assert!(result.unwrap().contains("2024-01-01"));
115 }
116
117 #[test]
118 fn test_datetime_to_timestamp() {
119 let result = datetime_to_timestamp("2024-01-01T12:00:00.000Z");
120 assert!(result.is_some());
121 }
122}