swift_mt_message/parser/
utils.rs1use super::MessageParser;
2use crate::errors::ParseError;
3use crate::traits::SwiftField;
4
5pub fn extract_block4(input: &str) -> Result<String, ParseError> {
9 if input.starts_with("{") {
10 super::SwiftParser::extract_block(input, 4)?.ok_or_else(|| ParseError::InvalidFormat {
11 message: "Block 4 not found".to_string(),
12 })
13 } else {
14 Ok(input.to_string())
15 }
16}
17
18pub fn append_field<T: SwiftField>(result: &mut String, field: &T) {
20 result.push_str(&field.to_swift_string());
21 result.push_str("\r\n");
22}
23
24pub fn append_optional_field<T: SwiftField>(result: &mut String, field: &Option<T>) {
26 if let Some(f) = field {
27 result.push_str(&f.to_swift_string());
28 result.push_str("\r\n");
29 }
30}
31
32pub fn append_vec_field<T: SwiftField>(result: &mut String, fields: &Option<Vec<T>>) {
34 if let Some(vec) = fields {
35 for field in vec {
36 result.push_str(&field.to_swift_string());
37 result.push_str("\r\n");
38 }
39 }
40}
41
42pub fn parse_repeated_field<T: crate::traits::SwiftField>(
45 parser: &mut MessageParser,
46 tag: &str,
47) -> Result<Option<Vec<T>>, ParseError> {
48 let mut fields = Vec::new();
49 while let Ok(field) = parser.parse_field::<T>(tag) {
50 fields.push(field);
51 }
52 Ok(if fields.is_empty() {
53 None
54 } else {
55 Some(fields)
56 })
57}
58
59pub fn verify_parser_complete(parser: &MessageParser) -> Result<(), ParseError> {
62 if !parser.is_complete() {
63 return Err(ParseError::InvalidFormat {
64 message: format!(
65 "Unparsed content remaining in message: {}",
66 parser.remaining()
67 ),
68 });
69 }
70 Ok(())
71}
72
73pub fn remove_trailing_crlf(result: &mut String) {
75 if result.ends_with("\r\n") {
76 result.truncate(result.len() - 2);
77 }
78}
79
80pub fn finalize_mt_string(mut result: String, add_terminator: bool) -> String {
82 remove_trailing_crlf(&mut result);
83 if add_terminator {
84 result.push('-');
85 }
86 result
87}
88
89#[cfg(test)]
90mod tests {
91 use super::*;
92
93 #[test]
94 fn test_extract_block4_with_blocks() {
95 let input = "{1:F01BANKFRPPAXXX0000000000}{4:\r\n:20:TEST123\r\n-}";
96 let result = extract_block4(input);
97 assert!(result.is_ok());
98 assert!(result.unwrap().contains(":20:TEST123"));
99 }
100
101 #[test]
102 fn test_extract_block4_plain() {
103 let input = ":20:TEST123\r\n";
104 let result = extract_block4(input);
105 assert!(result.is_ok());
106 assert_eq!(result.unwrap(), input);
107 }
108
109 #[test]
110 fn test_extract_block4_missing() {
111 let input = "{1:F01BANKFRPPAXXX0000000000}";
112 let result = extract_block4(input);
113 assert!(result.is_err());
114 }
115
116 #[test]
117 fn test_remove_trailing_crlf() {
118 let mut s = String::from("test\r\n");
119 remove_trailing_crlf(&mut s);
120 assert_eq!(s, "test");
121
122 let mut s2 = String::from("test");
123 remove_trailing_crlf(&mut s2);
124 assert_eq!(s2, "test");
125 }
126
127 #[test]
128 fn test_finalize_mt_string() {
129 let result = finalize_mt_string(String::from("test\r\n"), true);
130 assert_eq!(result, "test-");
131
132 let result2 = finalize_mt_string(String::from("test\r\n"), false);
133 assert_eq!(result2, "test");
134 }
135}