finance_query_core/models/
movers.rs1use serde::{Deserialize, Serialize};
2
3#[derive(Debug, Clone, Copy, Serialize, Deserialize, Default)]
4#[serde(rename_all = "snake_case")]
5pub enum MoverCount {
6 #[serde(rename = "25")]
7 TwentyFive,
8 #[serde(rename = "50")]
9 #[default]
10 Fifty,
11 #[serde(rename = "100")]
12 Hundred,
13}
14
15impl MoverCount {
16 pub fn as_str(&self) -> &'static str {
17 match self {
18 MoverCount::TwentyFive => "25",
19 MoverCount::Fifty => "50",
20 MoverCount::Hundred => "100",
21 }
22 }
23
24 pub fn parse(s: &str) -> Option<Self> {
25 match s {
26 "25" => Some(MoverCount::TwentyFive),
27 "50" => Some(MoverCount::Fifty),
28 "100" => Some(MoverCount::Hundred),
29 _ => None,
30 }
31 }
32}
33
34#[derive(Debug, Clone, Serialize, Deserialize)]
35#[serde(rename_all = "snake_case")]
36pub struct MarketMover {
37 pub symbol: String,
38 pub name: String,
39 pub price: String,
40 pub change: String,
41 #[serde(rename = "percentChange")]
42 pub percent_change: String,
43}
44
45#[cfg(test)]
46mod tests {
47 use super::*;
48 use proptest::prelude::*;
49
50 proptest! {
53 #![proptest_config(ProptestConfig::with_cases(100))]
54
55 #[test]
56 fn market_mover_roundtrip(
57 symbol in "[A-Z]{1,5}",
58 name in "[A-Za-z ]{1,50}",
59 price in "[0-9]{1,4}\\.[0-9]{2}",
60 change in "-?[0-9]{1,3}\\.[0-9]{2}",
61 percent_change in "-?[0-9]{1,3}\\.[0-9]{2}%",
62 ) {
63 let mover = MarketMover {
64 symbol: symbol.clone(),
65 name: name.clone(),
66 price: price.clone(),
67 change: change.clone(),
68 percent_change: percent_change.clone(),
69 };
70
71 let json = serde_json::to_string(&mover).unwrap();
72 let parsed: MarketMover = serde_json::from_str(&json).unwrap();
73
74 prop_assert_eq!(mover.symbol, parsed.symbol);
75 prop_assert_eq!(mover.name, parsed.name);
76 prop_assert_eq!(mover.price, parsed.price);
77 prop_assert_eq!(mover.change, parsed.change);
78 prop_assert_eq!(mover.percent_change, parsed.percent_change);
79 }
80
81 #[test]
82 fn mover_count_roundtrip(count in prop_oneof![
83 Just(MoverCount::TwentyFive),
84 Just(MoverCount::Fifty),
85 Just(MoverCount::Hundred),
86 ]) {
87 let json = serde_json::to_string(&count).unwrap();
88 let parsed: MoverCount = serde_json::from_str(&json).unwrap();
89
90 prop_assert_eq!(count.as_str(), parsed.as_str());
91 }
92 }
93}