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 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307
use enumflags2::{bitflags, BitFlags};
use crate::{
dds::with_key::datawriter::WriteOptions,
structure::{guid::GUID, rpc::SampleIdentity, sequence_number::SequenceNumber, time::Timestamp},
};
// use std::num::Zero; // unstable
/// indicates whether or not the corresponding data sample has already
/// been read by this `DataReader`.
///
/// > For each sample received, the middleware internally maintains a
/// > sample_state relative to each DataReader. The sample_state can either be
/// > READ or NOT_READ.
///
/// > The sample_state will, in general, be different for each sample in the
/// > collection returned by [`read()`](crate::with_key::DataReader::read())
/// > or [`take()`](crate::with_key::DataReader::take()).
///
/// See DDS spec v1.4 Section 2.2.2.5.4 and Section "2.2.2.5.1.2 Interpretation
/// of the SampleInfo sample_state".
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[bitflags]
#[repr(u32)] // DDS Spec 1.4 section 2.3.3 DCPS PSM : IDL defines these as "unsigned long",
// so u32
pub enum SampleState {
/// > indicates that the DataReader has already accessed that sample by means
/// of `read()` ... or corresponding iterator.
Read = 0b0001,
/// > indicates that the DataReader has not accessed that sample before
NotRead = 0b0010,
}
impl SampleState {
/// Set that contains all possible states
pub fn any() -> BitFlags<Self> {
BitFlags::<Self>::all()
}
}
/// Indicates if this data *instance* has been seen (viewed).
///
/// > For each instance (identified by the [key](crate::Key)), the middleware
/// > internally maintains a view_state relative to each DataReader. The
/// > view_state can either be NEW or NOT_NEW.
///
/// > The view_state available in the SampleInfo is a snapshot of the view_state
/// > of the instance relative to the DataReader used to access the samples at
/// > the time the collection was obtained (i.e., at the time read or take was
/// > called). The view_state is therefore the same for all samples in the
/// > returned collection that refer to the same instance.
/// > Once an instance has been detected as not having any "live" writers and
/// > all the samples associated with the instance are ‘taken’ from the
/// > DataReader, the middleware can reclaim all local resources regarding the
/// > instance. Future samples will be treated as 'never seen'.
///
/// Cf. [`SampleState`]
///
/// See DDS spec v.14 Section 2.2.2.5.1.8 Interpretation of the SampleInfo
/// view_state
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[repr(u32)]
#[bitflags]
pub enum ViewState {
/// > indicates that either this is the first time that the DataReader has
/// > ever accessed samples of that instance, or else that the DataReader
/// > has accessed previous samples of the instance, but the instance has
/// > since been reborn (i.e., become not-alive and then alive again).
New = 0b0001,
/// > indicates that the DataReader has already accessed samples of the same
/// > instance and that the instance has not been reborn since
NotNew = 0b0010,
}
impl ViewState {
/// Set that contains all possible states
pub fn any() -> BitFlags<Self> {
BitFlags::<Self>::all()
}
}
/// Is this data instance alive or not and why.
///
/// > The instance_state available in the SampleInfo is a snapshot of the
/// > instance_state of the instance at the time the collection was obtained
/// > (i.e., at the time read or take was called). The instance_state is
/// > therefore be the same for all samples in the returned collection that
/// > refer to the same instance.
///
/// DDS spec v1.4 Section "2.2.2.5.1.3 Interpretation of the SampleInfo
/// instance_state"
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[repr(u32)]
#[bitflags]
pub enum InstanceState {
/// > indicates that (a) samples have been received for the instance, (b)
/// > there are live DataWriter entities writing the instance, and (c) the
/// > instance has not been explicitly disposed (or else more samples have
/// > been received after it was disposed).
Alive = 0b0001,
/// > indicates the instance was explicitly disposed by a DataWriter by means
/// > of the dispose operation.
NotAliveDisposed = 0b0010,
/// > indicates the instance has been declared as not-alive by the DataReader
/// > because it detected that there are no live DataWriter entities writing
/// > that instance
NotAliveNoWriters = 0b0100,
}
impl InstanceState {
/// Set that contains all possible states
pub fn any() -> BitFlags<Self> {
BitFlags::<Self>::all()
}
/// Set that contains both not_alive states.
pub fn not_alive() -> BitFlags<Self> {
Self::NotAliveDisposed | Self::NotAliveNoWriters
}
}
/// A double counter for counting how many times an instance as become Alive.
///
/// > For each instance the middleware internally maintains two counts: the
/// > disposed_generation_count and no_writers_generation_count, relative to
/// > each DataReader:
/// > * The disposed_generation_count and
/// > no_writers_generation_count are initialized to zero when the DataReader
/// > first detects the presence of a never-seen-before instance.
/// > * The disposed_generation_count is incremented each time the
/// > instance_state of the corresponding instance changes
/// > from NOT_ALIVE_DISPOSED to ALIVE.
/// > * The no_writers_generation_count is incremented each time the
/// > instance_state of the corresponding instance changes
/// > from NOT_ALIVE_NO_WRITERS to ALIVE.
/// > The disposed_generation_count and no_writers_generation_count available in
/// > the SampleInfo capture a snapshot of the corresponding counters at the
/// > time the sample was received.
///
/// See DDS spec v1.4 Section "2.2.2.5.1.5 Interpretation of the SampleInfo
/// disposed_generation_count and no_writers_generation_count"
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct NotAliveGenerationCounts {
pub disposed_generation_count: i32,
pub no_writers_generation_count: i32,
}
impl NotAliveGenerationCounts {
/// Initial count value
pub fn zero() -> Self {
Self {
disposed_generation_count: 0,
no_writers_generation_count: 0,
}
}
/// Marker value for "never accessed"
pub fn sub_zero() -> Self {
Self {
disposed_generation_count: -1,
no_writers_generation_count: -1,
}
}
pub fn total(&self) -> i32 {
self.disposed_generation_count + self.no_writers_generation_count
}
}
/// SampleInfo is metadata attached to each received data sample.
/// It exists only at the receiving end of DDS, and is (mostly) generated by
/// DDS.
///
/// Some of the SampleInfo field description texts are quoted from the DDS
/// Specification.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct SampleInfo {
/// sample_state indicates whether or not the corresponding data sample has
/// already been read through this DataReader.
pub(crate) sample_state: SampleState,
/// Indicates that either this is the first time that the DataReader has ever
/// accessed samples of that instance, or else that the DataReader has
/// accessed previous samples of the instance, but the instance has since
/// been reborn (i.e., become not-alive and then alive again).
pub(crate) view_state: ViewState,
/// Indicates whether this instance is alive or not.
/// The instance can be not alive either because some writer has actively
/// disposed it, or there are no writers alive.
pub(crate) instance_state: InstanceState,
/// For each instance the middleware internally maintains these counts
/// relative to each DataReader. The counts capture snapshots of the
/// corresponding counters at the time the sample was received.
pub(crate) generation_counts: NotAliveGenerationCounts,
/// The ranks are are computed based solely on the actual samples in the
/// ordered collection returned by the read or take.
/// The sample_rank indicates the number of samples of the same instance that
/// follow the current one in the collection.
pub(crate) sample_rank: i32,
/// The generation_rank indicates the difference in generations between the
/// samples S and the Most Recent Sample of the same instance that appears In
/// the returned Collection (MRSIC). It counts the number of times the
/// instance transitioned from not-alive to alive in the time from the
/// reception of the S to the reception of MRSIC. The generation rank is
/// computed with: generation_rank =
/// (MRSIC.disposed_generation_count + MRSIC.no_writers_generation_count)
/// -- (S.disposed_generation_count + S.no_writers_generation_count)
pub(crate) generation_rank: i32,
/// The absolute_generation_rank indicates the difference in "generations"
/// between sample S and the Most Recent Sample of the instance that the
/// middleware has received (MRS). It counts the number of times the instance
/// transitioned from not-alive to alive in the time from the reception of the
/// S to the time when the read or take was called. absolute_generation_rank =
/// (MRS.disposed_generation_count + MRS.no_writers_generation_count)
/// -- (S.disposed_generation_count + S.no_writers_generation_count)
pub(crate) absolute_generation_rank: i32,
pub(crate) write_options: WriteOptions,
/// publication_handle identifies the DataWriter that modified
/// the instance (i.e. wrote this sample)
pub(crate) publication_handle: GUID,
pub(crate) sequence_number: SequenceNumber,
}
impl SampleInfo {
/// Source timestamp is the timestamp that was supplied by the DataWriter
/// that sent this sample. It is optional to timestamp samples when writing.
pub fn source_timestamp(&self) -> Option<Timestamp> {
self.write_options.source_timestamp()
}
pub fn sample_state(&self) -> SampleState {
self.sample_state
}
// pub fn set_sample_state(&mut self, sample_state: SampleState) {
// self.sample_state = sample_state
// }
pub fn view_state(&self) -> ViewState {
self.view_state
}
// pub fn set_view_state(&mut self, view_state: ViewState) {
// self.view_state = view_state;
// }
pub fn instance_state(&self) -> InstanceState {
self.instance_state
}
// pub fn set_instance_state(&mut self, instance_state: InstanceState) {
// self.instance_state = instance_state;
// }
pub fn disposed_generation_count(&self) -> i32 {
self.generation_counts.disposed_generation_count
}
pub fn no_writers_generation_count(&self) -> i32 {
self.generation_counts.no_writers_generation_count
}
pub fn sample_rank(&self) -> i32 {
self.sample_rank
}
pub fn generation_rank(&self) -> i32 {
self.generation_rank
}
pub fn absolute_generation_rank(&self) -> i32 {
self.absolute_generation_rank
}
/// publication_handle identifies the DataWriter that modified
/// the instance (i.e. wrote this sample)
pub fn publication_handle(&self) -> GUID {
self.publication_handle
}
pub fn writer_guid(&self) -> GUID {
self.publication_handle
}
pub fn related_sample_identity(&self) -> Option<SampleIdentity> {
self.write_options.related_sample_identity()
}
pub fn sample_identity(&self) -> SampleIdentity {
SampleIdentity {
writer_guid: self.publication_handle,
sequence_number: self.sequence_number,
}
}
// pub fn set_publication_handle(&mut self, publication_handle: GUID) {
// self.publication_handle = publication_handle
// }
}