swift_mt_message/fields/
field34.rs1use super::swift_utils::{parse_amount, parse_currency};
2use crate::errors::ParseError;
3use crate::traits::SwiftField;
4use serde::{Deserialize, Serialize};
5
6#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
19pub struct Field34F {
20 pub currency: String,
22
23 pub indicator: Option<char>,
25
26 pub amount: f64,
28}
29
30impl SwiftField for Field34F {
31 fn parse(input: &str) -> crate::Result<Self>
32 where
33 Self: Sized,
34 {
35 if input.len() < 4 {
37 return Err(ParseError::InvalidFormat {
39 message: format!(
40 "Field 34F must be at least 4 characters, found {}",
41 input.len()
42 ),
43 });
44 }
45
46 let currency = parse_currency(&input[0..3])?;
48
49 let (indicator, amount_start) = if input.len() > 3 {
51 let fourth_char = input.chars().nth(3).unwrap();
52 if fourth_char == 'D' || fourth_char == 'C' {
53 (Some(fourth_char), 4)
54 } else {
55 (None, 3)
56 }
57 } else {
58 (None, 3)
59 };
60
61 let amount_str = &input[amount_start..];
63 if amount_str.is_empty() {
64 return Err(ParseError::InvalidFormat {
65 message: "Field 34F amount cannot be empty".to_string(),
66 });
67 }
68
69 let amount = parse_amount(amount_str)?;
70
71 if amount <= 0.0 {
73 return Err(ParseError::InvalidFormat {
74 message: "Field 34F amount must be greater than zero".to_string(),
75 });
76 }
77
78 Ok(Field34F {
79 currency,
80 indicator,
81 amount,
82 })
83 }
84
85 fn to_swift_string(&self) -> String {
86 let indicator_str = self.indicator.map_or(String::new(), |c| c.to_string());
87 format!(
88 ":34F:{}{}{}",
89 self.currency,
90 indicator_str,
91 super::swift_utils::format_swift_amount(self.amount, 2)
92 )
93 }
94}
95
96#[cfg(test)]
97mod tests {
98 use super::*;
99
100 #[test]
101 fn test_field34f_valid() {
102 let field = Field34F::parse("USD5000,00").unwrap();
104 assert_eq!(field.currency, "USD");
105 assert_eq!(field.indicator, None);
106 assert_eq!(field.amount, 5000.00);
107 assert_eq!(field.to_swift_string(), ":34F:USD5000");
108
109 let field = Field34F::parse("USDD2500,00").unwrap();
111 assert_eq!(field.currency, "USD");
112 assert_eq!(field.indicator, Some('D'));
113 assert_eq!(field.amount, 2500.00);
114
115 let field = Field34F::parse("EURC1000,00").unwrap();
117 assert_eq!(field.currency, "EUR");
118 assert_eq!(field.indicator, Some('C'));
119 assert_eq!(field.amount, 1000.00);
120
121 let field = Field34F::parse("GBP10000,00").unwrap();
123 assert_eq!(field.currency, "GBP");
124 assert_eq!(field.indicator, None);
125 assert_eq!(field.amount, 10000.00);
126 }
127
128 #[test]
129 fn test_field34f_invalid() {
130 assert!(Field34F::parse("12A100").is_err());
132 assert!(Field34F::parse("US100").is_err());
133
134 assert!(Field34F::parse("USDX100").is_err());
136
137 assert!(Field34F::parse("USD0").is_err());
139 assert!(Field34F::parse("USDD0").is_err());
140
141 assert!(Field34F::parse("USD-100").is_err());
143
144 assert!(Field34F::parse("USD").is_err());
146 assert!(Field34F::parse("USDD").is_err());
147 }
148}