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
use enumflags2::{bitflags, BitFlags};
use serde::{Deserialize, Serialize};
#[cfg(test)]
use byteorder::ByteOrder;
use super::cache_change::ChangeKind;
use crate::{
dds::traits::serde_adapters::no_key::*,
messages::submessages::submessage_elements::RepresentationIdentifier,
serialization::CDRDeserializerAdapter,
};
#[cfg(test)]
use crate::serialization::cdr_serializer::to_bytes;
#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
#[repr(u8)]
#[bitflags]
pub enum StatusInfoEnum {
Disposed = 0b0001,
Unregistered = 0b0010,
Filtered = 0b0100,
}
/// [`StatusInfo`] is a 4 octet array
/// RTPS spec v2.3, Section 9.6.3.9 StatusInfo_t
#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
pub struct StatusInfo {
em: [u8; 3],
si: BitFlags<StatusInfoEnum>, /* This is now a bit set of StatusInfoEnum
* Interpretation:
* empty set => Sample is ALIVE and must be present in the
* message not Unregistered and
* not Disposed => ALIVE (but may be asbent)
* Disposed => DataWriter disposed instance. NOT_ALIVE
* Unregistered => DataWriter unregistered message. Note that
* DataWriter is not required
* notify about any unregister operations. This does not make
* the instance NOT_ALIVE, but infoms
* that the DataWriter is not going to update that instance
* anymore. Filtered =>
* DataWriter wrote a sample, but it was filtered away by the
* current QoS settings and thus
* data is not present.
*
* There may be several flags set at the same time.
*
* Disposed & Unregistered:
*
* Meanings of some combinations are uknown:
* Disposed & Filtered : ???
* Unregistered & Filtered: ???
* Disposed & Unregistered & Filtered: ??? */
}
impl StatusInfo {
pub fn empty() -> Self {
Self {
em: [0; 3],
si: BitFlags::empty(),
}
}
pub fn contains(&self, sie: StatusInfoEnum) -> bool {
self.si.contains(sie)
}
pub fn change_kind(&self) -> ChangeKind {
if self.contains(StatusInfoEnum::Disposed) {
// DISPOSED is strongest
ChangeKind::NotAliveDisposed
} else if self.contains(StatusInfoEnum::Unregistered) {
// Checking unregistered second
ChangeKind::NotAliveUnregistered
} else {
// Even if filtered is set it is still alive
ChangeKind::Alive
}
}
#[cfg(test)]
pub fn into_cdr_bytes<BO: ByteOrder>(
self,
) -> Result<Vec<u8>, crate::serialization::error::Error> {
to_bytes::<Self, BO>(&self)
}
pub fn from_cdr_bytes(
bytes: &[u8],
representation_id: RepresentationIdentifier,
) -> Result<Self, crate::serialization::error::Error> {
CDRDeserializerAdapter::from_bytes(bytes, representation_id)
}
}
#[cfg(test)]
mod tests {
use byteorder::{BigEndian, LittleEndian};
use super::*;
#[test]
fn inline_qos_status_info() {
// Little endian
let si_bytes = StatusInfo {
em: [0; 3],
si: StatusInfoEnum::Disposed | StatusInfoEnum::Unregistered,
}
.into_cdr_bytes::<LittleEndian>()
.unwrap();
let bytes: Vec<u8> = vec![0x00, 0x00, 0x00, 0x03];
assert_eq!(si_bytes, bytes);
let status_info = StatusInfo::from_cdr_bytes(&bytes, RepresentationIdentifier::CDR_LE).unwrap();
assert_eq!(
status_info,
StatusInfo {
em: [0; 3],
si: StatusInfoEnum::Disposed | StatusInfoEnum::Unregistered
}
);
// Big endian
let si_bytes = StatusInfo {
em: [0; 3],
si: StatusInfoEnum::Disposed | StatusInfoEnum::Unregistered,
}
.into_cdr_bytes::<BigEndian>()
.unwrap();
let bytes: Vec<u8> = vec![0x00, 0x00, 0x00, 0x03];
assert_eq!(si_bytes, bytes);
let status_info = StatusInfo::from_cdr_bytes(&bytes, RepresentationIdentifier::CDR_BE).unwrap();
assert_eq!(
status_info,
StatusInfo {
em: [0; 3],
si: StatusInfoEnum::Disposed | StatusInfoEnum::Unregistered
}
);
}
}