mx20022_parse/ser.rs
1//! Serialization of ISO 20022 message types to XML.
2//!
3//! Thin wrappers around [`quick_xml::se`] that translate errors into
4//! [`ParseError`].
5//!
6//! # Examples
7//!
8//! ```no_run
9//! # use mx20022_parse::ser::to_string;
10//! # use mx20022_model::generated::head::BusinessApplicationHeaderV04;
11//! # let hdr: BusinessApplicationHeaderV04 = unimplemented!();
12//! let xml = to_string(&hdr).unwrap();
13//! ```
14
15use serde::Serialize;
16
17use crate::ParseError;
18
19/// XML declaration prepended when using [`to_string_with_declaration`].
20const XML_DECLARATION: &str = r#"<?xml version="1.0" encoding="UTF-8"?>"#;
21
22/// Serialize an ISO 20022 message type to an XML string.
23///
24/// The root element name is derived from the struct name (or `#[serde(rename)]`).
25/// No XML declaration is prepended; use [`to_string_with_declaration`] if needed.
26///
27/// # Errors
28///
29/// Returns [`ParseError::Serialize`] if the value cannot be serialized.
30pub fn to_string<T: Serialize>(value: &T) -> Result<String, ParseError> {
31 quick_xml::se::to_string(value).map_err(ParseError::Serialize)
32}
33
34/// Serialize an ISO 20022 message type to an XML string with an XML declaration.
35///
36/// Prepends `<?xml version="1.0" encoding="UTF-8"?>` before the XML body.
37///
38/// # Errors
39///
40/// Returns [`ParseError::Serialize`] if the value cannot be serialized.
41pub fn to_string_with_declaration<T: Serialize>(value: &T) -> Result<String, ParseError> {
42 let body = quick_xml::se::to_string(value).map_err(ParseError::Serialize)?;
43 Ok(format!("{XML_DECLARATION}{body}"))
44}
45
46#[cfg(test)]
47mod tests {
48 use super::*;
49
50 #[test]
51 fn to_string_with_declaration_prepends_declaration() {
52 #[derive(serde::Serialize)]
53 struct Msg {
54 value: u32,
55 }
56
57 let result = to_string_with_declaration(&Msg { value: 42 }).unwrap();
58 assert!(
59 result.starts_with(r#"<?xml version="1.0" encoding="UTF-8"?>"#),
60 "expected XML declaration at start, got: {result}"
61 );
62 assert!(
63 result.contains("<value>42</value>"),
64 "expected body in output"
65 );
66 }
67
68 #[test]
69 fn to_string_no_declaration() {
70 #[derive(serde::Serialize)]
71 struct Msg {
72 value: u32,
73 }
74
75 let result = to_string(&Msg { value: 7 }).unwrap();
76 assert!(
77 !result.starts_with("<?xml"),
78 "to_string must not include XML declaration"
79 );
80 assert!(result.contains("<value>7</value>"));
81 }
82}