1use std::str::FromStr;
2
3#[derive(Debug, PartialEq)]
5pub struct Statement {
6 pub symbol: String,
7 pub weight: f64,
8}
9
10impl FromStr for Statement {
11 type Err = &'static str;
12
13 fn from_str(s: &str) -> Result<Self, Self::Err> {
14 let parts: Vec<&str> = s.split("::").map(str::trim).collect();
15 if parts.len() != 2 {
16 return Err("Invalid format: Expected 'SYMBOL::WEIGHT'");
17 }
18
19 let symbol = parts[0].to_string();
20 let weight: f64 = parts[1].parse().map_err(|_| "Invalid weight")?;
21
22 Ok(Statement { symbol, weight })
23 }
24}
25
26pub fn parse_statements(input: &str) -> Result<Vec<Statement>, &'static str> {
28 input
29 .split(';')
30 .filter(|s| !s.trim().is_empty()) .map(|s| s.parse())
32 .collect()
33}
34
35pub fn serialize_statements(statements: &[Statement]) -> String {
37 statements
38 .iter()
39 .map(|s| format!("{}::{}", s.symbol.trim(), s.weight))
40 .collect::<Vec<_>>()
41 .join(";")
42}
43
44#[cfg(test)]
45mod tests {
46 use super::*;
47
48 #[test]
49 fn test_parse_statements() {
50 let input = " AAPL :: 0.25 ; TSLA::0.15 ; GOOGL::0.60 ";
51 let expected = vec![
52 Statement {
53 symbol: "AAPL".to_string(),
54 weight: 0.25,
55 },
56 Statement {
57 symbol: "TSLA".to_string(),
58 weight: 0.15,
59 },
60 Statement {
61 symbol: "GOOGL".to_string(),
62 weight: 0.60,
63 },
64 ];
65
66 let result = parse_statements(input);
67 assert_eq!(result, Ok(expected));
68 }
69
70 #[test]
71 fn test_serialize_statements() {
72 let statements = vec![
73 Statement {
74 symbol: "AAPL".to_string(),
75 weight: 0.25,
76 },
77 Statement {
78 symbol: "TSLA".to_string(),
79 weight: 0.15,
80 },
81 Statement {
82 symbol: "GOOGL".to_string(),
83 weight: 0.60,
84 },
85 ];
86
87 let expected = "AAPL::0.25;TSLA::0.15;GOOGL::0.6";
88 let result = serialize_statements(&statements);
89 assert_eq!(result, expected);
90 }
91
92 #[test]
93 fn test_parse_invalid_format() {
94 let input = "INVALID";
95 let result = parse_statements(input);
96 assert!(result.is_err());
97 }
98
99 #[test]
100 fn test_parse_empty_input() {
101 let input = "";
102 let result = parse_statements(input);
103 assert_eq!(result, Ok(vec![]));
104 }
105
106 #[test]
107 fn test_parse_extra_whitespace() {
108 let input = " MSFT :: 1.0 ; AMZN::0.5 ";
109 let expected = vec![
110 Statement {
111 symbol: "MSFT".to_string(),
112 weight: 1.0,
113 },
114 Statement {
115 symbol: "AMZN".to_string(),
116 weight: 0.5,
117 },
118 ];
119 let result = parse_statements(input);
120 assert_eq!(result, Ok(expected));
121 }
122
123 #[test]
124 fn test_serialize_empty_list() {
125 let statements = vec![];
126 let result = serialize_statements(&statements);
127 assert_eq!(result, "");
128 }
129}