Skip to main content

MicroWriter

Struct MicroWriter 

Source
pub struct MicroWriter { /* private fields */ }
Expand description

MicroWriter - DDS DataWriter

Publishes data samples to a topic.

§Design

  • BEST_EFFORT QoS (no retransmissions)
  • No history cache (fire-and-forget)
  • Fixed-size packets

§Example

let writer = MicroWriter::new(
    participant.guid_prefix(),
    writer_entity_id,
    "Temperature",
    dest_locator,
);

// Encode sample
let mut buf = [0u8; 256];
let mut encoder = CdrEncoder::new(&mut buf);
encoder.encode_f32(23.5)?;
encoder.encode_i64(123456)?;
let payload = encoder.finish();

// Write sample
writer.write(payload, participant.transport_mut())?;

Implementations§

Source§

impl MicroWriter

Source

pub fn new( guid_prefix: GuidPrefix, entity_id: EntityId, topic_name: &str, dest_locator: Locator, ) -> Result<Self>

Create a new writer

§Arguments
  • guid_prefix - Participant’s GUID prefix
  • entity_id - Writer’s entity ID
  • topic_name - Topic name (max 63 chars)
  • dest_locator - Destination locator (multicast or unicast)
Examples found in repository?
examples/test_encoding.rs (line 28)
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 const fn guid(&self) -> GUID

Get writer GUID

Source

pub fn topic_name(&self) -> &str

Get topic name

Source

pub const fn sequence_number(&self) -> SequenceNumber

Get current sequence number

Source

pub fn write<T: Transport>( &mut self, payload: &[u8], transport: &mut T, ) -> Result<()>

Write a sample

§Arguments
  • payload - CDR-encoded payload
  • transport - Transport to send through

Trait Implementations§

Source§

impl Debug for MicroWriter

Source§

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

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

impl PartialEq for MicroWriter

Source§

fn eq(&self, other: &MicroWriter) -> 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 StructuralPartialEq for MicroWriter

Auto Trait Implementations§

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> 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.