opcua_types/
data_value.rs1use std::io::{Read, Write};
8
9use crate::{
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)]
35pub struct DataValue {
36 pub value: Option<Variant>,
39 pub status: Option<StatusCode>,
42 pub source_timestamp: Option<DateTime>,
45 pub source_picoseconds: Option<i16>,
49 pub server_timestamp: Option<DateTime>,
52 pub server_picoseconds: Option<i16>,
56}
57
58impl BinaryEncoder<DataValue> for DataValue {
59 fn byte_len(&self) -> usize {
60 let mut size = 1;
61 let encoding_mask = self.encoding_mask();
62 if encoding_mask.contains(DataValueFlags::HAS_VALUE) {
63 size += self.value.as_ref().unwrap().byte_len();
64 }
65 if encoding_mask.contains(DataValueFlags::HAS_STATUS) {
66 size += self.status.as_ref().unwrap().byte_len();
67 }
68 if encoding_mask.contains(DataValueFlags::HAS_SOURCE_TIMESTAMP) {
69 size += self.source_timestamp.as_ref().unwrap().byte_len();
70 if encoding_mask.contains(DataValueFlags::HAS_SOURCE_PICOSECONDS) {
71 size += self.source_picoseconds.as_ref().unwrap().byte_len();
72 }
73 }
74 if encoding_mask.contains(DataValueFlags::HAS_SERVER_TIMESTAMP) {
75 size += self.server_timestamp.as_ref().unwrap().byte_len();
76 if encoding_mask.contains(DataValueFlags::HAS_SERVER_PICOSECONDS) {
77 size += self.server_picoseconds.as_ref().unwrap().byte_len();
78 }
79 }
80 size
81 }
82
83 fn encode<S: Write>(&self, stream: &mut S) -> EncodingResult<usize> {
84 let mut size = 0;
85
86 let encoding_mask = self.encoding_mask();
87 size += encoding_mask.bits.encode(stream)?;
88
89 if encoding_mask.contains(DataValueFlags::HAS_VALUE) {
90 size += self.value.as_ref().unwrap().encode(stream)?;
91 }
92 if encoding_mask.contains(DataValueFlags::HAS_STATUS) {
93 size += self.status.as_ref().unwrap().bits().encode(stream)?;
94 }
95 if encoding_mask.contains(DataValueFlags::HAS_SOURCE_TIMESTAMP) {
96 size += self.source_timestamp.as_ref().unwrap().encode(stream)?;
97 if encoding_mask.contains(DataValueFlags::HAS_SOURCE_PICOSECONDS) {
98 size += self.source_picoseconds.as_ref().unwrap().encode(stream)?;
99 }
100 }
101 if encoding_mask.contains(DataValueFlags::HAS_SERVER_TIMESTAMP) {
102 size += self.server_timestamp.as_ref().unwrap().encode(stream)?;
103 if encoding_mask.contains(DataValueFlags::HAS_SERVER_PICOSECONDS) {
104 size += self.server_picoseconds.as_ref().unwrap().encode(stream)?;
105 }
106 }
107 Ok(size)
108 }
109
110 fn decode<S: Read>(stream: &mut S, decoding_options: &DecodingOptions) -> EncodingResult<Self> {
111 let encoding_mask =
112 DataValueFlags::from_bits_truncate(u8::decode(stream, decoding_options)?);
113
114 let value = if encoding_mask.contains(DataValueFlags::HAS_VALUE) {
116 Some(Variant::decode(stream, decoding_options)?)
117 } else {
118 None
119 };
120 let status = if encoding_mask.contains(DataValueFlags::HAS_STATUS) {
122 let status = StatusCode::from_bits_truncate(u32::decode(stream, decoding_options)?);
123 Some(status)
124 } else {
125 None
126 };
127 let source_timestamp = if encoding_mask.contains(DataValueFlags::HAS_SOURCE_TIMESTAMP) {
129 let decoding_options = DecodingOptions {
131 client_offset: chrono::Duration::zero(),
132 ..*decoding_options
133 };
134 Some(DateTime::decode(stream, &decoding_options)?)
135 } else {
136 None
137 };
138 let source_picoseconds = if encoding_mask.contains(DataValueFlags::HAS_SOURCE_PICOSECONDS) {
139 Some(i16::decode(stream, decoding_options)?)
140 } else {
141 None
142 };
143 let server_timestamp = if encoding_mask.contains(DataValueFlags::HAS_SERVER_TIMESTAMP) {
145 Some(DateTime::decode(stream, decoding_options)?)
146 } else {
147 None
148 };
149 let server_picoseconds = if encoding_mask.contains(DataValueFlags::HAS_SERVER_PICOSECONDS) {
150 Some(i16::decode(stream, decoding_options)?)
151 } else {
152 None
153 };
154 Ok(DataValue {
156 value,
157 status,
158 source_picoseconds: if source_timestamp.is_some() {
159 source_picoseconds
160 } else {
161 None
162 },
163 source_timestamp,
164 server_picoseconds: if server_timestamp.is_some() {
165 server_picoseconds
166 } else {
167 None
168 },
169 server_timestamp,
170 })
171 }
172}
173
174impl From<bool> for DataValue {
178 fn from(v: bool) -> Self {
179 Self::from(Variant::from(v))
180 }
181}
182
183impl From<u8> for DataValue {
184 fn from(v: u8) -> Self {
185 Self::from(Variant::from(v))
186 }
187}
188
189impl From<i8> for DataValue {
190 fn from(v: i8) -> Self {
191 Self::from(Variant::from(v))
192 }
193}
194
195impl From<i16> for DataValue {
196 fn from(v: i16) -> Self {
197 Self::from(Variant::from(v))
198 }
199}
200
201impl From<u16> for DataValue {
202 fn from(v: u16) -> Self {
203 Self::from(Variant::from(v))
204 }
205}
206
207impl From<i32> for DataValue {
208 fn from(v: i32) -> Self {
209 Self::from(Variant::from(v))
210 }
211}
212
213impl From<u32> for DataValue {
214 fn from(v: u32) -> Self {
215 Self::from(Variant::from(v))
216 }
217}
218
219impl From<i64> for DataValue {
220 fn from(v: i64) -> Self {
221 Self::from(Variant::from(v))
222 }
223}
224
225impl From<u64> for DataValue {
226 fn from(v: u64) -> Self {
227 Self::from(Variant::from(v))
228 }
229}
230
231impl From<f32> for DataValue {
232 fn from(v: f32) -> Self {
233 Self::from(Variant::from(v))
234 }
235}
236
237impl From<f64> for DataValue {
238 fn from(v: f64) -> Self {
239 Self::from(Variant::from(v))
240 }
241}
242
243impl<'a> From<&'a str> for DataValue {
244 fn from(v: &'a str) -> Self {
245 Self::from(Variant::from(v))
246 }
247}
248
249impl From<String> for DataValue {
250 fn from(v: String) -> Self {
251 Self::from(Variant::from(v))
252 }
253}
254
255impl From<UAString> for DataValue {
256 fn from(v: UAString) -> Self {
257 Self::from(Variant::from(v))
258 }
259}
260
261impl From<DateTime> for DataValue {
262 fn from(v: DateTime) -> Self {
263 Self::from(Variant::from(v))
264 }
265}
266
267impl From<Guid> for DataValue {
268 fn from(v: Guid) -> Self {
269 Self::from(Variant::from(v))
270 }
271}
272
273impl From<StatusCode> for DataValue {
274 fn from(v: StatusCode) -> Self {
275 Self::from(Variant::from(v))
276 }
277}
278
279impl From<ByteString> for DataValue {
280 fn from(v: ByteString) -> Self {
281 Self::from(Variant::from(v))
282 }
283}
284
285impl From<QualifiedName> for DataValue {
286 fn from(v: QualifiedName) -> Self {
287 Self::from(Variant::from(v))
288 }
289}
290
291impl From<LocalizedText> for DataValue {
292 fn from(v: LocalizedText) -> Self {
293 Self::from(Variant::from(v))
294 }
295}
296
297impl From<NodeId> for DataValue {
298 fn from(v: NodeId) -> Self {
299 Self::from(Variant::from(v))
300 }
301}
302impl From<Variant> for DataValue {
305 fn from(v: Variant) -> Self {
306 DataValue::value_only(v)
307 }
308}
309
310impl From<(Variant, StatusCode)> for DataValue {
311 fn from(v: (Variant, StatusCode)) -> Self {
312 DataValue {
313 value: Some(v.0),
314 status: Some(v.1),
315 source_timestamp: None,
316 source_picoseconds: None,
317 server_timestamp: None,
318 server_picoseconds: None,
319 }
320 }
321}
322
323impl Default for DataValue {
353 fn default() -> Self {
354 Self::null()
355 }
356}
357
358impl DataValue {
359 pub fn value_only<V>(value: V) -> DataValue
361 where
362 V: Into<Variant>,
363 {
364 DataValue {
365 value: Some(value.into()),
366 status: None,
367 source_timestamp: None,
368 source_picoseconds: None,
369 server_timestamp: None,
370 server_picoseconds: None,
371 }
372 }
373
374 pub fn new_now<V>(value: V) -> DataValue
382 where
383 V: Into<Variant>,
384 {
385 let now = DateTime::now();
386 DataValue {
387 value: Some(value.into()),
388 status: Some(StatusCode::Good),
389 source_timestamp: Some(now),
390 source_picoseconds: Some(0),
391 server_timestamp: Some(now),
392 server_picoseconds: Some(0),
393 }
394 }
395
396 pub fn null() -> DataValue {
398 DataValue {
399 value: None,
400 status: None,
401 source_timestamp: None,
402 source_picoseconds: None,
403 server_timestamp: None,
404 server_picoseconds: None,
405 }
406 }
407
408 pub fn set_value<V>(
410 &mut self,
411 value: V,
412 source_timestamp: &DateTime,
413 server_timestamp: &DateTime,
414 ) where
415 V: Into<Variant>,
416 {
417 self.value = Some(value.into());
418 self.source_timestamp = Some(*source_timestamp);
419 self.source_picoseconds = Some(0);
420 self.server_timestamp = Some(*server_timestamp);
421 self.server_picoseconds = Some(0);
422 }
423
424 pub fn set_timestamps(
426 &mut self,
427 timestamps_to_return: TimestampsToReturn,
428 source_timestamp: DateTime,
429 server_timestamp: DateTime,
430 ) {
431 match timestamps_to_return {
432 TimestampsToReturn::Source => {
433 self.source_timestamp = Some(source_timestamp);
434 self.source_picoseconds = Some(0);
435 self.server_timestamp = None;
436 self.server_picoseconds = None;
437 }
438 TimestampsToReturn::Server => {
439 self.source_timestamp = None;
440 self.source_picoseconds = None;
441 self.server_timestamp = Some(server_timestamp);
442 self.server_picoseconds = Some(0);
443 }
444 TimestampsToReturn::Both => {
445 self.source_timestamp = Some(source_timestamp);
446 self.source_picoseconds = Some(0);
447 self.server_timestamp = Some(server_timestamp);
448 self.server_picoseconds = Some(0);
449 }
450 TimestampsToReturn::Neither => {
451 self.source_timestamp = None;
452 self.source_picoseconds = None;
453 self.server_timestamp = None;
454 self.server_picoseconds = None;
455 }
456 _ => {}
457 }
458 }
459
460 pub fn status(&self) -> StatusCode {
462 self.status.map_or(StatusCode::Good, |s| s)
463 }
464
465 pub fn is_valid(&self) -> bool {
468 self.status().status().is_good()
469 }
470
471 fn encoding_mask(&self) -> DataValueFlags {
472 let mut encoding_mask = DataValueFlags::empty();
473 if self.value.is_some() {
474 encoding_mask |= DataValueFlags::HAS_VALUE;
475 }
476 if self.status.is_some() {
477 encoding_mask |= DataValueFlags::HAS_STATUS;
478 }
479 if self.source_timestamp.is_some() {
480 encoding_mask |= DataValueFlags::HAS_SOURCE_TIMESTAMP;
481 if self.source_picoseconds.is_some() {
482 encoding_mask |= DataValueFlags::HAS_SOURCE_PICOSECONDS;
483 }
484 }
485 if self.server_timestamp.is_some() {
486 encoding_mask |= DataValueFlags::HAS_SERVER_TIMESTAMP;
487 if self.server_picoseconds.is_some() {
488 encoding_mask |= DataValueFlags::HAS_SERVER_PICOSECONDS;
489 }
490 }
491 encoding_mask
492 }
493}