use serde::Deserialize;
#[derive(Debug, Clone, Deserialize)]
pub struct KlineData {
#[serde(rename = "start")]
#[serde(default)]
pub start: Option<i64>,
#[serde(rename = "end")]
#[serde(default)]
pub end: Option<i64>,
#[serde(rename = "interval")]
#[serde(default)]
pub interval: Option<String>,
#[serde(rename = "open")]
#[serde(default)]
pub open: Option<String>,
#[serde(rename = "close")]
#[serde(default)]
pub close: Option<String>,
#[serde(rename = "high")]
#[serde(default)]
pub high: Option<String>,
#[serde(rename = "low")]
#[serde(default)]
pub low: Option<String>,
#[serde(rename = "volume")]
#[serde(default)]
pub volume: Option<String>,
#[serde(rename = "turnover")]
#[serde(default)]
pub turnover: Option<String>,
#[serde(rename = "confirm")]
#[serde(default)]
pub confirm: Option<bool>,
#[serde(rename = "timestamp")]
#[serde(default)]
pub timestamp: Option<i64>,
}
pub struct KlineStream;
impl KlineStream {
pub fn parse(data: &serde_json::Value) -> serde_json::Result<Vec<KlineData>> {
serde_json::from_value(data.clone())
}
pub fn parse_single(data: &serde_json::Value) -> serde_json::Result<KlineData> {
let mut klines: Vec<KlineData> = serde_json::from_value(data.clone())?;
klines
.pop()
.ok_or_else(|| serde::de::Error::custom("empty kline array"))
}
pub fn matches_topic(topic: &str) -> bool {
topic.starts_with("kline.")
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_parse_kline() {
let json = serde_json::json!([{
"start": 1672828800000_i64,
"end": 1672832400000_i64,
"interval": "60",
"open": "50000.00",
"close": "50100.00",
"high": "50200.00",
"low": "49900.00",
"volume": "150.5",
"turnover": "7525000.00",
"confirm": false,
"timestamp": 1672832100000_i64
}]);
let kline = KlineStream::parse_single(&json).unwrap();
assert_eq!(kline.open.as_deref(), Some("50000.00"));
assert_eq!(kline.close.as_deref(), Some("50100.00"));
assert_eq!(kline.confirm, Some(false));
}
#[test]
fn test_matches_topic() {
assert!(KlineStream::matches_topic("kline.1.BTCUSDT"));
assert!(KlineStream::matches_topic("kline.D.ETHUSDT"));
assert!(!KlineStream::matches_topic("tickers.BTCUSDT"));
}
}