1use crate::{
4 BinaryEncodable, ByteString, Error, ExpandedMessageInfo, ExpandedNodeId, NodeId, UaNullable,
5};
6
7use super::TypeLoader;
8
9pub struct FallbackTypeLoader;
12
13impl TypeLoader for FallbackTypeLoader {
14 #[cfg(feature = "xml")]
15 fn load_from_xml(
16 &self,
17 node_id: &crate::NodeId,
18 stream: &mut crate::xml::XmlStreamReader<&mut dyn std::io::Read>,
19 _ctx: &super::Context<'_>,
20 name: &str,
21 ) -> Option<crate::EncodingResult<Box<dyn crate::DynEncodable>>> {
22 let raw = match stream.consume_raw() {
23 Ok(v) => v,
24 Err(e) => return Some(Err(e.into())),
25 };
26 Some(Ok(Box::new(XmlBody {
27 raw,
28 encoding_id: node_id.clone(),
29 tag_name: name.to_owned(),
30 })))
31 }
32
33 #[cfg(feature = "json")]
34 fn load_from_json(
35 &self,
36 node_id: &crate::NodeId,
37 stream: &mut crate::json::JsonStreamReader<&mut dyn std::io::Read>,
38 _ctx: &super::Context<'_>,
39 ) -> Option<crate::EncodingResult<Box<dyn crate::DynEncodable>>> {
40 use crate::json::consume_raw_value;
41
42 let raw = match consume_raw_value(stream) {
43 Ok(v) => v,
44 Err(e) => return Some(Err(e)),
45 };
46 Some(Ok(Box::new(JsonBody {
47 raw,
48 encoding_id: node_id.clone(),
49 })))
50 }
51
52 fn load_from_binary(
53 &self,
54 node_id: &NodeId,
55 stream: &mut dyn std::io::Read,
56 _ctx: &super::Context<'_>,
57 length: Option<usize>,
58 ) -> Option<crate::EncodingResult<Box<dyn crate::DynEncodable>>> {
59 let length = length?;
61 let mut buf = vec![0u8; length];
62 if let Err(e) = stream.read_exact(&mut buf) {
63 return Some(Err(e.into()));
64 }
65 Some(Ok(Box::new(ByteStringBody {
66 raw: ByteString::from(buf),
67 encoding_id: node_id.clone(),
68 })))
69 }
70
71 fn priority(&self) -> super::TypeLoaderPriority {
72 super::TypeLoaderPriority::Fallback
73 }
74}
75
76#[derive(Debug, PartialEq, Clone)]
79pub struct ByteStringBody {
80 raw: ByteString,
81 encoding_id: NodeId,
82}
83
84impl ByteStringBody {
85 pub fn new(raw: ByteString, encoding_id: NodeId) -> Self {
87 Self { raw, encoding_id }
88 }
89
90 pub fn raw_body(&self) -> &ByteString {
92 &self.raw
93 }
94
95 pub fn into_raw(self) -> ByteString {
97 self.raw
98 }
99
100 pub fn encoding_id(&self) -> &NodeId {
102 &self.encoding_id
103 }
104}
105
106impl BinaryEncodable for ByteStringBody {
107 fn byte_len(&self, _ctx: &crate::Context<'_>) -> usize {
108 self.raw.len()
109 }
110
111 fn encode<S: std::io::Write + ?Sized>(
112 &self,
113 stream: &mut S,
114 _ctx: &super::Context<'_>,
115 ) -> crate::EncodingResult<()> {
116 Ok(stream.write_all(self.raw.as_ref())?)
117 }
118
119 fn override_encoding(&self) -> Option<crate::BuiltInDataEncoding> {
120 Some(crate::BuiltInDataEncoding::Binary)
121 }
122}
123
124impl ExpandedMessageInfo for ByteStringBody {
127 fn full_data_type_id(&self) -> crate::ExpandedNodeId {
128 ExpandedNodeId::new(self.encoding_id.clone())
129 }
130
131 fn full_json_type_id(&self) -> ExpandedNodeId {
132 ExpandedNodeId::new(self.encoding_id.clone())
133 }
134
135 fn full_type_id(&self) -> ExpandedNodeId {
136 ExpandedNodeId::new(self.encoding_id.clone())
137 }
138
139 fn full_xml_type_id(&self) -> ExpandedNodeId {
140 ExpandedNodeId::new(self.encoding_id.clone())
141 }
142}
143
144impl UaNullable for ByteStringBody {
145 fn is_ua_null(&self) -> bool {
146 self.raw.is_null()
147 }
148}
149
150#[derive(Debug, PartialEq, Clone)]
153pub struct JsonBody {
154 raw: Vec<u8>,
155 encoding_id: NodeId,
156}
157
158impl JsonBody {
159 pub fn new(raw: Vec<u8>, encoding_id: NodeId) -> Self {
161 Self { raw, encoding_id }
162 }
163
164 pub fn raw_body(&self) -> &[u8] {
166 &self.raw
167 }
168
169 pub fn into_raw(self) -> Vec<u8> {
171 self.raw
172 }
173
174 pub fn encoding_id(&self) -> &NodeId {
176 &self.encoding_id
177 }
178}
179
180impl BinaryEncodable for JsonBody {
181 fn byte_len(&self, _ctx: &crate::Context<'_>) -> usize {
182 0
183 }
184
185 fn encode<S: std::io::Write + ?Sized>(
186 &self,
187 _stream: &mut S,
188 _ctx: &super::Context<'_>,
189 ) -> crate::EncodingResult<()> {
190 Err(Error::encoding(
192 "Cannot encode a raw json body as a binary ExtensionObject body",
193 ))
194 }
195
196 fn override_encoding(&self) -> Option<crate::BuiltInDataEncoding> {
197 Some(crate::BuiltInDataEncoding::JSON)
198 }
199}
200
201impl ExpandedMessageInfo for JsonBody {
202 fn full_data_type_id(&self) -> crate::ExpandedNodeId {
203 ExpandedNodeId::new(self.encoding_id.clone())
204 }
205
206 fn full_json_type_id(&self) -> ExpandedNodeId {
207 ExpandedNodeId::new(self.encoding_id.clone())
208 }
209
210 fn full_type_id(&self) -> ExpandedNodeId {
211 ExpandedNodeId::new(self.encoding_id.clone())
212 }
213
214 fn full_xml_type_id(&self) -> ExpandedNodeId {
215 ExpandedNodeId::new(self.encoding_id.clone())
216 }
217}
218
219impl UaNullable for JsonBody {
220 fn is_ua_null(&self) -> bool {
221 self.raw.is_empty()
222 }
223}
224
225#[derive(Debug, PartialEq, Clone)]
228pub struct XmlBody {
229 raw: Vec<u8>,
230 encoding_id: NodeId,
231 tag_name: String,
232}
233
234impl XmlBody {
235 pub fn new(raw: Vec<u8>, encoding_id: NodeId, tag_name: String) -> Self {
237 Self {
238 raw,
239 encoding_id,
240 tag_name,
241 }
242 }
243
244 pub fn raw_body(&self) -> &[u8] {
246 &self.raw
247 }
248
249 pub fn into_raw(self) -> Vec<u8> {
251 self.raw
252 }
253
254 pub fn encoding_id(&self) -> &NodeId {
256 &self.encoding_id
257 }
258}
259
260impl BinaryEncodable for XmlBody {
261 fn byte_len(&self, _ctx: &crate::Context<'_>) -> usize {
262 self.raw.len()
263 }
264
265 fn encode<S: std::io::Write + ?Sized>(
266 &self,
267 stream: &mut S,
268 _ctx: &super::Context<'_>,
269 ) -> crate::EncodingResult<()> {
270 stream.write_all(&self.raw)?;
271 Ok(())
272 }
273
274 fn override_encoding(&self) -> Option<crate::BuiltInDataEncoding> {
275 Some(crate::BuiltInDataEncoding::XML)
276 }
277}
278
279impl ExpandedMessageInfo for XmlBody {
280 fn full_data_type_id(&self) -> crate::ExpandedNodeId {
281 ExpandedNodeId::new(self.encoding_id.clone())
282 }
283
284 fn full_json_type_id(&self) -> ExpandedNodeId {
285 ExpandedNodeId::new(self.encoding_id.clone())
286 }
287
288 fn full_type_id(&self) -> ExpandedNodeId {
289 ExpandedNodeId::new(self.encoding_id.clone())
290 }
291
292 fn full_xml_type_id(&self) -> ExpandedNodeId {
293 ExpandedNodeId::new(self.encoding_id.clone())
294 }
295}
296
297impl UaNullable for XmlBody {
298 fn is_ua_null(&self) -> bool {
299 self.raw.is_empty()
300 }
301}
302
303#[cfg(feature = "json")]
304mod json {
305 use crate::json::*;
306
307 use super::{ByteStringBody, JsonBody, XmlBody};
308
309 impl JsonEncodable for ByteStringBody {
310 fn encode(
311 &self,
312 stream: &mut struson::writer::JsonStreamWriter<&mut dyn std::io::Write>,
313 _ctx: &crate::Context<'_>,
314 ) -> crate::EncodingResult<()> {
315 stream.string_value(&self.raw.as_base64())?;
316 Ok(())
317 }
318 }
319
320 impl JsonEncodable for JsonBody {
321 fn encode(
322 &self,
323 stream: &mut JsonStreamWriter<&mut dyn std::io::Write>,
324 _ctx: &crate::Context<'_>,
325 ) -> crate::EncodingResult<()> {
326 write_raw_value(&self.raw, stream)?;
327 Ok(())
328 }
329 }
330
331 impl JsonEncodable for XmlBody {
332 fn encode(
333 &self,
334 stream: &mut JsonStreamWriter<&mut dyn std::io::Write>,
335 _ctx: &crate::Context<'_>,
336 ) -> crate::EncodingResult<()> {
337 stream.string_value(&String::from_utf8_lossy(&self.raw))?;
338 Ok(())
339 }
340 }
341}
342
343#[cfg(feature = "xml")]
344mod xml {
345 use crate::{
346 xml::{XmlEncodable, XmlType},
347 Error,
348 };
349
350 use super::{ByteStringBody, JsonBody, XmlBody};
351
352 impl XmlType for ByteStringBody {
353 const TAG: &'static str = "ByteString";
354 }
355
356 impl XmlEncodable for ByteStringBody {
357 fn encode(
358 &self,
359 writer: &mut opcua_xml::XmlStreamWriter<&mut dyn std::io::Write>,
360 _context: &crate::Context<'_>,
361 ) -> crate::EncodingResult<()> {
362 writer.write_text(&self.raw.as_base64())?;
363 Ok(())
364 }
365 }
366
367 impl XmlType for JsonBody {
368 const TAG: &'static str = "JsonElement"; }
370
371 impl XmlEncodable for JsonBody {
372 fn encode(
373 &self,
374 _writer: &mut opcua_xml::XmlStreamWriter<&mut dyn std::io::Write>,
375 _context: &crate::Context<'_>,
376 ) -> crate::EncodingResult<()> {
377 Err(Error::encoding(
379 "Cannot encode a raw json body as an XML ExtensionObject body",
380 ))
381 }
382 }
383
384 impl XmlType for XmlBody {
385 const TAG: &'static str = "XmlElement";
386 fn tag(&self) -> &str {
387 &self.tag_name
388 }
389 }
390
391 impl XmlEncodable for XmlBody {
392 fn encode(
393 &self,
394 writer: &mut opcua_xml::XmlStreamWriter<&mut dyn std::io::Write>,
395 _context: &crate::Context<'_>,
396 ) -> crate::EncodingResult<()> {
397 writer.write_raw(&self.raw)?;
398 Ok(())
399 }
400 }
401}