1use super::{
2 encoding::{XmlDecodable, XmlEncodable, XmlType},
3 XmlReadExt, XmlWriteExt,
4};
5use crate::{Context, Error};
6use opcua_xml::{XmlStreamReader, XmlStreamWriter};
7use std::io::{Read, Write};
8
9macro_rules! xml_enc_number {
10 ($t:ty, $name:expr) => {
11 impl XmlType for $t {
12 const TAG: &'static str = $name;
13 }
14
15 impl XmlEncodable for $t {
16 fn encode(
17 &self,
18 writer: &mut XmlStreamWriter<&mut dyn Write>,
19 _context: &Context<'_>,
20 ) -> Result<(), Error> {
21 writer.write_text(&self.to_string())?;
22 Ok(())
23 }
24 }
25
26 impl XmlDecodable for $t {
27 fn decode(
28 read: &mut XmlStreamReader<&mut dyn Read>,
29 _context: &Context<'_>,
30 ) -> Result<Self, Error> {
31 Ok(read.consume_content()?)
32 }
33 }
34 };
35}
36
37const VALUE_INFINITY: &str = "INF";
38const VALUE_NEG_INFINITY: &str = "-INF";
39const VALUE_NAN: &str = "NaN";
40
41macro_rules! xml_enc_float {
42 ($t:ty, $name:expr) => {
43 impl XmlType for $t {
44 const TAG: &'static str = $name;
45 }
46
47 impl XmlEncodable for $t {
48 fn encode(
49 &self,
50 writer: &mut XmlStreamWriter<&mut dyn Write>,
51 _context: &Context<'_>,
52 ) -> Result<(), Error> {
53 if self.is_infinite() {
54 if self.is_sign_positive() {
55 writer.write_text(VALUE_INFINITY)?;
56 } else {
57 writer.write_text(VALUE_NEG_INFINITY)?;
58 }
59 } else if self.is_nan() {
60 writer.write_text(VALUE_NAN)?;
61 } else {
62 writer.write_text(&self.to_string())?;
63 }
64 Ok(())
65 }
66 }
67
68 impl XmlDecodable for $t {
69 fn decode(
70 read: &mut XmlStreamReader<&mut dyn Read>,
71 _context: &Context<'_>,
72 ) -> Result<Self, Error> {
73 let val = read.consume_as_text()?;
74 match val.as_str() {
75 VALUE_INFINITY => Ok(Self::INFINITY),
76 VALUE_NEG_INFINITY => Ok(Self::NEG_INFINITY),
77 VALUE_NAN => Ok(Self::NAN),
78 _ => Ok(val.parse()?),
79 }
80 }
81 }
82 };
83}
84
85xml_enc_number!(u8, "Byte");
86xml_enc_number!(u16, "UInt16");
87xml_enc_number!(u32, "UInt32");
88xml_enc_number!(u64, "UInt64");
89xml_enc_number!(i8, "SByte");
90xml_enc_number!(i16, "Int16");
91xml_enc_number!(i32, "Int32");
92xml_enc_number!(i64, "Int64");
93xml_enc_float!(f32, "Float");
94xml_enc_float!(f64, "Double");
95
96impl XmlType for String {
97 const TAG: &'static str = "String";
98}
99
100impl XmlDecodable for String {
101 fn decode(
102 read: &mut XmlStreamReader<&mut dyn Read>,
103 _context: &Context<'_>,
104 ) -> Result<Self, Error>
105 where
106 Self: Sized,
107 {
108 Ok(read.consume_as_text()?)
109 }
110}
111
112impl XmlEncodable for String {
113 fn encode(
114 &self,
115 writer: &mut XmlStreamWriter<&mut dyn Write>,
116 _context: &Context<'_>,
117 ) -> Result<(), Error> {
118 writer.write_text(self)?;
119 Ok(())
120 }
121}
122
123impl XmlType for str {
124 const TAG: &'static str = "String";
125}
126
127impl XmlEncodable for str {
128 fn encode(
129 &self,
130 writer: &mut XmlStreamWriter<&mut dyn Write>,
131 _context: &Context<'_>,
132 ) -> Result<(), Error> {
133 writer.write_text(self)?;
134 Ok(())
135 }
136}
137
138impl XmlType for bool {
139 const TAG: &'static str = "Boolean";
140}
141
142impl XmlDecodable for bool {
143 fn decode(
144 read: &mut XmlStreamReader<&mut dyn Read>,
145 _context: &Context<'_>,
146 ) -> Result<Self, Error>
147 where
148 Self: Sized,
149 {
150 let val = read.consume_as_text()?;
151 match val.as_str() {
152 "true" | "1" => Ok(true),
153 "false" | "0" => Ok(false),
154 _ => Err(Error::decoding(format!("Invalid boolean value: {val}"))),
155 }
156 }
157}
158
159impl XmlEncodable for bool {
160 fn encode(
161 &self,
162 writer: &mut XmlStreamWriter<&mut dyn Write>,
163 _context: &Context<'_>,
164 ) -> Result<(), Error> {
165 writer.write_text(if *self { "true" } else { "false" })?;
166 Ok(())
167 }
168}
169
170impl<T> XmlType for Box<T>
171where
172 T: XmlType,
173{
174 const TAG: &'static str = T::TAG;
175 fn tag(&self) -> &str {
176 self.as_ref().tag()
177 }
178}
179
180impl<T> XmlDecodable for Box<T>
181where
182 T: XmlDecodable,
183{
184 fn decode(
185 read: &mut XmlStreamReader<&mut dyn Read>,
186 context: &Context<'_>,
187 ) -> Result<Self, Error> {
188 Ok(Box::new(T::decode(read, context)?))
189 }
190}
191
192impl<T> XmlEncodable for Box<T>
193where
194 T: XmlEncodable,
195{
196 fn encode(
197 &self,
198 writer: &mut XmlStreamWriter<&mut dyn Write>,
199 context: &Context<'_>,
200 ) -> Result<(), Error> {
201 self.as_ref().encode(writer, context)
202 }
203}
204
205impl<T> XmlType for Vec<T>
206where
207 T: XmlType,
208{
209 const TAG: &'static str = T::TAG;
212 fn tag(&self) -> &str {
213 self.first().map(|v| v.tag()).unwrap_or(Self::TAG)
214 }
215}
216
217impl<T> XmlDecodable for Vec<T>
218where
219 T: XmlDecodable + Default,
220{
221 fn decode(
222 read: &mut XmlStreamReader<&mut dyn Read>,
223 context: &Context<'_>,
224 ) -> Result<Self, Error> {
225 let mut vec = Vec::new();
226 read.iter_children_include_empty(
227 |_, reader, context| {
228 let Some(reader) = reader else {
229 vec.push(T::default());
230 return Ok(());
231 };
232 vec.push(T::decode(reader, context)?);
233 Ok(())
234 },
235 context,
236 )?;
237 Ok(vec)
238 }
239}
240
241impl<T> XmlEncodable for Vec<T>
242where
243 T: XmlEncodable,
244{
245 fn encode(
246 &self,
247 writer: &mut XmlStreamWriter<&mut dyn Write>,
248 context: &Context<'_>,
249 ) -> super::EncodingResult<()> {
250 for item in self {
251 if item.is_ua_null() {
252 writer.write_empty(item.tag())?;
253 } else {
254 writer.encode_child(item.tag(), item, context)?;
255 }
256 }
257 Ok(())
258 }
259}
260
261impl<T> XmlType for Option<T>
262where
263 T: XmlType,
264{
265 const TAG: &'static str = T::TAG;
266 fn tag(&self) -> &str {
267 self.as_ref().map(|v| v.tag()).unwrap_or(Self::TAG)
268 }
269}
270
271impl<T> XmlDecodable for Option<T>
272where
273 T: XmlDecodable,
274{
275 fn decode(
276 read: &mut XmlStreamReader<&mut dyn Read>,
277 context: &Context<'_>,
278 ) -> Result<Self, Error> {
279 Ok(Some(T::decode(read, context)?))
282 }
283}
284
285impl<T> XmlEncodable for Option<T>
286where
287 T: XmlEncodable,
288{
289 fn encode(
290 &self,
291 writer: &mut XmlStreamWriter<&mut dyn Write>,
292 context: &Context<'_>,
293 ) -> super::EncodingResult<()> {
294 if let Some(value) = self {
295 value.encode(writer, context)?;
296 }
297 Ok(())
298 }
299}