swift_mt_message/fields/
field86.rs1use super::swift_utils::parse_swift_chars;
2use crate::errors::ParseError;
3use crate::traits::SwiftField;
4use serde::{Deserialize, Serialize};
5
6#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
22pub struct Field86 {
23 pub narrative: Vec<String>,
25}
26
27impl SwiftField for Field86 {
28 fn parse(input: &str) -> crate::Result<Self>
29 where
30 Self: Sized,
31 {
32 let mut lines = Vec::new();
33
34 for line in input.lines().take(6) {
36 if line.len() > 65 {
38 return Err(ParseError::InvalidFormat {
39 message: format!("Field 86 line exceeds 65 characters: {}", line.len()),
40 });
41 }
42
43 parse_swift_chars(line, "Field 86 line")?;
45
46 lines.push(line.to_string());
47 }
48
49 if lines.is_empty() {
50 return Err(ParseError::InvalidFormat {
51 message: "Field 86 must contain at least one line".to_string(),
52 });
53 }
54
55 Ok(Field86 { narrative: lines })
56 }
57
58 fn to_swift_string(&self) -> String {
59 let content = self.narrative.join("\n");
60 format!(":86:{}", content)
61 }
62}
63
64#[cfg(test)]
65mod tests {
66 use super::*;
67
68 #[test]
69 fn test_field86_parse_single_line() {
70 let field = Field86::parse("PAYMENT RECEIVED FROM ABC COMPANY FOR INVOICE 12345").unwrap();
71 assert_eq!(field.narrative.len(), 1);
72 assert_eq!(
73 field.narrative[0],
74 "PAYMENT RECEIVED FROM ABC COMPANY FOR INVOICE 12345"
75 );
76 }
77
78 #[test]
79 fn test_field86_parse_multiple_lines() {
80 let input = "TRANSACTION DETAILS:\nCOUNTERPARTY: ABC CORP\nREFERENCE: PAY-2023-12345\nDESCRIPTION: MONTHLY SERVICE FEE";
81 let field = Field86::parse(input).unwrap();
82 assert_eq!(field.narrative.len(), 4);
83 assert_eq!(field.narrative[0], "TRANSACTION DETAILS:");
84 assert_eq!(field.narrative[1], "COUNTERPARTY: ABC CORP");
85 assert_eq!(field.narrative[2], "REFERENCE: PAY-2023-12345");
86 assert_eq!(field.narrative[3], "DESCRIPTION: MONTHLY SERVICE FEE");
87 }
88
89 #[test]
90 fn test_field86_line_too_long() {
91 let long_line = "THIS LINE IS MUCH TOO LONG TO BE ACCEPTED IN FIELD 86 AS IT EXCEEDS THE 65 CHARACTER LIMIT SIGNIFICANTLY";
92 assert!(Field86::parse(long_line).is_err());
93 }
94
95 #[test]
96 fn test_field86_max_line_length() {
97 let line_65_chars = "12345678901234567890123456789012345678901234567890123456789012345";
99 let field = Field86::parse(line_65_chars).unwrap();
100 assert_eq!(field.narrative[0], line_65_chars);
101 }
102
103 #[test]
104 fn test_field86_max_lines() {
105 let input = "LINE 1\nLINE 2\nLINE 3\nLINE 4\nLINE 5\nLINE 6";
106 let field = Field86::parse(input).unwrap();
107 assert_eq!(field.narrative.len(), 6);
108 assert_eq!(field.narrative[0], "LINE 1");
109 assert_eq!(field.narrative[5], "LINE 6");
110 }
111
112 #[test]
113 fn test_field86_empty_input() {
114 assert!(Field86::parse("").is_err());
115 }
116
117 #[test]
118 fn test_field86_to_swift_string() {
119 let field = Field86 {
120 narrative: vec![
121 "WIRE TRANSFER RECEIVED".to_string(),
122 "FROM: INTERNATIONAL BANK".to_string(),
123 "PURPOSE: TRADE SETTLEMENT".to_string(),
124 ],
125 };
126 let expected =
127 ":86:WIRE TRANSFER RECEIVED\nFROM: INTERNATIONAL BANK\nPURPOSE: TRADE SETTLEMENT";
128 assert_eq!(field.to_swift_string(), expected);
129 }
130
131 #[test]
132 fn test_field86_single_line_to_swift_string() {
133 let field = Field86 {
134 narrative: vec!["DIRECT DEBIT AUTHORIZATION PAYMENT".to_string()],
135 };
136 assert_eq!(
137 field.to_swift_string(),
138 ":86:DIRECT DEBIT AUTHORIZATION PAYMENT"
139 );
140 }
141
142 #[test]
143 fn test_field86_account_holder_information() {
144 let field = Field86 {
145 narrative: vec![
146 "ACCOUNT BALANCE UPDATE".to_string(),
147 "INTEREST CREDITED: USD 125.50".to_string(),
148 "ANNUAL RATE: 2.5%".to_string(),
149 "CALCULATION PERIOD: Q4 2023".to_string(),
150 ],
151 };
152
153 let expected = ":86:ACCOUNT BALANCE UPDATE\nINTEREST CREDITED: USD 125.50\nANNUAL RATE: 2.5%\nCALCULATION PERIOD: Q4 2023";
154 assert_eq!(field.to_swift_string(), expected);
155 assert_eq!(field.narrative.len(), 4);
156 }
157}