1use crate::errors::serialize::DeError;
2use serde::ser::{Impossible, Serialize, Serializer};
3use serde::serde_if_integer128;
4use std::fmt::Write;
5
6pub struct QNameSerializer<W: Write> {
15 pub writer: W,
17}
18
19impl<W: Write> QNameSerializer<W> {
20 #[inline]
21 fn write_str(&mut self, value: &str) -> Result<(), DeError> {
22 Ok(self.writer.write_str(value)?)
23 }
24}
25
26impl<W: Write> Serializer for QNameSerializer<W> {
27 type Ok = W;
28 type Error = DeError;
29
30 type SerializeSeq = Impossible<Self::Ok, Self::Error>;
31 type SerializeTuple = Impossible<Self::Ok, Self::Error>;
32 type SerializeTupleStruct = Impossible<Self::Ok, Self::Error>;
33 type SerializeTupleVariant = Impossible<Self::Ok, Self::Error>;
34 type SerializeMap = Impossible<Self::Ok, Self::Error>;
35 type SerializeStruct = Impossible<Self::Ok, Self::Error>;
36 type SerializeStructVariant = Impossible<Self::Ok, Self::Error>;
37
38 write_primitive!();
39
40 fn serialize_str(mut self, value: &str) -> Result<Self::Ok, Self::Error> {
41 self.write_str(value)?;
42 Ok(self.writer)
43 }
44
45 fn serialize_unit(self) -> Result<Self::Ok, Self::Error> {
48 Err(DeError::Unsupported(
49 "cannot serialize unit type `()` as an XML tag name".into(),
50 ))
51 }
52
53 fn serialize_unit_struct(self, name: &'static str) -> Result<Self::Ok, Self::Error> {
56 Err(DeError::Unsupported(
57 format!("cannot serialize unit struct `{}` as an XML tag name", name).into(),
58 ))
59 }
60
61 fn serialize_newtype_variant<T: ?Sized + Serialize>(
64 self,
65 name: &'static str,
66 _variant_index: u32,
67 variant: &'static str,
68 _value: &T,
69 ) -> Result<Self::Ok, DeError> {
70 Err(DeError::Unsupported(
71 format!(
72 "cannot serialize enum newtype variant `{}::{}` as an XML tag name",
73 name, variant
74 )
75 .into(),
76 ))
77 }
78
79 fn serialize_seq(self, _len: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> {
80 Err(DeError::Unsupported(
81 "cannot serialize sequence as an XML tag name".into(),
82 ))
83 }
84
85 fn serialize_tuple(self, _len: usize) -> Result<Self::SerializeTuple, Self::Error> {
86 Err(DeError::Unsupported(
87 "cannot serialize tuple as an XML tag name".into(),
88 ))
89 }
90
91 fn serialize_tuple_struct(
92 self,
93 name: &'static str,
94 _len: usize,
95 ) -> Result<Self::SerializeTupleStruct, Self::Error> {
96 Err(DeError::Unsupported(
97 format!(
98 "cannot serialize tuple struct `{}` as an XML tag name",
99 name
100 )
101 .into(),
102 ))
103 }
104
105 fn serialize_tuple_variant(
106 self,
107 name: &'static str,
108 _variant_index: u32,
109 variant: &'static str,
110 _len: usize,
111 ) -> Result<Self::SerializeTupleVariant, Self::Error> {
112 Err(DeError::Unsupported(
113 format!(
114 "cannot serialize enum tuple variant `{}::{}` as an XML tag name",
115 name, variant
116 )
117 .into(),
118 ))
119 }
120
121 fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap, Self::Error> {
122 Err(DeError::Unsupported(
123 "cannot serialize map as an XML tag name".into(),
124 ))
125 }
126
127 fn serialize_struct(
128 self,
129 name: &'static str,
130 _len: usize,
131 ) -> Result<Self::SerializeStruct, Self::Error> {
132 Err(DeError::Unsupported(
133 format!("cannot serialize struct `{}` as an XML tag name", name).into(),
134 ))
135 }
136
137 fn serialize_struct_variant(
138 self,
139 name: &'static str,
140 _variant_index: u32,
141 variant: &'static str,
142 _len: usize,
143 ) -> Result<Self::SerializeStructVariant, Self::Error> {
144 Err(DeError::Unsupported(
145 format!(
146 "cannot serialize enum struct variant `{}::{}` as an XML tag name",
147 name, variant
148 )
149 .into(),
150 ))
151 }
152}
153
154#[cfg(test)]
155mod tests {
156 use super::*;
157 use crate::utils::Bytes;
158 use pretty_assertions::assert_eq;
159 use serde::Serialize;
160 use std::collections::BTreeMap;
161
162 #[derive(Debug, Serialize, PartialEq)]
163 struct Unit;
164
165 #[derive(Debug, Serialize, PartialEq)]
166 struct Newtype(bool);
167
168 #[derive(Debug, Serialize, PartialEq)]
169 struct Tuple(&'static str, usize);
170
171 #[derive(Debug, Serialize, PartialEq)]
172 struct Struct {
173 key: &'static str,
174 val: usize,
175 }
176
177 #[derive(Debug, Serialize, PartialEq)]
178 enum Enum {
179 Unit,
180 #[serde(rename = "<\"&'>")]
181 UnitEscaped,
182 Newtype(bool),
183 Tuple(&'static str, usize),
184 Struct {
185 key: &'static str,
186 val: usize,
187 },
188 }
189
190 macro_rules! serialize_as {
192 ($name:ident: $data:expr => $expected:literal) => {
193 #[test]
194 fn $name() {
195 let ser = QNameSerializer {
196 writer: String::new(),
197 };
198
199 let buffer = $data.serialize(ser).unwrap();
200 assert_eq!(buffer, $expected);
201 }
202 };
203 }
204
205 macro_rules! err {
208 ($name:ident: $data:expr => $kind:ident($reason:literal)) => {
209 #[test]
210 fn $name() {
211 let mut buffer = String::new();
212 let ser = QNameSerializer {
213 writer: &mut buffer,
214 };
215
216 match $data.serialize(ser).unwrap_err() {
217 DeError::$kind(e) => assert_eq!(e, $reason),
218 e => panic!(
219 "Expected `{}({})`, found `{:?}`",
220 stringify!($kind),
221 $reason,
222 e
223 ),
224 }
225 assert_eq!(buffer, "");
226 }
227 };
228 }
229
230 serialize_as!(false_: false => "false");
231 serialize_as!(true_: true => "true");
232
233 serialize_as!(i8_: -42i8 => "-42");
234 serialize_as!(i16_: -4200i16 => "-4200");
235 serialize_as!(i32_: -42000000i32 => "-42000000");
236 serialize_as!(i64_: -42000000000000i64 => "-42000000000000");
237 serialize_as!(isize_: -42000000000000isize => "-42000000000000");
238
239 serialize_as!(u8_: 42u8 => "42");
240 serialize_as!(u16_: 4200u16 => "4200");
241 serialize_as!(u32_: 42000000u32 => "42000000");
242 serialize_as!(u64_: 42000000000000u64 => "42000000000000");
243 serialize_as!(usize_: 42000000000000usize => "42000000000000");
244
245 serde_if_integer128! {
246 serialize_as!(i128_: -420000000000000000000000000000i128 => "-420000000000000000000000000000");
247 serialize_as!(u128_: 420000000000000000000000000000u128 => "420000000000000000000000000000");
248 }
249
250 serialize_as!(f32_: 4.2f32 => "4.2");
251 serialize_as!(f64_: 4.2f64 => "4.2");
252
253 serialize_as!(char_non_escaped: 'h' => "h");
254 serialize_as!(char_lt: '<' => "<");
255 serialize_as!(char_gt: '>' => ">");
256 serialize_as!(char_amp: '&' => "&");
257 serialize_as!(char_apos: '\'' => "'");
258 serialize_as!(char_quot: '"' => "\"");
259
260 serialize_as!(str_valid_name: "valid-name" => "valid-name");
261 serialize_as!(str_space: "string with spaces" => "string with spaces");
262 serialize_as!(str_lt: "string<" => "string<");
263 serialize_as!(str_gt: "string>" => "string>");
264 serialize_as!(str_amp: "string&" => "string&");
265 serialize_as!(str_apos: "string'" => "string'");
266 serialize_as!(str_quot: "string\"" => "string\"");
267
268 err!(bytes: Bytes(b"<\"escaped & bytes'>")
269 => Unsupported("`serialize_bytes` not supported yet"));
270
271 serialize_as!(option_none: Option::<&str>::None => "");
272 serialize_as!(option_some: Some("non-escaped-string") => "non-escaped-string");
273
274 err!(unit: ()
275 => Unsupported("cannot serialize unit type `()` as an XML tag name"));
276 err!(unit_struct: Unit
277 => Unsupported("cannot serialize unit struct `Unit` as an XML tag name"));
278
279 serialize_as!(enum_unit: Enum::Unit => "Unit");
280 serialize_as!(enum_unit_escaped: Enum::UnitEscaped => "<\"&'>");
281
282 serialize_as!(newtype: Newtype(true) => "true");
283 err!(enum_newtype: Enum::Newtype(false)
284 => Unsupported("cannot serialize enum newtype variant `Enum::Newtype` as an XML tag name"));
285
286 err!(seq: vec![1, 2, 3]
287 => Unsupported("cannot serialize sequence as an XML tag name"));
288 err!(tuple: ("<\"&'>", "with\t\r\n spaces", 3usize)
289 => Unsupported("cannot serialize tuple as an XML tag name"));
290 err!(tuple_struct: Tuple("first", 42)
291 => Unsupported("cannot serialize tuple struct `Tuple` as an XML tag name"));
292 err!(enum_tuple: Enum::Tuple("first", 42)
293 => Unsupported("cannot serialize enum tuple variant `Enum::Tuple` as an XML tag name"));
294
295 err!(map: BTreeMap::from([("_1", 2), ("_3", 4)])
296 => Unsupported("cannot serialize map as an XML tag name"));
297 err!(struct_: Struct { key: "answer", val: 42 }
298 => Unsupported("cannot serialize struct `Struct` as an XML tag name"));
299 err!(enum_struct: Enum::Struct { key: "answer", val: 42 }
300 => Unsupported("cannot serialize enum struct variant `Enum::Struct` as an XML tag name"));
301}