/rust/registry/src/index.crates.io-1949cf8c6b5b557f/quick-xml-0.37.5/src/se/key.rs
Line | Count | Source |
1 | | use crate::se::SeError; |
2 | | use serde::ser::{Impossible, Serialize, Serializer}; |
3 | | use serde::serde_if_integer128; |
4 | | use std::fmt::Write; |
5 | | |
6 | | /// A serializer, that ensures, that only plain types can be serialized, |
7 | | /// so result can be used as an XML tag or attribute name. |
8 | | /// |
9 | | /// This serializer does not check that name does not contain characters that |
10 | | /// [not allowed] in XML names, because in some cases it should pass names |
11 | | /// that would be filtered on higher level. |
12 | | /// |
13 | | /// [not allowed]: https://www.w3.org/TR/xml11/#sec-common-syn |
14 | | pub struct QNameSerializer<W: Write> { |
15 | | /// Writer to which this serializer writes content |
16 | | pub writer: W, |
17 | | } |
18 | | |
19 | | impl<W: Write> QNameSerializer<W> { |
20 | | #[inline] |
21 | 0 | fn write_str(&mut self, value: &str) -> Result<(), SeError> { |
22 | 0 | Ok(self.writer.write_str(value)?) |
23 | 0 | } |
24 | | } |
25 | | |
26 | | impl<W: Write> Serializer for QNameSerializer<W> { |
27 | | type Ok = W; |
28 | | type Error = SeError; |
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 | 0 | fn serialize_str(mut self, value: &str) -> Result<Self::Ok, Self::Error> { |
41 | 0 | self.write_str(value)?; |
42 | 0 | Ok(self.writer) |
43 | 0 | } |
44 | | |
45 | | /// Because unit type can be represented only by empty string which is not |
46 | | /// a valid XML name, serialization of unit returns `Err(Unsupported)` |
47 | 0 | fn serialize_unit(self) -> Result<Self::Ok, Self::Error> { |
48 | 0 | Err(SeError::Unsupported( |
49 | 0 | "cannot serialize unit type `()` as an XML tag name".into(), |
50 | 0 | )) |
51 | 0 | } |
52 | | |
53 | | /// Because unit struct can be represented only by empty string which is not |
54 | | /// a valid XML name, serialization of unit struct returns `Err(Unsupported)` |
55 | 0 | fn serialize_unit_struct(self, name: &'static str) -> Result<Self::Ok, Self::Error> { |
56 | 0 | Err(SeError::Unsupported( |
57 | 0 | format!("cannot serialize unit struct `{}` as an XML tag name", name).into(), |
58 | 0 | )) |
59 | 0 | } |
60 | | |
61 | | /// We cannot store both a variant discriminant and a variant value, |
62 | | /// so serialization of enum newtype variant returns `Err(Unsupported)` |
63 | 0 | fn serialize_newtype_variant<T: ?Sized + Serialize>( |
64 | 0 | self, |
65 | 0 | name: &'static str, |
66 | 0 | _variant_index: u32, |
67 | 0 | variant: &'static str, |
68 | 0 | _value: &T, |
69 | 0 | ) -> Result<Self::Ok, SeError> { |
70 | 0 | Err(SeError::Unsupported( |
71 | 0 | format!( |
72 | 0 | "cannot serialize enum newtype variant `{}::{}` as an XML tag name", |
73 | 0 | name, variant |
74 | 0 | ) |
75 | 0 | .into(), |
76 | 0 | )) |
77 | 0 | } |
78 | | |
79 | 0 | fn serialize_seq(self, _len: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> { |
80 | 0 | Err(SeError::Unsupported( |
81 | 0 | "cannot serialize sequence as an XML tag name".into(), |
82 | 0 | )) |
83 | 0 | } |
84 | | |
85 | 0 | fn serialize_tuple(self, _len: usize) -> Result<Self::SerializeTuple, Self::Error> { |
86 | 0 | Err(SeError::Unsupported( |
87 | 0 | "cannot serialize tuple as an XML tag name".into(), |
88 | 0 | )) |
89 | 0 | } |
90 | | |
91 | 0 | fn serialize_tuple_struct( |
92 | 0 | self, |
93 | 0 | name: &'static str, |
94 | 0 | _len: usize, |
95 | 0 | ) -> Result<Self::SerializeTupleStruct, Self::Error> { |
96 | 0 | Err(SeError::Unsupported( |
97 | 0 | format!( |
98 | 0 | "cannot serialize tuple struct `{}` as an XML tag name", |
99 | 0 | name |
100 | 0 | ) |
101 | 0 | .into(), |
102 | 0 | )) |
103 | 0 | } |
104 | | |
105 | 0 | fn serialize_tuple_variant( |
106 | 0 | self, |
107 | 0 | name: &'static str, |
108 | 0 | _variant_index: u32, |
109 | 0 | variant: &'static str, |
110 | 0 | _len: usize, |
111 | 0 | ) -> Result<Self::SerializeTupleVariant, Self::Error> { |
112 | 0 | Err(SeError::Unsupported( |
113 | 0 | format!( |
114 | 0 | "cannot serialize enum tuple variant `{}::{}` as an XML tag name", |
115 | 0 | name, variant |
116 | 0 | ) |
117 | 0 | .into(), |
118 | 0 | )) |
119 | 0 | } |
120 | | |
121 | 0 | fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap, Self::Error> { |
122 | 0 | Err(SeError::Unsupported( |
123 | 0 | "cannot serialize map as an XML tag name".into(), |
124 | 0 | )) |
125 | 0 | } |
126 | | |
127 | 0 | fn serialize_struct( |
128 | 0 | self, |
129 | 0 | name: &'static str, |
130 | 0 | _len: usize, |
131 | 0 | ) -> Result<Self::SerializeStruct, Self::Error> { |
132 | 0 | Err(SeError::Unsupported( |
133 | 0 | format!("cannot serialize struct `{}` as an XML tag name", name).into(), |
134 | 0 | )) |
135 | 0 | } |
136 | | |
137 | 0 | fn serialize_struct_variant( |
138 | 0 | self, |
139 | 0 | name: &'static str, |
140 | 0 | _variant_index: u32, |
141 | 0 | variant: &'static str, |
142 | 0 | _len: usize, |
143 | 0 | ) -> Result<Self::SerializeStructVariant, Self::Error> { |
144 | 0 | Err(SeError::Unsupported( |
145 | 0 | format!( |
146 | 0 | "cannot serialize enum struct variant `{}::{}` as an XML tag name", |
147 | 0 | name, variant |
148 | 0 | ) |
149 | 0 | .into(), |
150 | 0 | )) |
151 | 0 | } |
152 | | } |
153 | | |
154 | | #[cfg(test)] |
155 | | mod 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 | | /// Checks that given `$data` successfully serialized as `$expected` |
191 | | 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 | | /// Checks that attempt to serialize given `$data` results to a |
206 | | /// serialization error `$kind` with `$reason` |
207 | | 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 | | SeError::$kind(e) => assert_eq!(e, $reason), |
218 | | e => panic!( |
219 | | "Expected `Err({}({}))`, but got `{:?}`", |
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 | | } |