Skip to main content

Data

Struct Data 

Source
pub struct Data {
    pub reader_id: EntityId,
    pub writer_id: EntityId,
    pub writer_sn: SequenceNumber,
}
Expand description

DATA submessage

Carries user data from writer to reader.

Fields§

§reader_id: EntityId

Reader entity ID

§writer_id: EntityId

Writer entity ID

§writer_sn: SequenceNumber

Sequence number

Implementations§

Source§

impl Data

Source

pub const MIN_SIZE: usize = 24

Minimum size (without payload) Layout: 4 (submsg header) + 2 (extraFlags) + 2 (octetsToInlineQos) + 4 (readerId) + 4 (writerId) + 8 (seqNum) = 24

Source

pub const fn new( reader_id: EntityId, writer_id: EntityId, writer_sn: SequenceNumber, ) -> Self

Create a new DATA submessage

Examples found in repository?
examples/test_encoding.rs (lines 52-56)
12fn main() {
13    println!("=== HDDS Micro Encoding Test ===\n");
14
15    // Create a null transport (captures sent data)
16    let transport = NullTransport::default();
17
18    // Create participant
19    let mut participant = MicroParticipant::new(0, transport).unwrap();
20    let guid_prefix = participant.guid_prefix();
21    let entity_id = participant.allocate_entity_id(true);
22
23    println!("GUID Prefix: {:02X?}", guid_prefix.as_bytes());
24    println!("Entity ID: {:02X?}", entity_id.as_bytes());
25
26    // Create writer (for demonstration, not used in this encoding test)
27    let dest = Locator::udpv4([239, 255, 0, 1], 7400);
28    let _writer = MicroWriter::new(guid_prefix, entity_id, "test/topic", dest).unwrap();
29
30    // Encode temperature-like payload: sensor_id(4) + value(4) + timestamp(8)
31    let mut buf = [0u8; 32];
32    let mut encoder = CdrEncoder::new(&mut buf);
33    encoder.encode_u32(0x42).unwrap(); // sensor_id
34    encoder.encode_f32(25.5).unwrap(); // temperature
35    encoder.encode_u64(12345678).unwrap(); // timestamp
36    let payload = encoder.finish();
37
38    println!("Payload ({} bytes): {:02X?}", payload.len(), payload);
39
40    // Build the packet manually to inspect bytes
41    let mut packet = [0u8; 256];
42
43    // RTPS Header (20 bytes)
44    let header = hdds_micro::rtps::RtpsHeader::new(
45        hdds_micro::rtps::ProtocolVersion::RTPS_2_5,
46        hdds_micro::rtps::VendorId::HDDS,
47        guid_prefix,
48    );
49    let header_len = header.encode(&mut packet).unwrap();
50
51    // DATA submessage
52    let data = hdds_micro::rtps::submessages::Data::new(
53        EntityId::UNKNOWN,
54        entity_id,
55        hdds_micro::rtps::SequenceNumber::new(1),
56    );
57    let data_len = data.encode_header(&mut packet[header_len..]).unwrap();
58
59    // Copy payload
60    let payload_offset = header_len + data_len;
61    packet[payload_offset..payload_offset + payload.len()].copy_from_slice(payload);
62
63    let total_len = payload_offset + payload.len();
64
65    // Update octets_to_next
66    let octets_to_next = (20 + payload.len()) as u16;
67    packet[header_len + 2] = (octets_to_next & 0xff) as u8;
68    packet[header_len + 3] = ((octets_to_next >> 8) & 0xff) as u8;
69
70    println!("\n=== Complete RTPS Packet ({} bytes) ===", total_len);
71
72    // Print in rows of 16
73    for i in (0..total_len).step_by(16) {
74        print!("{:04X}  ", i);
75        for &byte in &packet[i..std::cmp::min(i + 16, total_len)] {
76            print!("{:02X} ", byte);
77        }
78        println!();
79    }
80
81    println!("\n=== Key Bytes Analysis ===");
82    println!(
83        "Bytes 0-3 (RTPS magic): {:02X} {:02X} {:02X} {:02X} = '{}'",
84        packet[0],
85        packet[1],
86        packet[2],
87        packet[3],
88        std::str::from_utf8(&packet[0..4]).unwrap_or("???")
89    );
90    println!("Bytes 4-5 (version): {:02X} {:02X}", packet[4], packet[5]);
91    println!("Bytes 6-7 (vendor): {:02X} {:02X}", packet[6], packet[7]);
92    println!("Bytes 8-19 (GUID prefix): {:02X?}", &packet[8..20]);
93    println!(
94        "Byte 20 (submsg kind): {:02X} (expected: 0x15 for DATA)",
95        packet[20]
96    );
97    println!(
98        "Byte 21 (submsg flags): {:02X} (expected: 0x05)",
99        packet[21]
100    );
101    println!(
102        "Bytes 22-23 (octetsToNext): {:02X} {:02X} = {} bytes",
103        packet[22],
104        packet[23],
105        u16::from_le_bytes([packet[22], packet[23]])
106    );
107
108    // Verify
109    if packet[20] == 0x15 {
110        println!("\n✓ Submessage kind is correct (0x15)");
111    } else {
112        println!(
113            "\n✗ ERROR: Submessage kind is wrong: 0x{:02X} instead of 0x15",
114            packet[20]
115        );
116    }
117}
Source

pub fn encode_header(&self, buf: &mut [u8]) -> Result<usize>

Encode DATA submessage (header + fixed fields, no payload)

Encodes per RTPS 2.3 Sec.8.3.7.2:

  • Submessage header: id=0x15, flags=0x05 (LE + data present), octetsToNext
  • extraFlags (2 bytes)
  • octetsToInlineQos = 16 (skip to payload after readerId+writerId+seqNum)
  • readerEntityId (4 bytes)
  • writerEntityId (4 bytes)
  • writerSN (8 bytes as high:i32 + low:u32)

Payload should be appended separately by caller.

Examples found in repository?
examples/test_encoding.rs (line 57)
12fn main() {
13    println!("=== HDDS Micro Encoding Test ===\n");
14
15    // Create a null transport (captures sent data)
16    let transport = NullTransport::default();
17
18    // Create participant
19    let mut participant = MicroParticipant::new(0, transport).unwrap();
20    let guid_prefix = participant.guid_prefix();
21    let entity_id = participant.allocate_entity_id(true);
22
23    println!("GUID Prefix: {:02X?}", guid_prefix.as_bytes());
24    println!("Entity ID: {:02X?}", entity_id.as_bytes());
25
26    // Create writer (for demonstration, not used in this encoding test)
27    let dest = Locator::udpv4([239, 255, 0, 1], 7400);
28    let _writer = MicroWriter::new(guid_prefix, entity_id, "test/topic", dest).unwrap();
29
30    // Encode temperature-like payload: sensor_id(4) + value(4) + timestamp(8)
31    let mut buf = [0u8; 32];
32    let mut encoder = CdrEncoder::new(&mut buf);
33    encoder.encode_u32(0x42).unwrap(); // sensor_id
34    encoder.encode_f32(25.5).unwrap(); // temperature
35    encoder.encode_u64(12345678).unwrap(); // timestamp
36    let payload = encoder.finish();
37
38    println!("Payload ({} bytes): {:02X?}", payload.len(), payload);
39
40    // Build the packet manually to inspect bytes
41    let mut packet = [0u8; 256];
42
43    // RTPS Header (20 bytes)
44    let header = hdds_micro::rtps::RtpsHeader::new(
45        hdds_micro::rtps::ProtocolVersion::RTPS_2_5,
46        hdds_micro::rtps::VendorId::HDDS,
47        guid_prefix,
48    );
49    let header_len = header.encode(&mut packet).unwrap();
50
51    // DATA submessage
52    let data = hdds_micro::rtps::submessages::Data::new(
53        EntityId::UNKNOWN,
54        entity_id,
55        hdds_micro::rtps::SequenceNumber::new(1),
56    );
57    let data_len = data.encode_header(&mut packet[header_len..]).unwrap();
58
59    // Copy payload
60    let payload_offset = header_len + data_len;
61    packet[payload_offset..payload_offset + payload.len()].copy_from_slice(payload);
62
63    let total_len = payload_offset + payload.len();
64
65    // Update octets_to_next
66    let octets_to_next = (20 + payload.len()) as u16;
67    packet[header_len + 2] = (octets_to_next & 0xff) as u8;
68    packet[header_len + 3] = ((octets_to_next >> 8) & 0xff) as u8;
69
70    println!("\n=== Complete RTPS Packet ({} bytes) ===", total_len);
71
72    // Print in rows of 16
73    for i in (0..total_len).step_by(16) {
74        print!("{:04X}  ", i);
75        for &byte in &packet[i..std::cmp::min(i + 16, total_len)] {
76            print!("{:02X} ", byte);
77        }
78        println!();
79    }
80
81    println!("\n=== Key Bytes Analysis ===");
82    println!(
83        "Bytes 0-3 (RTPS magic): {:02X} {:02X} {:02X} {:02X} = '{}'",
84        packet[0],
85        packet[1],
86        packet[2],
87        packet[3],
88        std::str::from_utf8(&packet[0..4]).unwrap_or("???")
89    );
90    println!("Bytes 4-5 (version): {:02X} {:02X}", packet[4], packet[5]);
91    println!("Bytes 6-7 (vendor): {:02X} {:02X}", packet[6], packet[7]);
92    println!("Bytes 8-19 (GUID prefix): {:02X?}", &packet[8..20]);
93    println!(
94        "Byte 20 (submsg kind): {:02X} (expected: 0x15 for DATA)",
95        packet[20]
96    );
97    println!(
98        "Byte 21 (submsg flags): {:02X} (expected: 0x05)",
99        packet[21]
100    );
101    println!(
102        "Bytes 22-23 (octetsToNext): {:02X} {:02X} = {} bytes",
103        packet[22],
104        packet[23],
105        u16::from_le_bytes([packet[22], packet[23]])
106    );
107
108    // Verify
109    if packet[20] == 0x15 {
110        println!("\n✓ Submessage kind is correct (0x15)");
111    } else {
112        println!(
113            "\n✗ ERROR: Submessage kind is wrong: 0x{:02X} instead of 0x15",
114            packet[20]
115        );
116    }
117}
Source

pub fn decode(buf: &[u8]) -> Result<(Self, usize)>

Decode DATA submessage (header + fixed fields)

Decodes per RTPS 2.3 Sec.8.3.7.2. Uses octetsToInlineQos to find payload.

Returns (Data, payload_offset)

Trait Implementations§

Source§

impl Clone for Data

Source§

fn clone(&self) -> Data

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for Data

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl PartialEq for Data

Source§

fn eq(&self, other: &Data) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl Copy for Data

Source§

impl Eq for Data

Source§

impl StructuralPartialEq for Data

Auto Trait Implementations§

§

impl Freeze for Data

§

impl RefUnwindSafe for Data

§

impl Send for Data

§

impl Sync for Data

§

impl Unpin for Data

§

impl UnsafeUnpin for Data

§

impl UnwindSafe for Data

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.