1use std::{fmt, i32};
19
20use serde::{
21 de, de::DeserializeOwned, de::Error, Deserialize, Deserializer, Serialize, Serializer,
22};
23use serde_json::json;
24
25use crate::types::*;
26
27pub(crate) enum VariantJsonId {
58 Empty = 0,
59 Boolean,
60 SByte,
61 Byte,
62 Int16,
63 UInt16,
64 Int32,
65 UInt32,
66 Int64,
67 UInt64,
68 Float,
69 Double,
70 String,
71 DateTime,
72 Guid,
73 ByteString,
74 XmlElement,
75 NodeId,
76 ExpandedNodeId,
77 StatusCode,
78 QualifiedName,
79 LocalizedText,
80 ExtensionObject,
81 DataValue,
82 Variant,
83 DiagnosticInfo,
84}
85
86#[derive(Serialize, Deserialize)]
90struct JsonVariant {
91 #[serde(rename = "Type")]
92 variant_type: u32,
93 #[serde(skip_serializing_if = "Option::is_none")]
94 #[serde(rename = "Body")]
95 body: Option<serde_json::Value>,
96 #[serde(skip_serializing_if = "Option::is_none")]
97 #[serde(rename = "Dimensions")]
98 dimensions: Option<Vec<u32>>,
99}
100
101const VALUE_INFINITY: &str = "Infinity";
102const VALUE_NEG_INFINITY: &str = "-Infinity";
103const VALUE_NAN: &str = "NaN";
104
105macro_rules! float_to_json {
107 ( $v: expr, $t: ty) => {
108 if $v == <$t>::INFINITY {
109 json!(VALUE_INFINITY)
110 } else if $v == <$t>::NEG_INFINITY {
111 json!(VALUE_NEG_INFINITY)
112 } else if $v.is_nan() {
113 json!(VALUE_NAN)
114 } else {
115 json!($v)
116 }
117 };
118}
119
120macro_rules! serializable_to_json {
122 ( $v: expr ) => {
123 serde_json::value::to_value($v).unwrap()
124 };
125}
126
127fn json_as_value<T, E>(v: Option<serde_json::Value>, typename: &str) -> Result<T, E>
129where
130 T: DeserializeOwned,
131 E: Error,
132{
133 if let Some(v) = v {
134 let v = serde_json::from_value::<T>(v)
135 .map_err(|_| Error::custom(format!("Invalid value, cannot parse {}", typename)))?;
136 Ok(v)
137 } else {
138 Err(Error::custom(format!(
139 "Invalid value, cannot parse {}",
140 typename
141 )))
142 }
143}
144
145impl Serialize for Variant {
157 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
158 where
159 S: Serializer,
160 {
161 let (body, dimensions) = if *self == Variant::Empty {
163 (None, None)
164 } else {
165 let body = match self {
166 Variant::Boolean(v) => json!(*v),
168 Variant::SByte(v) => json!(*v),
170 Variant::Byte(v) => json!(*v),
171 Variant::Int16(v) => json!(*v),
172 Variant::UInt16(v) => json!(*v),
173 Variant::Int32(v) => json!(*v),
174 Variant::UInt32(v) => json!(*v),
175 Variant::Int64(v) => json!(v.to_string()),
177 Variant::UInt64(v) => json!(v.to_string()),
178 Variant::Float(v) => float_to_json!(*v, f32),
181 Variant::Double(v) => float_to_json!(*v, f64),
182 Variant::String(v) => serializable_to_json!(v),
184 Variant::XmlElement(v) => serializable_to_json!(v),
186 Variant::DateTime(v) => serializable_to_json!(v),
188 Variant::Guid(v) => serializable_to_json!(v),
190 Variant::ByteString(v) => serializable_to_json!(v),
192 Variant::NodeId(v) => serializable_to_json!(v),
194 Variant::ExpandedNodeId(v) => serializable_to_json!(v),
196 Variant::StatusCode(v) => serializable_to_json!(v),
198 Variant::QualifiedName(v) => serializable_to_json!(v),
200 Variant::LocalizedText(v) => serializable_to_json!(v),
202 Variant::ExtensionObject(v) => serializable_to_json!(v),
204 Variant::DataValue(v) => serializable_to_json!(v),
206 Variant::DiagnosticInfo(v) => serializable_to_json!(v),
208 Variant::Variant(v) => serializable_to_json!(v),
210 _ => panic!("Unsupported variant type"),
219 };
220 (Some(body), None)
221 };
222
223 let json_variant = JsonVariant {
224 variant_type: self.json_id() as u32,
225 body,
226 dimensions,
227 };
228 json_variant.serialize(serializer)
229 }
230}
231
232struct VariantVisitor;
233
234impl VariantVisitor {
235 fn numeric_i64<E>(
237 v: Option<serde_json::Value>,
238 name: &str,
239 min: i64,
240 max: i64,
241 ) -> Result<i64, E>
242 where
243 E: de::Error,
244 {
245 if let Some(v) = v {
246 let v = v
247 .as_i64()
248 .ok_or_else(|| Error::custom(format!("Wrong type, expecting {} value", name)))?;
249 if v < min || v > max {
250 Err(Error::custom(format!(
251 "Value {} is out of range for {}",
252 v, name
253 )))
254 } else {
255 Ok(v)
256 }
257 } else {
258 Ok(0)
259 }
260 }
261
262 fn numeric_u64<E>(
264 v: Option<serde_json::Value>,
265 name: &str,
266 min: u64,
267 max: u64,
268 ) -> Result<u64, E>
269 where
270 E: de::Error,
271 {
272 if let Some(v) = v {
273 let v = v
274 .as_u64()
275 .ok_or_else(|| Error::custom(format!("Wrong type, expecting {} value", name)))?;
276 if v < min || v > max {
277 Err(Error::custom(format!(
278 "Value {} is out of range for {}",
279 v, name
280 )))
281 } else {
282 Ok(v)
283 }
284 } else {
285 Ok(0)
286 }
287 }
288
289 fn numeric_f64<E>(
291 v: Option<serde_json::Value>,
292 name: &str,
293 min: f64,
294 max: f64,
295 ) -> Result<f64, E>
296 where
297 E: de::Error,
298 {
299 if let Some(v) = v {
300 if let Some(v) = v.as_str() {
302 match v {
303 VALUE_INFINITY => Ok(f64::INFINITY),
304 VALUE_NEG_INFINITY => Ok(f64::NEG_INFINITY),
305 VALUE_NAN => Ok(f64::NAN),
306 _ => Err(Error::custom(format!(
307 "Wrong type, expecting {} value",
308 name
309 ))),
310 }
311 } else {
312 let v = v.as_f64().ok_or_else(|| {
313 Error::custom(format!("Wrong type, expecting {} value", name))
314 })?;
315 if v < min || v > max {
316 Err(Error::custom(format!(
317 "Value {} is out of range for {}",
318 v, name
319 )))
320 } else {
321 Ok(v)
322 }
323 }
324 } else {
325 Ok(0.0)
326 }
327 }
328}
329
330impl<'de> serde::de::Visitor<'de> for VariantVisitor {
331 type Value = Variant;
332
333 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
334 write!(formatter, "a variant value or null")
335 }
336
337 fn visit_none<E>(self) -> Result<Self::Value, E>
338 where
339 E: de::Error,
340 {
341 Ok(Variant::Empty)
342 }
343
344 fn visit_some<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
345 where
346 D: Deserializer<'de>,
347 {
348 let v = JsonVariant::deserialize(deserializer)?;
349
350 let t = v.variant_type;
351 let body = v.body;
352 let dimensions = v.dimensions;
353
354 if dimensions.is_some() {
355 return Err(Error::custom("Dimensions not supported yet"));
357 }
358
359 match t {
360 t if t == VariantJsonId::Empty as u32 => {
361 if body.is_some() {
362 Err(Error::custom("Unexpected Body"))
363 } else {
364 Ok(Variant::Empty)
365 }
366 }
367 t if t == VariantJsonId::Boolean as u32 => {
369 let v = body.ok_or_else(|| Error::custom("Missing Boolean value"))?;
370 Ok(Variant::Boolean(
371 v.as_bool()
372 .ok_or_else(|| Error::custom("Value is not Boolean"))?,
373 ))
374 }
375 t if t == VariantJsonId::SByte as u32 => {
377 Ok(Variant::SByte(
378 Self::numeric_i64(body, "SByte", i8::MIN as i64, i8::MAX as i64)? as i8,
379 ))
380 }
381 t if t == VariantJsonId::Byte as u32 => {
382 Ok(Variant::Byte(
383 Self::numeric_u64(body, "Byte", u8::MIN as u64, u8::MAX as u64)? as u8,
384 ))
385 }
386 t if t == VariantJsonId::Int16 as u32 => Ok(Variant::Int16(Self::numeric_i64(
387 body,
388 "Int16",
389 i16::MIN as i64,
390 i16::MAX as i64,
391 )? as i16)),
392 t if t == VariantJsonId::UInt16 as u32 => Ok(Variant::UInt16(Self::numeric_u64(
393 body,
394 "UInt16",
395 u16::MIN as u64,
396 u16::MAX as u64,
397 )? as u16)),
398 t if t == VariantJsonId::Int32 as u32 => Ok(Variant::Int32(Self::numeric_i64(
399 body,
400 "Int32",
401 i32::MIN as i64,
402 i32::MAX as i64,
403 )? as i32)),
404 t if t == VariantJsonId::UInt32 as u32 => Ok(Variant::UInt32(Self::numeric_u64(
405 body,
406 "UInt32",
407 u32::MIN as u64,
408 u32::MAX as u64,
409 )? as u32)),
410 t if t == VariantJsonId::Int64 as u32 => {
411 let v = if let Some(v) = body {
412 const ERR: &str = "Int64 encoded as a string";
413 let v = v.as_str().ok_or_else(|| {
414 Error::custom(format!("Wrong type, expecting {} value", ERR))
415 })?;
416 v.parse::<i64>().map_err(|_| {
417 Error::custom(format!("Parse error, expecting {} value", ERR))
418 })?
419 } else {
420 0i64
421 };
422 Ok(Variant::Int64(v))
423 }
424 t if t == VariantJsonId::UInt64 as u32 => {
425 let v = if let Some(v) = body {
426 const ERR: &str = "UInt64 encoded as a string";
427 let v = v.as_str().ok_or_else(|| {
428 Error::custom(format!("Wrong type, expecting {} value", ERR))
429 })?;
430 v.parse::<u64>().map_err(|_| {
431 Error::custom(format!("Parse error, expecting {} value", ERR))
432 })?
433 } else {
434 0u64
435 };
436 Ok(Variant::UInt64(v))
437 }
438 t if t == VariantJsonId::Float as u32 => Ok(Variant::Float(Self::numeric_f64(
439 body,
440 "Float",
441 f32::MIN as f64,
442 f32::MAX as f64,
443 )? as f32)),
444 t if t == VariantJsonId::Double as u32 => Ok(Variant::Double(Self::numeric_f64(
445 body,
446 "Double",
447 f64::MIN,
448 f64::MAX,
449 )?)),
450 t if t == VariantJsonId::String as u32 => {
451 if let Some(ref v) = body {
452 if v.is_null() {
453 Ok(Variant::String(UAString::null()))
454 } else {
455 json_as_value(body, "UAString").map(|v| Variant::String(v))
456 }
457 } else {
458 Ok(Variant::String(UAString::null()))
459 }
460 }
461 t if t == VariantJsonId::DateTime as u32 => {
462 json_as_value(body, "DateTime").map(|v| Variant::DateTime(Box::new(v)))
463 }
464 t if t == VariantJsonId::Guid as u32 => {
465 json_as_value(body, "Guid").map(|v| Variant::Guid(Box::new(v)))
466 }
467 t if t == VariantJsonId::ByteString as u32 => {
468 if let Some(ref v) = body {
469 if v.is_null() {
470 Ok(Variant::ByteString(ByteString::null()))
471 } else {
472 json_as_value(body, "ByteString").map(|v| Variant::ByteString(v))
473 }
474 } else {
475 Ok(Variant::ByteString(ByteString::null()))
476 }
477 }
478 t if t == VariantJsonId::XmlElement as u32 => {
479 json_as_value(body, "XmlElement").map(|v| Variant::XmlElement(v))
480 }
481 t if t == VariantJsonId::NodeId as u32 => {
482 json_as_value(body, "NodeId").map(|v| Variant::NodeId(Box::new(v)))
483 }
484 t if t == VariantJsonId::ExpandedNodeId as u32 => {
485 json_as_value(body, "ExpandedNodeId").map(|v| Variant::ExpandedNodeId(Box::new(v)))
486 }
487 t if t == VariantJsonId::StatusCode as u32 => {
488 if let Some(v) = body {
489 let v = serde_json::from_value::<u32>(v)
490 .map_err(|_| Error::custom("Invalid value, cannot parse StatusCode"))?;
491 Ok(Variant::StatusCode(StatusCode::from_bits_truncate(v)))
492 } else {
493 Err(Error::custom("Invalid value, cannot parse StatusCode"))
494 }
495 }
496 t if t == VariantJsonId::QualifiedName as u32 => {
497 json_as_value(body, "QualifiedName").map(|v| Variant::QualifiedName(Box::new(v)))
498 }
499 t if t == VariantJsonId::LocalizedText as u32 => {
500 json_as_value(body, "LocalizedText").map(|v| Variant::LocalizedText(Box::new(v)))
501 }
502 t if t == VariantJsonId::ExtensionObject as u32 => {
503 json_as_value(body, "ExtensionObject")
504 .map(|v| Variant::ExtensionObject(Box::new(v)))
505 }
506 t if t == VariantJsonId::DataValue as u32 => {
507 json_as_value(body, "DataValue").map(|v| Variant::DataValue(Box::new(v)))
508 }
509 t if t == VariantJsonId::Variant as u32 => {
510 json_as_value(body, "Variant").map(|v| Variant::Variant(Box::new(v)))
511 }
512 t if t == VariantJsonId::DiagnosticInfo as u32 => {
513 json_as_value(body, "DiagnosticInfo").map(|v| Variant::DiagnosticInfo(Box::new(v)))
514 }
515 t => Err(Error::custom(format!("Unhandled type {}", t))),
516 }
517 }
518}
519
520impl<'de> Deserialize<'de> for Variant {
521 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
522 where
523 D: Deserializer<'de>,
524 {
525 deserializer.deserialize_option(VariantVisitor)
526 }
527}
528
529impl Variant {
530 fn json_id(&self) -> VariantJsonId {
531 match self {
532 Variant::Empty => VariantJsonId::Empty,
533 Variant::Boolean(_) => VariantJsonId::Boolean,
534 Variant::SByte(_) => VariantJsonId::SByte,
535 Variant::Byte(_) => VariantJsonId::Byte,
536 Variant::Int16(_) => VariantJsonId::Int16,
537 Variant::UInt16(_) => VariantJsonId::UInt16,
538 Variant::Int32(_) => VariantJsonId::Int32,
539 Variant::UInt32(_) => VariantJsonId::UInt32,
540 Variant::Int64(_) => VariantJsonId::Int64,
541 Variant::UInt64(_) => VariantJsonId::UInt64,
542 Variant::Float(_) => VariantJsonId::Float,
543 Variant::Double(_) => VariantJsonId::Double,
544 Variant::String(_) => VariantJsonId::String,
545 Variant::DateTime(_) => VariantJsonId::DateTime,
546 Variant::Guid(_) => VariantJsonId::Guid,
547 Variant::ByteString(_) => VariantJsonId::ByteString,
548 Variant::XmlElement(_) => VariantJsonId::XmlElement,
549 Variant::NodeId(_) => VariantJsonId::NodeId,
550 Variant::ExpandedNodeId(_) => VariantJsonId::ExpandedNodeId,
551 Variant::StatusCode(_) => VariantJsonId::StatusCode,
552 Variant::QualifiedName(_) => VariantJsonId::QualifiedName,
553 Variant::LocalizedText(_) => VariantJsonId::LocalizedText,
554 Variant::ExtensionObject(_) => VariantJsonId::ExtensionObject,
555 Variant::Variant(_) => VariantJsonId::Variant,
556 Variant::DataValue(_) => VariantJsonId::DataValue,
557 Variant::DiagnosticInfo(_) => VariantJsonId::DiagnosticInfo,
558 _ => {
559 panic!("Cannot return type")
561 }
562 }
563 }
564}