1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
use std::marker::PhantomData;
use crate::{DataType, DataTypeExt, ua};
/// Typed variant of [`ua::DataValue`].
//
// Do not derive trait implementations (except `fmt::Debug`) to avoid
// depending on the capabilities of the generic, marker type `T`.
// Instead we implement all applicable traits manually by delegating
// to the implementations for `ua::DataValue` (see below).
#[derive(Debug)]
// ABI must match that of the the untyped variant ua::DataValue.
// Required to safely transmute both types.
#[repr(transparent)]
pub struct DataValue<T> {
data_value: ua::DataValue,
_kind: PhantomData<T>,
}
impl<T> Clone for DataValue<T> {
fn clone(&self) -> Self {
let Self {
data_value,
_kind: _,
} = self;
Self {
data_value: data_value.clone(),
_kind: PhantomData,
}
}
}
impl<T> PartialEq for DataValue<T> {
fn eq(&self, other: &Self) -> bool {
let Self {
data_value,
_kind: _,
} = self;
data_value.eq(&other.data_value)
}
}
impl<T> Eq for DataValue<T> {
// `ua::DataValue` implements `Eq`.
// TODO: Verify this at compile time.
}
impl<T> PartialOrd for DataValue<T> {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
}
}
impl<T> Ord for DataValue<T> {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
let Self {
data_value,
_kind: _,
} = self;
data_value.cmp(&other.data_value)
}
}
impl<T: DataTypeExt> DataValue<T> {
#[must_use]
pub(crate) const fn new(data_value: ua::DataValue) -> Self {
Self {
data_value,
_kind: PhantomData,
}
}
/// Gets value.
///
/// This returns `None` when the value is unset.
#[must_use]
pub fn value(&self) -> Option<&ua::Variant> {
self.data_value.value()
}
/// Extracts value.
///
/// This returns `None` when the value is unset.
#[must_use]
pub fn into_value(self) -> Option<ua::Variant> {
self.data_value.into_value()
}
/// Gets scalar value.
///
/// This returns `None` when the value is unset or not a scalar of the given type. The same can
/// be achieved in two steps with [`Self::value()`] and [`ua::Variant::as_scalar()`].
pub fn scalar_value(&self) -> Option<&T>
where
// `DataType` has transparent representation required for `as_scalar()`.
T: DataType,
{
self.value().and_then(ua::Variant::as_scalar::<T>)
}
/// Extracts scalar value.
///
/// This returns `None` when the value is unset or not a scalar of the given type. The same can
/// be achieved in two steps with [`Self::into_value()`] and [`ua::Variant::into_scalar()`].
pub fn into_scalar_value(self) -> Option<T> {
self.into_value()
.and_then(ua::Variant::into_scalar::<T::Inner>)
.map(T::from_inner)
}
#[must_use]
pub fn source_timestamp(&self) -> Option<&ua::DateTime> {
self.data_value.source_timestamp()
}
#[must_use]
pub fn server_timestamp(&self) -> Option<&ua::DateTime> {
self.data_value.server_timestamp()
}
#[must_use]
pub fn source_picoseconds(&self) -> Option<u16> {
self.data_value.source_picoseconds()
}
#[must_use]
pub fn server_picoseconds(&self) -> Option<u16> {
self.data_value.server_picoseconds()
}
#[must_use]
pub fn status(&self) -> Option<ua::StatusCode> {
self.data_value.status()
}
}
impl DataValue<ua::Variant> {
/// Casts to specific value type.
///
/// This adjusts the target type of `self`, casting the inner value to the specified data type
/// when read with [`Self::value()`]. This should be used in situations when the expected type
/// can be deduced from circumstances and typed data values can be returned for convenience.
pub(crate) fn cast<T: DataTypeExt>(self) -> DataValue<T> {
let Self { data_value, _kind } = self;
DataValue::new(data_value)
}
}