Skip to main content

zerodds_dcps/
sample.rs

1// SPDX-License-Identifier: Apache-2.0
2// Copyright 2026 ZeroDDS Contributors
3//! `Sample<T>` — Daten + [`SampleInfo`] zusammen.
4//!
5//! Spec-Referenz: OMG DDS-DCPS 1.4 §2.2.2.5.3 `read`/`take`. Die Spec
6//! arbeitet mit zwei parallelen Sequenzen `data_values` und
7//! `sample_infos`; in unserer Rust-API buendeln wir sie zu einem
8//! `Sample<T> { data, info }`.
9//!
10//! ## valid_data
11//!
12//! Wenn `info.valid_data == false`, traegt das Sample reine
13//! Lifecycle-Information (Dispose-/Unregister-Marker). `data` enthaelt
14//! in diesem Fall einen Default-konstruierten `T` mit nur den Key-
15//! Feldern befuellt (Spec §2.2.2.5.1.13).
16
17extern crate alloc;
18
19use crate::sample_info::SampleInfo;
20
21/// Einzelner Sample-Datensatz aus `read`/`take`.
22#[derive(Debug, Clone, PartialEq, Eq)]
23pub struct Sample<T> {
24    /// Application-Daten. Bei `info.valid_data == false` ist nur der
25    /// Key-Anteil bedeutungsvoll.
26    pub data: T,
27    /// Metadaten (Spec §2.2.2.5.1).
28    pub info: SampleInfo,
29}
30
31impl<T> Sample<T> {
32    /// Konstruktor.
33    #[must_use]
34    pub fn new(data: T, info: SampleInfo) -> Self {
35        Self { data, info }
36    }
37
38    /// `true` wenn das Sample Nutzdaten enthaelt (nicht nur einen
39    /// Lifecycle-Marker).
40    #[must_use]
41    pub fn is_valid(&self) -> bool {
42        self.info.valid_data
43    }
44
45    /// Komfort-Akzessor: Lifecycle-Sicht ohne Daten.
46    #[must_use]
47    pub fn info(&self) -> &SampleInfo {
48        &self.info
49    }
50}
51
52#[cfg(test)]
53#[allow(clippy::expect_used, clippy::unwrap_used)]
54mod tests {
55    use super::*;
56    use crate::instance_handle::InstanceHandle;
57    use crate::sample_info::{InstanceStateKind, SampleStateKind, ViewStateKind};
58    use crate::time::Time;
59
60    #[test]
61    fn sample_new_holds_data_and_info() {
62        let info = SampleInfo::new_alive(
63            InstanceHandle::from_raw(1),
64            InstanceHandle::from_raw(2),
65            Time::new(10, 0),
66        );
67        let s = Sample::new(42u32, info);
68        assert_eq!(s.data, 42);
69        assert_eq!(s.info().instance_handle, InstanceHandle::from_raw(1));
70        assert!(s.is_valid());
71    }
72
73    #[test]
74    fn sample_with_invalid_data_marker() {
75        let info = SampleInfo {
76            valid_data: false,
77            instance_state: InstanceStateKind::NotAliveDisposed,
78            ..SampleInfo::default()
79        };
80        let s = Sample::new(0u32, info);
81        assert!(!s.is_valid());
82        assert_eq!(s.info.instance_state, InstanceStateKind::NotAliveDisposed);
83    }
84
85    #[test]
86    fn sample_states_in_info_default() {
87        let s = Sample::new((), SampleInfo::default());
88        assert_eq!(s.info.sample_state, SampleStateKind::NotRead);
89        assert_eq!(s.info.view_state, ViewStateKind::New);
90    }
91}