swift_mt_message/fields/
field77.rs1use super::field_utils::validate_multiline_text;
2use crate::errors::ParseError;
3use crate::traits::SwiftField;
4use serde::{Deserialize, Serialize};
5
6#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
12pub struct Field77T {
13    pub envelope_content: String,
15}
16
17impl SwiftField for Field77T {
18    fn parse(input: &str) -> crate::Result<Self>
19    where
20        Self: Sized,
21    {
22        if input.is_empty() {
23            return Err(ParseError::InvalidFormat {
24                message: "Field 77T cannot be empty".to_string(),
25            });
26        }
27
28        if input.len() > 9000 {
29            return Err(ParseError::InvalidFormat {
30                message: format!("Field 77T exceeds 9000 characters, found {}", input.len()),
31            });
32        }
33
34        Ok(Field77T {
38            envelope_content: input.to_string(),
39        })
40    }
41
42    fn to_swift_string(&self) -> String {
43        format!(":77T:{}", self.envelope_content)
44    }
45}
46
47#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
53pub struct Field77A {
54    pub narrative: Vec<String>,
56}
57
58impl SwiftField for Field77A {
59    fn parse(input: &str) -> crate::Result<Self>
60    where
61        Self: Sized,
62    {
63        let lines: Vec<&str> = input.lines().collect();
64        let narrative = validate_multiline_text(&lines, 20, 35, "Field 77A")?;
65        Ok(Field77A { narrative })
66    }
67
68    fn to_swift_string(&self) -> String {
69        format!(":77A:{}", self.narrative.join("\n"))
70    }
71}
72
73#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
79pub struct Field77B {
80    pub narrative: Vec<String>,
82}
83
84impl SwiftField for Field77B {
85    fn parse(input: &str) -> crate::Result<Self>
86    where
87        Self: Sized,
88    {
89        let lines: Vec<&str> = input.lines().collect();
90        let narrative = validate_multiline_text(&lines, 3, 35, "Field 77B")?;
91        Ok(Field77B { narrative })
92    }
93
94    fn to_swift_string(&self) -> String {
95        format!(":77B:{}", self.narrative.join("\n"))
96    }
97}
98
99#[cfg(test)]
100mod tests {
101    use super::*;
102
103    #[test]
104    fn test_field77t_valid() {
105        let content = "This is envelope content with multiple lines\nAnd special characters\nRegulatory information";
106        let field = Field77T::parse(content).unwrap();
107        assert_eq!(field.envelope_content, content);
108        assert_eq!(field.to_swift_string(), format!(":77T:{}", content));
109
110        let large_content = "x".repeat(9000);
112        let field = Field77T::parse(&large_content).unwrap();
113        assert_eq!(field.envelope_content.len(), 9000);
114    }
115
116    #[test]
117    fn test_field77t_invalid() {
118        assert!(Field77T::parse("").is_err());
120
121        let content = "x".repeat(9001);
123        assert!(Field77T::parse(&content).is_err());
124    }
125
126    #[test]
127    fn test_field77a_valid() {
128        let field = Field77A::parse("LINE 1\nLINE 2\nLINE 3").unwrap();
129        assert_eq!(field.narrative.len(), 3);
130        assert_eq!(field.narrative[0], "LINE 1");
131        assert_eq!(field.narrative[1], "LINE 2");
132        assert_eq!(field.narrative[2], "LINE 3");
133
134        let field = Field77A::parse("SINGLE LINE").unwrap();
136        assert_eq!(field.narrative.len(), 1);
137
138        let mut lines = Vec::new();
140        for i in 1..=20 {
141            lines.push(format!("LINE {}", i));
142        }
143        let field = Field77A::parse(&lines.join("\n")).unwrap();
144        assert_eq!(field.narrative.len(), 20);
145    }
146
147    #[test]
148    fn test_field77a_invalid() {
149        assert!(Field77A::parse("").is_err());
151
152        let mut lines = Vec::new();
154        for i in 1..=21 {
155            lines.push(format!("LINE {}", i));
156        }
157        assert!(Field77A::parse(&lines.join("\n")).is_err());
158
159        assert!(
161            Field77A::parse("THIS LINE IS TOO LONG AND EXCEEDS THE 35 CHARACTER LIMIT").is_err()
162        );
163    }
164
165    #[test]
166    fn test_field77b_valid() {
167        let field = Field77B::parse("LINE 1\nLINE 2\nLINE 3").unwrap();
168        assert_eq!(field.narrative.len(), 3);
169        assert_eq!(field.narrative[0], "LINE 1");
170        assert_eq!(field.narrative[1], "LINE 2");
171        assert_eq!(field.narrative[2], "LINE 3");
172
173        let field = Field77B::parse("SINGLE LINE").unwrap();
175        assert_eq!(field.narrative.len(), 1);
176    }
177
178    #[test]
179    fn test_field77b_invalid() {
180        assert!(Field77B::parse("").is_err());
182
183        assert!(Field77B::parse("L1\nL2\nL3\nL4").is_err());
185
186        assert!(
188            Field77B::parse("THIS LINE IS TOO LONG AND EXCEEDS THE 35 CHARACTER LIMIT").is_err()
189        );
190    }
191}