opcua/types/
data_value.rs1use std::io::{Read, Write};
8
9use crate::types::{
10 byte_string::ByteString, date_time::*, encoding::*, guid::Guid, localized_text::LocalizedText,
11 node_id::NodeId, qualified_name::QualifiedName, service_types::TimestampsToReturn,
12 status_codes::StatusCode, string::UAString, variant::Variant,
13};
14
15bitflags! {
16 struct DataValueFlags: u8 {
17 const HAS_VALUE = 0x1;
19 const HAS_STATUS = 0x2;
21 const HAS_SOURCE_TIMESTAMP = 0x4;
23 const HAS_SERVER_TIMESTAMP = 0x8;
25 const HAS_SOURCE_PICOSECONDS = 0x10;
27 const HAS_SERVER_PICOSECONDS = 0x20;
29 }
30}
31
32#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
35#[serde(rename_all = "PascalCase")]
36pub struct DataValue {
37 #[serde(skip_serializing_if = "Option::is_none")]
40 pub value: Option<Variant>,
41 #[serde(skip_serializing_if = "Option::is_none")]
44 pub status: Option<StatusCode>,
45 #[serde(skip_serializing_if = "Option::is_none")]
48 pub source_timestamp: Option<DateTime>,
49 #[serde(skip_serializing_if = "Option::is_none")]
53 pub source_picoseconds: Option<u16>,
54 #[serde(skip_serializing_if = "Option::is_none")]
57 pub server_timestamp: Option<DateTime>,
58 #[serde(skip_serializing_if = "Option::is_none")]
62 pub server_picoseconds: Option<u16>,
63}
64
65impl BinaryEncoder<DataValue> for DataValue {
66 fn byte_len(&self) -> usize {
67 let mut size = 1;
68 let encoding_mask = self.encoding_mask();
69 if encoding_mask.contains(DataValueFlags::HAS_VALUE) {
70 size += self.value.as_ref().unwrap().byte_len();
71 }
72 if encoding_mask.contains(DataValueFlags::HAS_STATUS) {
73 size += self.status.as_ref().unwrap().byte_len();
74 }
75 if encoding_mask.contains(DataValueFlags::HAS_SOURCE_TIMESTAMP) {
76 size += self.source_timestamp.as_ref().unwrap().byte_len();
77 if encoding_mask.contains(DataValueFlags::HAS_SOURCE_PICOSECONDS) {
78 size += self.source_picoseconds.as_ref().unwrap().byte_len();
79 }
80 }
81 if encoding_mask.contains(DataValueFlags::HAS_SERVER_TIMESTAMP) {
82 size += self.server_timestamp.as_ref().unwrap().byte_len();
83 if encoding_mask.contains(DataValueFlags::HAS_SERVER_PICOSECONDS) {
84 size += self.server_picoseconds.as_ref().unwrap().byte_len();
85 }
86 }
87 size
88 }
89
90 fn encode<S: Write>(&self, stream: &mut S) -> EncodingResult<usize> {
91 let mut size = 0;
92
93 let encoding_mask = self.encoding_mask();
94 size += encoding_mask.bits.encode(stream)?;
95
96 if encoding_mask.contains(DataValueFlags::HAS_VALUE) {
97 size += self.value.as_ref().unwrap().encode(stream)?;
98 }
99 if encoding_mask.contains(DataValueFlags::HAS_STATUS) {
100 size += self.status.as_ref().unwrap().bits().encode(stream)?;
101 }
102 if encoding_mask.contains(DataValueFlags::HAS_SOURCE_TIMESTAMP) {
103 size += self.source_timestamp.as_ref().unwrap().encode(stream)?;
104 if encoding_mask.contains(DataValueFlags::HAS_SOURCE_PICOSECONDS) {
105 size += self.source_picoseconds.as_ref().unwrap().encode(stream)?;
106 }
107 }
108 if encoding_mask.contains(DataValueFlags::HAS_SERVER_TIMESTAMP) {
109 size += self.server_timestamp.as_ref().unwrap().encode(stream)?;
110 if encoding_mask.contains(DataValueFlags::HAS_SERVER_PICOSECONDS) {
111 size += self.server_picoseconds.as_ref().unwrap().encode(stream)?;
112 }
113 }
114 Ok(size)
115 }
116
117 fn decode<S: Read>(stream: &mut S, decoding_options: &DecodingOptions) -> EncodingResult<Self> {
118 let encoding_mask =
119 DataValueFlags::from_bits_truncate(u8::decode(stream, decoding_options)?);
120
121 let value = if encoding_mask.contains(DataValueFlags::HAS_VALUE) {
123 Some(Variant::decode(stream, decoding_options)?)
124 } else {
125 None
126 };
127 let status = if encoding_mask.contains(DataValueFlags::HAS_STATUS) {
129 let status = StatusCode::from_bits_truncate(u32::decode(stream, decoding_options)?);
130 Some(status)
131 } else {
132 None
133 };
134 let source_timestamp = if encoding_mask.contains(DataValueFlags::HAS_SOURCE_TIMESTAMP) {
136 let decoding_options = DecodingOptions {
138 client_offset: chrono::Duration::zero(),
139 ..decoding_options.clone()
140 };
141 Some(DateTime::decode(stream, &decoding_options)?)
142 } else {
143 None
144 };
145 let source_picoseconds = if encoding_mask.contains(DataValueFlags::HAS_SOURCE_PICOSECONDS) {
146 Some(u16::decode(stream, decoding_options)?)
147 } else {
148 None
149 };
150 let server_timestamp = if encoding_mask.contains(DataValueFlags::HAS_SERVER_TIMESTAMP) {
152 Some(DateTime::decode(stream, decoding_options)?)
153 } else {
154 None
155 };
156 let server_picoseconds = if encoding_mask.contains(DataValueFlags::HAS_SERVER_PICOSECONDS) {
157 Some(u16::decode(stream, decoding_options)?)
158 } else {
159 None
160 };
161 Ok(DataValue {
163 value,
164 status,
165 source_picoseconds: if source_timestamp.is_some() {
166 source_picoseconds
167 } else {
168 None
169 },
170 source_timestamp,
171 server_picoseconds: if server_timestamp.is_some() {
172 server_picoseconds
173 } else {
174 None
175 },
176 server_timestamp,
177 })
178 }
179}
180
181impl From<bool> for DataValue {
185 fn from(v: bool) -> Self {
186 Self::from(Variant::from(v))
187 }
188}
189
190impl From<u8> for DataValue {
191 fn from(v: u8) -> Self {
192 Self::from(Variant::from(v))
193 }
194}
195
196impl From<i8> for DataValue {
197 fn from(v: i8) -> Self {
198 Self::from(Variant::from(v))
199 }
200}
201
202impl From<i16> for DataValue {
203 fn from(v: i16) -> Self {
204 Self::from(Variant::from(v))
205 }
206}
207
208impl From<u16> for DataValue {
209 fn from(v: u16) -> Self {
210 Self::from(Variant::from(v))
211 }
212}
213
214impl From<i32> for DataValue {
215 fn from(v: i32) -> Self {
216 Self::from(Variant::from(v))
217 }
218}
219
220impl From<u32> for DataValue {
221 fn from(v: u32) -> Self {
222 Self::from(Variant::from(v))
223 }
224}
225
226impl From<i64> for DataValue {
227 fn from(v: i64) -> Self {
228 Self::from(Variant::from(v))
229 }
230}
231
232impl From<u64> for DataValue {
233 fn from(v: u64) -> Self {
234 Self::from(Variant::from(v))
235 }
236}
237
238impl From<f32> for DataValue {
239 fn from(v: f32) -> Self {
240 Self::from(Variant::from(v))
241 }
242}
243
244impl From<f64> for DataValue {
245 fn from(v: f64) -> Self {
246 Self::from(Variant::from(v))
247 }
248}
249
250impl<'a> From<&'a str> for DataValue {
251 fn from(v: &'a str) -> Self {
252 Self::from(Variant::from(v))
253 }
254}
255
256impl From<String> for DataValue {
257 fn from(v: String) -> Self {
258 Self::from(Variant::from(v))
259 }
260}
261
262impl From<UAString> for DataValue {
263 fn from(v: UAString) -> Self {
264 Self::from(Variant::from(v))
265 }
266}
267
268impl From<DateTime> for DataValue {
269 fn from(v: DateTime) -> Self {
270 Self::from(Variant::from(v))
271 }
272}
273
274impl From<Guid> for DataValue {
275 fn from(v: Guid) -> Self {
276 Self::from(Variant::from(v))
277 }
278}
279
280impl From<StatusCode> for DataValue {
281 fn from(v: StatusCode) -> Self {
282 Self::from(Variant::from(v))
283 }
284}
285
286impl From<ByteString> for DataValue {
287 fn from(v: ByteString) -> Self {
288 Self::from(Variant::from(v))
289 }
290}
291
292impl From<QualifiedName> for DataValue {
293 fn from(v: QualifiedName) -> Self {
294 Self::from(Variant::from(v))
295 }
296}
297
298impl From<LocalizedText> for DataValue {
299 fn from(v: LocalizedText) -> Self {
300 Self::from(Variant::from(v))
301 }
302}
303
304impl From<NodeId> for DataValue {
305 fn from(v: NodeId) -> Self {
306 Self::from(Variant::from(v))
307 }
308}
309impl From<Variant> for DataValue {
312 fn from(v: Variant) -> Self {
313 DataValue::value_only(v)
314 }
315}
316
317impl From<(Variant, StatusCode)> for DataValue {
318 fn from(v: (Variant, StatusCode)) -> Self {
319 DataValue {
320 value: Some(v.0),
321 status: Some(v.1),
322 source_timestamp: None,
323 source_picoseconds: None,
324 server_timestamp: None,
325 server_picoseconds: None,
326 }
327 }
328}
329
330impl Default for DataValue {
360 fn default() -> Self {
361 Self::null()
362 }
363}
364
365impl DataValue {
366 pub fn value_only<V>(value: V) -> DataValue
368 where
369 V: Into<Variant>,
370 {
371 DataValue {
372 value: Some(value.into()),
373 status: None,
374 source_timestamp: None,
375 source_picoseconds: None,
376 server_timestamp: None,
377 server_picoseconds: None,
378 }
379 }
380
381 pub fn new_now<V>(value: V) -> DataValue
389 where
390 V: Into<Variant>,
391 {
392 let now = DateTime::now();
393 DataValue {
394 value: Some(value.into()),
395 status: Some(StatusCode::Good),
396 source_timestamp: Some(now),
397 source_picoseconds: Some(0),
398 server_timestamp: Some(now),
399 server_picoseconds: Some(0),
400 }
401 }
402
403 pub fn null() -> DataValue {
405 DataValue {
406 value: None,
407 status: None,
408 source_timestamp: None,
409 source_picoseconds: None,
410 server_timestamp: None,
411 server_picoseconds: None,
412 }
413 }
414
415 pub fn set_value<V>(
417 &mut self,
418 value: V,
419 source_timestamp: &DateTime,
420 server_timestamp: &DateTime,
421 ) where
422 V: Into<Variant>,
423 {
424 self.value = Some(value.into());
425 self.source_timestamp = Some(*source_timestamp);
426 self.source_picoseconds = Some(0);
427 self.server_timestamp = Some(*server_timestamp);
428 self.server_picoseconds = Some(0);
429 }
430
431 pub fn set_timestamps(
433 &mut self,
434 timestamps_to_return: TimestampsToReturn,
435 source_timestamp: DateTime,
436 server_timestamp: DateTime,
437 ) {
438 match timestamps_to_return {
439 TimestampsToReturn::Source => {
440 self.source_timestamp = Some(source_timestamp);
441 self.source_picoseconds = Some(0);
442 self.server_timestamp = None;
443 self.server_picoseconds = None;
444 }
445 TimestampsToReturn::Server => {
446 self.source_timestamp = None;
447 self.source_picoseconds = None;
448 self.server_timestamp = Some(server_timestamp);
449 self.server_picoseconds = Some(0);
450 }
451 TimestampsToReturn::Both => {
452 self.source_timestamp = Some(source_timestamp);
453 self.source_picoseconds = Some(0);
454 self.server_timestamp = Some(server_timestamp);
455 self.server_picoseconds = Some(0);
456 }
457 TimestampsToReturn::Neither => {
458 self.source_timestamp = None;
459 self.source_picoseconds = None;
460 self.server_timestamp = None;
461 self.server_picoseconds = None;
462 }
463 _ => {}
464 }
465 }
466
467 pub fn status(&self) -> StatusCode {
469 self.status.map_or(StatusCode::Good, |s| s)
470 }
471
472 pub fn is_valid(&self) -> bool {
475 self.status().status().is_good()
476 }
477
478 fn encoding_mask(&self) -> DataValueFlags {
479 let mut encoding_mask = DataValueFlags::empty();
480 if self.value.is_some() {
481 encoding_mask |= DataValueFlags::HAS_VALUE;
482 }
483 if self.status.is_some() {
484 encoding_mask |= DataValueFlags::HAS_STATUS;
485 }
486 if self.source_timestamp.is_some() {
487 encoding_mask |= DataValueFlags::HAS_SOURCE_TIMESTAMP;
488 if self.source_picoseconds.is_some() {
489 encoding_mask |= DataValueFlags::HAS_SOURCE_PICOSECONDS;
490 }
491 }
492 if self.server_timestamp.is_some() {
493 encoding_mask |= DataValueFlags::HAS_SERVER_TIMESTAMP;
494 if self.server_picoseconds.is_some() {
495 encoding_mask |= DataValueFlags::HAS_SERVER_PICOSECONDS;
496 }
497 }
498 encoding_mask
499 }
500}