1use std::io::{Cursor, Read};
4
5use crate::{
6 json::*, ByteString, DataValue, DateTime, DiagnosticInfo, EncodingResult, Error,
7 ExpandedNodeId, ExtensionObject, Guid, LocalizedText, NodeId, QualifiedName, StatusCode,
8 UAString, Variant, VariantScalarTypeId, XmlElement,
9};
10
11impl Variant {
12 pub fn serialize_variant_value(
17 &self,
18 stream: &mut JsonStreamWriter<&mut dyn std::io::Write>,
19 ctx: &crate::Context<'_>,
20 ) -> crate::EncodingResult<()> {
21 match self {
22 Variant::Empty => stream.null_value()?,
23 Variant::Boolean(v) => JsonEncodable::encode(v, stream, ctx)?,
24 Variant::SByte(v) => JsonEncodable::encode(v, stream, ctx)?,
25 Variant::Byte(v) => JsonEncodable::encode(v, stream, ctx)?,
26 Variant::Int16(v) => JsonEncodable::encode(v, stream, ctx)?,
27 Variant::UInt16(v) => JsonEncodable::encode(v, stream, ctx)?,
28 Variant::Int32(v) => JsonEncodable::encode(v, stream, ctx)?,
29 Variant::UInt32(v) => JsonEncodable::encode(v, stream, ctx)?,
30 Variant::Int64(v) => JsonEncodable::encode(v, stream, ctx)?,
31 Variant::UInt64(v) => JsonEncodable::encode(v, stream, ctx)?,
32 Variant::Float(v) => JsonEncodable::encode(v, stream, ctx)?,
33 Variant::Double(v) => JsonEncodable::encode(v, stream, ctx)?,
34 Variant::String(v) => JsonEncodable::encode(v, stream, ctx)?,
35 Variant::DateTime(v) => JsonEncodable::encode(v, stream, ctx)?,
36 Variant::Guid(v) => JsonEncodable::encode(v, stream, ctx)?,
37 Variant::StatusCode(v) => JsonEncodable::encode(v, stream, ctx)?,
38 Variant::ByteString(v) => JsonEncodable::encode(v, stream, ctx)?,
39 Variant::XmlElement(v) => JsonEncodable::encode(v, stream, ctx)?,
40 Variant::QualifiedName(v) => JsonEncodable::encode(v, stream, ctx)?,
41 Variant::LocalizedText(v) => JsonEncodable::encode(v, stream, ctx)?,
42 Variant::NodeId(v) => JsonEncodable::encode(v, stream, ctx)?,
43 Variant::ExpandedNodeId(v) => JsonEncodable::encode(v, stream, ctx)?,
44 Variant::ExtensionObject(v) => JsonEncodable::encode(v, stream, ctx)?,
45 Variant::Variant(v) => JsonEncodable::encode(v, stream, ctx)?,
46 Variant::DataValue(v) => JsonEncodable::encode(v, stream, ctx)?,
47 Variant::DiagnosticInfo(v) => JsonEncodable::encode(v, stream, ctx)?,
48 Variant::Array(array) => {
49 stream.begin_array()?;
51 for v in &array.values {
52 v.serialize_variant_value(stream, ctx)?;
53 }
54 stream.end_array()?;
55 }
56 }
57
58 Ok(())
59 }
60}
61
62impl JsonEncodable for Variant {
63 fn encode(
64 &self,
65 stream: &mut JsonStreamWriter<&mut dyn std::io::Write>,
66 ctx: &crate::Context<'_>,
67 ) -> crate::EncodingResult<()> {
68 let type_id = match self.type_id() {
69 crate::VariantTypeId::Empty => {
70 stream.null_value()?;
71 return Ok(());
72 }
73 crate::VariantTypeId::Scalar(s) => s,
74 crate::VariantTypeId::Array(s, _) => s,
75 };
76
77 stream.begin_object()?;
78
79 stream.name("Type")?;
80 stream.number_value(type_id as u32)?;
81
82 if let Variant::Array(a) = self {
83 if let Some(dims) = a.dimensions.as_ref() {
84 if dims.len() > 1 {
85 stream.name("Dimensions")?;
86 JsonEncodable::encode(dims, stream, ctx)?;
87 }
88 }
89 stream.name("Body")?;
90 stream.begin_array()?;
91 for v in &a.values {
92 v.serialize_variant_value(stream, ctx)?;
93 }
94 stream.end_array()?;
95 } else {
96 stream.name("Body")?;
97 self.serialize_variant_value(stream, ctx)?;
98 }
99 stream.end_object()?;
100
101 Ok(())
102 }
103}
104
105enum VariantOrArray {
106 Single(Variant),
107 Array(Vec<Variant>),
108}
109
110impl JsonDecodable for Variant {
111 fn decode(
112 stream: &mut JsonStreamReader<&mut dyn std::io::Read>,
113 ctx: &Context<'_>,
114 ) -> EncodingResult<Self> {
115 if stream.peek()? == ValueType::Null {
116 stream.next_null()?;
117 return Ok(Self::Empty);
118 }
119
120 stream.begin_object()?;
121
122 fn dec_body<T>(
123 stream: &mut JsonStreamReader<&mut dyn std::io::Read>,
124 ctx: &Context<'_>,
125 ) -> EncodingResult<VariantOrArray>
126 where
127 T: Into<Variant> + JsonDecodable + Default,
128 {
129 match stream.peek()? {
130 ValueType::Array => {
131 let mut res = Vec::new();
132 stream.begin_array()?;
133 while stream.has_next()? {
134 res.push(T::decode(stream, ctx)?.into());
135 }
136 stream.end_array()?;
137 Ok(VariantOrArray::Array(res))
138 }
139 ValueType::Null => Ok(VariantOrArray::Single(T::default().into())),
140 _ => Ok(VariantOrArray::Single(T::decode(stream, ctx)?.into())),
141 }
142 }
143
144 fn dec_body_dyn(
145 stream: &mut JsonStreamReader<&mut dyn std::io::Read>,
146 ctx: &Context<'_>,
147 type_id: VariantScalarTypeId,
148 ) -> EncodingResult<VariantOrArray> {
149 match type_id {
150 VariantScalarTypeId::Boolean => dec_body::<bool>(stream, ctx),
151 VariantScalarTypeId::SByte => dec_body::<i8>(stream, ctx),
152 VariantScalarTypeId::Byte => dec_body::<u8>(stream, ctx),
153 VariantScalarTypeId::Int16 => dec_body::<i16>(stream, ctx),
154 VariantScalarTypeId::UInt16 => dec_body::<u16>(stream, ctx),
155 VariantScalarTypeId::Int32 => dec_body::<i32>(stream, ctx),
156 VariantScalarTypeId::UInt32 => dec_body::<u32>(stream, ctx),
157 VariantScalarTypeId::Int64 => dec_body::<i64>(stream, ctx),
158 VariantScalarTypeId::UInt64 => dec_body::<u64>(stream, ctx),
159 VariantScalarTypeId::Float => dec_body::<f32>(stream, ctx),
160 VariantScalarTypeId::Double => dec_body::<f64>(stream, ctx),
161 VariantScalarTypeId::String => dec_body::<UAString>(stream, ctx),
162 VariantScalarTypeId::DateTime => dec_body::<DateTime>(stream, ctx),
163 VariantScalarTypeId::Guid => dec_body::<Guid>(stream, ctx),
164 VariantScalarTypeId::ByteString => dec_body::<ByteString>(stream, ctx),
165 VariantScalarTypeId::XmlElement => dec_body::<XmlElement>(stream, ctx),
166 VariantScalarTypeId::NodeId => dec_body::<NodeId>(stream, ctx),
167 VariantScalarTypeId::ExpandedNodeId => dec_body::<ExpandedNodeId>(stream, ctx),
168 VariantScalarTypeId::StatusCode => dec_body::<StatusCode>(stream, ctx),
169 VariantScalarTypeId::QualifiedName => dec_body::<QualifiedName>(stream, ctx),
170 VariantScalarTypeId::LocalizedText => dec_body::<LocalizedText>(stream, ctx),
171 VariantScalarTypeId::ExtensionObject => dec_body::<ExtensionObject>(stream, ctx),
172 VariantScalarTypeId::DataValue => dec_body::<DataValue>(stream, ctx),
173 VariantScalarTypeId::Variant => {
174 let v = dec_body::<Variant>(stream, ctx)?;
175 match v {
178 VariantOrArray::Single(variant) => {
179 Ok(VariantOrArray::Single(Variant::Variant(Box::new(variant))))
180 }
181 VariantOrArray::Array(vec) => Ok(VariantOrArray::Array(vec)),
182 }
183 }
184 VariantScalarTypeId::DiagnosticInfo => dec_body::<DiagnosticInfo>(stream, ctx),
185 }
186 }
187
188 let mut type_id = None;
189 let mut value = None;
190 let mut dimensions: Option<Vec<u32>> = None;
191 let mut raw_value = None;
192 while stream.has_next()? {
193 match stream.next_name()? {
194 "Type" => {
195 let ty: u32 = stream.next_number()??;
196 if ty != 0 {
197 type_id = Some(VariantScalarTypeId::try_from(ty).map_err(|_| {
198 Error::decoding(format!("Unexpected variant type: {ty}"))
199 })?);
200 }
201 }
202 "Body" => {
203 if let Some(type_id) = type_id {
204 value = Some(dec_body_dyn(stream, ctx, type_id)?);
205 } else {
206 raw_value = Some(consume_raw_value(stream)?);
207 }
208 }
209 "Dimensions" => {
210 dimensions = JsonDecodable::decode(stream, ctx)?;
211 }
212 _ => {
213 stream.skip_value()?;
214 }
215 }
216 }
217
218 let Some(type_id) = type_id else {
219 stream.end_object()?;
220 return Ok(Variant::Empty);
221 };
222
223 if let Some(raw_value) = raw_value {
224 let mut cursor = Cursor::new(raw_value);
225 let mut inner_stream = JsonStreamReader::new(&mut cursor as &mut dyn Read);
226 value = Some(dec_body_dyn(&mut inner_stream, ctx, type_id)?);
227 }
228
229 let value = value.unwrap_or_else(|| {
230 VariantOrArray::Single(match type_id {
231 VariantScalarTypeId::Boolean => Variant::from(bool::default()),
232 VariantScalarTypeId::SByte => Variant::from(i8::default()),
233 VariantScalarTypeId::Byte => Variant::from(u8::default()),
234 VariantScalarTypeId::Int16 => Variant::from(i16::default()),
235 VariantScalarTypeId::UInt16 => Variant::from(u16::default()),
236 VariantScalarTypeId::Int32 => Variant::from(i32::default()),
237 VariantScalarTypeId::UInt32 => Variant::from(u32::default()),
238 VariantScalarTypeId::Int64 => Variant::from(i64::default()),
239 VariantScalarTypeId::UInt64 => Variant::from(u64::default()),
240 VariantScalarTypeId::Float => Variant::from(f32::default()),
241 VariantScalarTypeId::Double => Variant::from(f64::default()),
242 VariantScalarTypeId::String => Variant::from(UAString::default()),
243 VariantScalarTypeId::DateTime => Variant::from(DateTime::default()),
244 VariantScalarTypeId::Guid => Variant::from(Guid::default()),
245 VariantScalarTypeId::ByteString => Variant::from(ByteString::default()),
246 VariantScalarTypeId::XmlElement => Variant::from(XmlElement::default()),
247 VariantScalarTypeId::NodeId => Variant::from(NodeId::default()),
248 VariantScalarTypeId::ExpandedNodeId => Variant::from(ExpandedNodeId::default()),
249 VariantScalarTypeId::StatusCode => Variant::from(StatusCode::default()),
250 VariantScalarTypeId::QualifiedName => Variant::from(QualifiedName::default()),
251 VariantScalarTypeId::LocalizedText => Variant::from(LocalizedText::default()),
252 VariantScalarTypeId::ExtensionObject => Variant::from(ExtensionObject::default()),
253 VariantScalarTypeId::DataValue => Variant::from(DataValue::default()),
254 VariantScalarTypeId::Variant => Variant::Variant(Box::default()),
255 VariantScalarTypeId::DiagnosticInfo => Variant::from(DiagnosticInfo::default()),
256 })
257 });
258
259 let variant = match (value, dimensions) {
260 (VariantOrArray::Single(variant), None) => variant,
261 (VariantOrArray::Single(_), Some(_)) => {
262 return Err(Error::decoding(
263 "Unexpected dimensions for scalar variant value during json decoding",
264 ));
265 }
266 (VariantOrArray::Array(vec), d) => Variant::Array(Box::new(crate::Array {
267 value_type: type_id,
268 values: vec,
269 dimensions: d,
270 })),
271 };
272
273 stream.end_object()?;
274
275 Ok(variant)
276 }
277}