swift_mt_message/fields/
field75.rs

1use super::swift_utils::parse_swift_chars;
2use crate::errors::ParseError;
3use crate::traits::SwiftField;
4use serde::{Deserialize, Serialize};
5
6/// **Field 75: Queries**
7///
8/// Query information in MT n95 series messages for requesting clarification,
9/// status updates, or additional details on transactions.
10///
11/// **Format:** `6*35x` (max 6 lines, 35 chars each)
12/// **Used in:** MT 195, 295, 395, 495, 595, 695, 795, 895, 995 (query messages)
13///
14/// **Example:**
15/// ```text
16/// :75:QUERY: TRANSACTION STATUS
17/// REF: MT103 20240719001
18/// PLEASE CONFIRM
19/// ```
20
21#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
22pub struct Field75 {
23    /// Query information (max 6 lines, 35 chars each)
24    pub information: Vec<String>,
25}
26
27impl SwiftField for Field75 {
28    fn parse(input: &str) -> crate::Result<Self>
29    where
30        Self: Sized,
31    {
32        let mut information = Vec::new();
33
34        // Parse up to 6 lines of 35 characters each
35        for line in input.lines() {
36            if information.len() >= 6 {
37                break;
38            }
39
40            if line.len() > 35 {
41                return Err(ParseError::InvalidFormat {
42                    message: format!(
43                        "Field75 line cannot exceed 35 characters, found {}",
44                        line.len()
45                    ),
46                });
47            }
48
49            // Validate SWIFT character set
50            parse_swift_chars(line, "Field75 line")?;
51            information.push(line.to_string());
52        }
53
54        if information.is_empty() {
55            return Err(ParseError::InvalidFormat {
56                message: "Field75 requires at least one line of information".to_string(),
57            });
58        }
59
60        Ok(Field75 { information })
61    }
62
63    fn to_swift_string(&self) -> String {
64        let content = self.information.join("\n");
65        format!(":75:{}", content)
66    }
67}
68
69#[cfg(test)]
70mod tests {
71    use super::*;
72
73    #[test]
74    fn test_field75_parse() {
75        let field =
76            Field75::parse("QUERY: TRANSACTION STATUS\nREF: MT103 20240719001\nPLEASE CONFIRM")
77                .unwrap();
78        assert_eq!(field.information.len(), 3);
79        assert_eq!(field.information[0], "QUERY: TRANSACTION STATUS");
80        assert_eq!(field.information[1], "REF: MT103 20240719001");
81        assert_eq!(field.information[2], "PLEASE CONFIRM");
82
83        // Single line
84        let field = Field75::parse("STATUS REQUEST").unwrap();
85        assert_eq!(field.information.len(), 1);
86        assert_eq!(field.information[0], "STATUS REQUEST");
87    }
88
89    #[test]
90    fn test_field75_to_swift_string() {
91        let field = Field75 {
92            information: vec![
93                "QUERY: TRANSACTION STATUS".to_string(),
94                "REF: MT103 20240719001".to_string(),
95                "PLEASE CONFIRM".to_string(),
96            ],
97        };
98        assert_eq!(
99            field.to_swift_string(),
100            ":75:QUERY: TRANSACTION STATUS\nREF: MT103 20240719001\nPLEASE CONFIRM"
101        );
102    }
103
104    #[test]
105    fn test_field75_parse_invalid() {
106        // Empty input
107        assert!(Field75::parse("").is_err());
108
109        // Line too long (over 35 characters)
110        assert!(
111            Field75::parse(
112                "THIS LINE IS DEFINITELY TOO LONG AND EXCEEDS THE THIRTY FIVE CHARACTER LIMIT"
113            )
114            .is_err()
115        );
116    }
117}