swift_mt_message/messages/
mod.rs

1//! SWIFT MT message implementations
2
3use serde::{Deserialize, Serialize};
4
5use crate::common::{Field, MessageBlock};
6use crate::error::{MTError, Result};
7
8// Import all message types
9pub mod mt102;
10pub mod mt103;
11pub mod mt192;
12pub mod mt195;
13pub mod mt196;
14pub mod mt197;
15pub mod mt199;
16pub mod mt202;
17pub mod mt940;
18pub mod mt941;
19pub mod mt942;
20
21// Re-export message types
22pub use mt102::MT102;
23pub use mt103::MT103;
24pub use mt192::MT192;
25pub use mt195::MT195;
26pub use mt196::MT196;
27pub use mt197::MT197;
28pub use mt199::MT199;
29pub use mt202::MT202;
30pub use mt940::MT940;
31pub use mt941::MT941;
32pub use mt942::MT942;
33
34/// Main enum representing all supported MT message types
35#[derive(Debug, Clone, Serialize, Deserialize)]
36pub enum MTMessage {
37    /// MT102: Multiple Customer Credit Transfer
38    MT102(MT102),
39    /// MT103: Single Customer Credit Transfer
40    MT103(MT103),
41    /// MT192: Request for Cancellation
42    MT192(MT192),
43    /// MT195: Queries
44    MT195(MT195),
45    /// MT196: Answers
46    MT196(MT196),
47    /// MT197: Copy of a Message
48    MT197(MT197),
49    /// MT199: Free Format Message
50    MT199(MT199),
51    /// MT202: General Financial Institution Transfer
52    MT202(MT202),
53    /// MT940: Customer Statement Message
54    MT940(MT940),
55    /// MT941: Balance Report Message
56    MT941(MT941),
57    /// MT942: Interim Transaction Report
58    MT942(MT942),
59}
60
61impl MTMessage {
62    /// Get the message type as a string
63    pub fn message_type(&self) -> &'static str {
64        match self {
65            MTMessage::MT102(_) => "102",
66            MTMessage::MT103(_) => "103",
67            MTMessage::MT192(_) => "192",
68            MTMessage::MT195(_) => "195",
69            MTMessage::MT196(_) => "196",
70            MTMessage::MT197(_) => "197",
71            MTMessage::MT199(_) => "199",
72            MTMessage::MT202(_) => "202",
73            MTMessage::MT940(_) => "940",
74            MTMessage::MT941(_) => "941",
75            MTMessage::MT942(_) => "942",
76        }
77    }
78
79    /// Get a field by tag from the message
80    pub fn get_field(&self, tag: &str) -> Option<&Field> {
81        match self {
82            MTMessage::MT102(msg) => msg.get_field(tag),
83            MTMessage::MT103(msg) => msg.get_field(tag),
84            MTMessage::MT192(msg) => msg.get_field(tag),
85            MTMessage::MT195(msg) => msg.get_field(tag),
86            MTMessage::MT196(msg) => msg.get_field(tag),
87            MTMessage::MT197(msg) => msg.get_field(tag),
88            MTMessage::MT199(msg) => msg.get_field(tag),
89            MTMessage::MT202(msg) => msg.get_field(tag),
90            MTMessage::MT940(msg) => msg.get_field(tag),
91            MTMessage::MT941(msg) => msg.get_field(tag),
92            MTMessage::MT942(msg) => msg.get_field(tag),
93        }
94    }
95
96    /// Get all fields with a specific tag from the message
97    pub fn get_fields(&self, tag: &str) -> Vec<&Field> {
98        match self {
99            MTMessage::MT102(msg) => msg.get_fields(tag),
100            MTMessage::MT103(msg) => msg.get_fields(tag),
101            MTMessage::MT192(msg) => msg.get_fields(tag),
102            MTMessage::MT195(msg) => msg.get_fields(tag),
103            MTMessage::MT196(msg) => msg.get_fields(tag),
104            MTMessage::MT197(msg) => msg.get_fields(tag),
105            MTMessage::MT199(msg) => msg.get_fields(tag),
106            MTMessage::MT202(msg) => msg.get_fields(tag),
107            MTMessage::MT940(msg) => msg.get_fields(tag),
108            MTMessage::MT941(msg) => msg.get_fields(tag),
109            MTMessage::MT942(msg) => msg.get_fields(tag),
110        }
111    }
112
113    /// Get all fields from the message
114    pub fn get_all_fields(&self) -> Vec<&Field> {
115        match self {
116            MTMessage::MT102(msg) => msg.get_all_fields(),
117            MTMessage::MT103(msg) => msg.get_all_fields(),
118            MTMessage::MT192(msg) => msg.get_all_fields(),
119            MTMessage::MT195(msg) => msg.get_all_fields(),
120            MTMessage::MT196(msg) => msg.get_all_fields(),
121            MTMessage::MT197(msg) => msg.get_all_fields(),
122            MTMessage::MT199(msg) => msg.get_all_fields(),
123            MTMessage::MT202(msg) => msg.get_all_fields(),
124            MTMessage::MT940(msg) => msg.get_all_fields(),
125            MTMessage::MT941(msg) => msg.get_all_fields(),
126            MTMessage::MT942(msg) => msg.get_all_fields(),
127        }
128    }
129}
130
131/// Common trait for all MT message types
132pub trait MTMessageType {
133    /// Create message from parsed blocks
134    fn from_blocks(blocks: Vec<MessageBlock>) -> Result<Self>
135    where
136        Self: Sized;
137
138    /// Get a field by tag
139    fn get_field(&self, tag: &str) -> Option<&Field>;
140
141    /// Get all fields with a specific tag
142    fn get_fields(&self, tag: &str) -> Vec<&Field>;
143
144    /// Get all fields
145    fn get_all_fields(&self) -> Vec<&Field>;
146
147    /// Get the text block fields
148    fn text_fields(&self) -> &[Field];
149}
150
151/// Helper function to extract text block from message blocks
152pub fn extract_text_block(blocks: &[MessageBlock]) -> Result<Vec<Field>> {
153    for block in blocks {
154        if let MessageBlock::TextBlock { fields } = block {
155            return Ok(fields.clone());
156        }
157    }
158    Err(MTError::InvalidMessageStructure {
159        message: "No text block found in message".to_string(),
160    })
161}
162
163/// Helper function to find field by tag in a list of fields
164pub fn find_field<'a>(fields: &'a [Field], tag: &str) -> Option<&'a Field> {
165    fields.iter().find(|field| field.tag.as_str() == tag)
166}
167
168/// Helper function to find all fields with a specific tag
169pub fn find_fields<'a>(fields: &'a [Field], tag: &str) -> Vec<&'a Field> {
170    fields.iter().filter(|field| field.tag.as_str() == tag).collect()
171}
172
173/// Helper function to get required field value
174pub fn get_required_field_value(fields: &[Field], tag: &str) -> Result<String> {
175    find_field(fields, tag)
176        .map(|field| field.value().to_string())
177        .ok_or_else(|| MTError::missing_required_field(tag))
178}
179
180/// Helper function to get optional field value
181pub fn get_optional_field_value(fields: &[Field], tag: &str) -> Option<String> {
182    find_field(fields, tag).map(|field| field.value().to_string())
183}