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