crossref_xml/
serializers.rs1use serde::Serializer;
2
3pub fn serialize_version<S: Serializer>(_: &(), s: S) -> Result<S::Ok, S::Error> {
4 s.serialize_str("5.4.0")
5}
6
7pub fn serialize_xmlns<S: Serializer>(_: &(), s: S) -> Result<S::Ok, S::Error> {
8 s.serialize_str("http://www.crossref.org/schema/5.4.0")
9}
10
11pub fn serialize_xmlns_xsi<S: Serializer>(_: &(), s: S) -> Result<S::Ok, S::Error> {
12 s.serialize_str("http://www.w3.org/2001/XMLSchema-instance")
13}
14
15pub fn serialize_xsi_schemalocation<S: Serializer>(_: &(), s: S) -> Result<S::Ok, S::Error> {
16 s.serialize_str(
17 "http://www.crossref.org/schema/5.4.0 http://data.crossref.org/schemas/crossref5.4.0.xsd",
18 )
19}
20
21pub fn serialize_xmlns_jats<S: Serializer>(_: &(), s: S) -> Result<S::Ok, S::Error> {
22 s.serialize_str("http://www.ncbi.nlm.nih.gov/JATS1")
23}
24
25pub fn serialize_timestamp<S: Serializer>(_: &(), s: S) -> Result<S::Ok, S::Error> {
26 let now = std::time::SystemTime::now();
27 let epoch = now.duration_since(std::time::UNIX_EPOCH).unwrap();
28 s.serialize_str(&epoch.as_millis().to_string())
29}
30
31pub fn serialize_two_digits<S>(value: &Option<u32>, serializer: S) -> Result<S::Ok, S::Error>
32where
33 S: serde::Serializer,
34{
35 match value {
36 Some(v) => serializer.serialize_str(&format!("{:02}", v)),
37 None => serializer.serialize_none(),
38 }
39}
40
41#[cfg(test)]
42mod unit {
43 use super::*;
44 use serde::Serialize;
45
46 #[derive(Serialize)]
47 struct TestVersion {
48 #[serde(serialize_with = "serialize_version")]
49 version: (),
50 }
51
52 #[test]
53 fn test_serialize_version() {
54 let test = TestVersion { version: () };
55 let xml = quick_xml::se::to_string(&test).unwrap();
56 assert!(xml.contains("5.4.0"), "Version should be 5.4.0");
57 }
58
59 #[derive(Serialize)]
60 struct TestXmlns {
61 #[serde(serialize_with = "serialize_xmlns")]
62 xmlns: (),
63 }
64
65 #[test]
66 fn test_serialize_xmlns() {
67 let test = TestXmlns { xmlns: () };
68 let xml = quick_xml::se::to_string(&test).unwrap();
69 assert!(
70 xml.contains("http://www.crossref.org/schema/5.4.0"),
71 "xmlns should contain correct URL"
72 );
73 }
74
75 #[derive(Serialize)]
76 struct TestTimestamp {
77 #[serde(serialize_with = "serialize_timestamp")]
78 timestamp: (),
79 }
80
81 #[test]
82 fn test_serialize_timestamp() {
83 let before = std::time::SystemTime::now()
84 .duration_since(std::time::UNIX_EPOCH)
85 .unwrap()
86 .as_millis();
87
88 let test = TestTimestamp { timestamp: () };
89 let xml = quick_xml::se::to_string(&test).unwrap();
90
91 let after = std::time::SystemTime::now()
92 .duration_since(std::time::UNIX_EPOCH)
93 .unwrap()
94 .as_millis();
95
96 assert!(
98 xml.contains("<timestamp>"),
99 "XML should contain timestamp tag"
100 );
101
102 let timestamp_str = xml
104 .trim_start_matches("<TestTimestamp><timestamp>")
105 .trim_end_matches("</timestamp></TestTimestamp>");
106 let timestamp: u128 = timestamp_str.parse().expect("Should parse as u128");
107
108 assert!(
109 timestamp >= before && timestamp <= after,
110 "Timestamp should be between {} and {}, got {}",
111 before,
112 after,
113 timestamp
114 );
115 }
116
117 #[derive(Serialize)]
118 struct TestTwoDigits {
119 #[serde(serialize_with = "serialize_two_digits")]
120 value: Option<u32>,
121 }
122
123 #[test]
124 fn test_serialize_two_digits_some() {
125 let test = TestTwoDigits { value: Some(5) };
126 let xml = quick_xml::se::to_string(&test).unwrap();
127 assert!(
128 xml.contains("05"),
129 "Should format single digit with leading zero"
130 );
131 }
132
133 #[test]
134 fn test_serialize_two_digits_double_digit() {
135 let test = TestTwoDigits { value: Some(42) };
136 let xml = quick_xml::se::to_string(&test).unwrap();
137 assert!(xml.contains("42"), "Should format double digit as-is");
138 }
139
140 #[test]
141 fn test_serialize_two_digits_none() {
142 let test = TestTwoDigits { value: None };
143 let xml = quick_xml::se::to_string(&test).unwrap();
144 assert!(
146 !xml.contains("<value>") || xml.contains("<value/>") || xml.contains("<value></value>"),
147 "None should serialize as empty or omitted"
148 );
149 }
150}