From 99db3bc8ee31f84d0962670a23da0919f77ee14e Mon Sep 17 00:00:00 2001 From: Alex Campos Date: Mon, 12 Jan 2026 12:15:05 -0800 Subject: [PATCH 1/7] docs: align Rust guide structure with JS --- docs/connector.md | 33 +++++++++- docs/guide/advanced.md | 33 ++++++++++ docs/guide/configuration.md | 120 ++++++++++++++++++++++++++++++++++ docs/guide/connector.md | 71 ++++++++++++++++++++ docs/guide/data.md | 97 +++++++++++++++++++++++++++ docs/guide/errors.md | 50 ++++++++++++++ docs/guide/getting_started.md | 60 +++++++++++++++++ docs/guide/index.md | 17 +++++ docs/guide/input.md | 89 +++++++++++++++++++++++++ docs/guide/output.md | 113 ++++++++++++++++++++++++++++++++ docs/guide/threading.md | 23 +++++++ docs/input.md | 45 +++++++++++-- docs/lib.md | 84 +++++++----------------- docs/output.md | 36 ++++++++-- docs/result.md | 26 +++++--- src/guide/mod.rs | 66 +++++++++++++++++++ src/lib.rs | 1 + 17 files changed, 883 insertions(+), 81 deletions(-) create mode 100644 docs/guide/advanced.md create mode 100644 docs/guide/configuration.md create mode 100644 docs/guide/connector.md create mode 100644 docs/guide/data.md create mode 100644 docs/guide/errors.md create mode 100644 docs/guide/getting_started.md create mode 100644 docs/guide/index.md create mode 100644 docs/guide/input.md create mode 100644 docs/guide/output.md create mode 100644 docs/guide/threading.md create mode 100644 src/guide/mod.rs diff --git a/docs/connector.md b/docs/connector.md index 04c4006..57b328f 100644 --- a/docs/connector.md +++ b/docs/connector.md @@ -1,4 +1,33 @@ # Connector and related utilities -This module contains everything related to the [`Connector`] abstraction, -including methods to create [`Input`] and [`Output`] objects. +The [`Connector`] type is the entry point to the RTI Connector for Rust API. +It wraps a DDS `DomainParticipant` configured from an XML file and is used +to acquire [`Input`] and [`Output`] handles for reading and writing data. + +## Typical flow + +1. Create a `Connector` with [`Connector::new`], passing a participant name and + the path to an XML configuration file. +2. Acquire an [`Input`] or [`Output`] with [`Connector::get_input`] and + [`Connector::get_output`]. +3. Use the `Input`/`Output` APIs to read or write samples. + +```text +let connector = Connector::new("MyLibrary::MyParticipant", "/path/to/App.xml")?; +let input = connector.get_input("MySubscriber::MyReader")?; +let output = connector.get_output("MyPublisher::MyWriter")?; +``` + +## Ownership and blocking acquisition + +`Connector` enforces thread-aware ownership for `Input` and `Output` instances. +If a named entity is already in use, [`Connector::get_input`] and +[`Connector::get_output`] will return an error. Use [`Connector::take_input`] +or [`Connector::take_output`] to wait until the entity becomes available. + +## Waiting for data + +You can wait for any `Input` owned by the connector to receive data using +[`Connector::wait_for_data`] or [`Connector::wait_for_data_with_timeout`]. +These calls do not read data; you still need to call [`Input::read`] or +[`Input::take`] on the specific `Input` you want to process. diff --git a/docs/guide/advanced.md b/docs/guide/advanced.md new file mode 100644 index 0000000..1120bc9 --- /dev/null +++ b/docs/guide/advanced.md @@ -0,0 +1,33 @@ +# Advanced operations + +This section collects less common operations that are still useful in +production applications. + +## Write parameters + +[`crate::Output::write_with_params`] accepts a [`crate::WriteParams`] struct +that can change the write action (`write`, `dispose`, `unregister`) and attach +identity or timestamp metadata. + +The available constructors are: + +* [`crate::WriteParams::write`] +* [`crate::WriteParams::dispose`] +* [`crate::WriteParams::unregister`] + +## Waiting and matching + +* [`crate::Connector::wait_for_data`]: wait for any input to have data. +* [`crate::Input::wait_for_publications`]: wait for matched writers. +* [`crate::Output::wait_for_subscriptions`]: wait for matched readers. +* [`crate::Output::wait`]: wait for acknowledgments. + +Both `Input` and `Output` provide JSON helpers to inspect matches: + +* [`crate::Input::display_matched_publications`] +* [`crate::Output::display_matched_subscriptions`] + +## Loan management + +If you call [`crate::Input::take`], you can return the loan with +[`crate::Input::return_loan`] after processing to release native resources. diff --git a/docs/guide/configuration.md b/docs/guide/configuration.md new file mode 100644 index 0000000..63258cc --- /dev/null +++ b/docs/guide/configuration.md @@ -0,0 +1,120 @@ +# Configuration + +RTI Connector for Rust uses an XML configuration file to define participants, +readers, writers, topics, types, and QoS. The XML schema is the same one used +by RTI Connext DDS XML-Based Application Creation. + +For background on the XML format, see: + +* + +## Loading a configuration + +Create a connector by passing a participant name and the XML file path: + +```rust +use rtiddsconnector::Connector; + +fn load_config() -> rtiddsconnector::ConnectorFallible { + let _connector = Connector::new("MyLibrary::MyParticipant", "App.xml")?; + Ok(()) +} +``` + +The `config_name` must match a `` element in the XML. + +## XML tags and Connector API + +The table below summarizes the most common XML tags and how they map to the +Connector API: + +| XML Tag | DDS Concept | Connector API | +| --- | --- | --- | +| `` | Data types | Types used by `Input` and `Output` | +| ``, ``, ``, `` | Domain, Topic | Defines the domain and topics used by `Connector` | +| ``, `` | DomainParticipant | Loaded by `Connector::new` | +| ``, `` | Publisher, DataWriter | Each `` defines an `Output` | +| ``, `` | Subscriber, DataReader | Each `` defines an `Input` | +| ``, `` | QoS | QoS for `Connector`, `Output`, and `Input` | + +## Types + +Types are defined under `` and associated with topics. Example: + +```xml + + + + + + + + +``` + +You can define types in IDL and convert them to XML with `rtiddsgen`: + +``` +rtiddsgen -convertToXml MyTypes.idl +``` + +## Domain and topics + +Domains register types and define topics: + +```xml + + + + + + +``` + +## Participants, readers, and writers + +Participants contain publishers and subscribers, which contain writers/readers: + +```xml + + + + + + + + + + + + + +``` + +## QoS profiles + +QoS can be configured at the profile level or per-entity. Example profile: + +```xml + + + + + RELIABLE_RELIABILITY_QOS + + + + + RELIABLE_RELIABILITY_QOS + + + + +``` + +## Examples in this repo + +The repository includes XML examples you can adapt: + +* `examples/MyApplication.xml` +* `examples/shapes/Shapes.xml` diff --git a/docs/guide/connector.md b/docs/guide/connector.md new file mode 100644 index 0000000..1dc5c6e --- /dev/null +++ b/docs/guide/connector.md @@ -0,0 +1,71 @@ +# Connector lifecycle + +[`crate::Connector`] represents a DDS `DomainParticipant` configured from XML. +It owns native resources and creates `Input` and `Output` handles. + +## Importing the crate + +```rust +use rtiddsconnector::Connector; +``` + +## Creating a connector + +Create a connector with [`crate::Connector::new`], passing the namespaced +participant name and the XML file path: + +```rust +use rtiddsconnector::Connector; + +fn create_connector() -> rtiddsconnector::ConnectorFallible { + let _connector = Connector::new("MyLibrary::MyParticipant", "App.xml")?; + Ok(()) +} +``` + +The XML file defines your types, QoS profiles, and DDS entities. The call above +loads a `` from a ``, for example: + +```xml + + + ... + + +``` + +See a complete example in `examples/MyApplication.xml`. + +## Closing a connector + +There is no explicit `close()` method in Rust. Instead, `Connector`, `Input`, and +`Output` are released when they go out of scope. The crate uses RAII to free +native resources. + +If you want to force cleanup of Connext global resources at the end of a scope +(for example in tests), use [`crate::GlobalsDropGuard`]. + +## Getting inputs and outputs + +[`crate::Connector::get_input`] and [`crate::Connector::get_output`] return +owned handles to the named reader/writer. The crate enforces single-threaded +ownership: if an entity is already in use, these calls return an error. To wait +until the entity becomes available, use [`crate::Connector::take_input`] or +[`crate::Connector::take_output`]. + +See [Publishing data](crate::guide::output) and [Reading data](crate::guide::input) +for the workflow that follows. + +## Threading note + +Operations on the same `Connector` or its contained entities are not protected +for multi-threaded access. See [Threading and ownership](crate::guide::threading) +for guidance. + +## Auto-enable considerations + +Connext DDS controls entity enablement through XML QoS settings (for example, +`/`). If readers are enabled before +you acquire an `Input`, data may already be available when you call +`get_input`. This behavior comes from Connext configuration rather than the +Rust API itself. diff --git a/docs/guide/data.md b/docs/guide/data.md new file mode 100644 index 0000000..4427e5f --- /dev/null +++ b/docs/guide/data.md @@ -0,0 +1,97 @@ +# Data access and Serde + +RTI Connector exposes data as JSON under the hood, while also providing typed +accessors for common primitive fields. + +## Complex types and XML definitions + +The types you read and write can include nested structs, sequences, arrays, and +unions. These types are defined in XML following RTI's XML-Based Application +Creation format. See +[RTI XML-Based Application Creation](https://community.rti.com/static/documentation/connext-dds/current/doc/manuals/connext_dds_professional/xml_application_creation/xml_based_app_creation_guide/UnderstandingXMLBased/XMLTagsConfigEntities.htm). + +## JSON vs member access + +You can access data member-by-member or as JSON. JSON access is convenient when +working with large structures; member access is convenient when you only need a +few fields. + +* Set with JSON: [`crate::Instance::set_as_json`] +* Get JSON: [`crate::Sample::get_value_json`] +* Member access: [`crate::Instance::set_number`], [`crate::Instance::set_string`], + [`crate::Sample::get_number`], [`crate::Sample::get_string`] + +## Accessing basic members + +Use typed setters/getters for numbers, booleans, and strings: + +```rust +use rtiddsconnector::{Instance, Sample}; + +fn set_basic(instance: &mut Instance) -> rtiddsconnector::ConnectorFallible { + instance.set_number("my_long", 2.0)?; + instance.set_boolean("my_boolean", true)?; + instance.set_string("my_string", "Hello, World!")?; + Ok(()) +} + +fn get_basic(sample: &Sample) -> rtiddsconnector::ConnectorFallible { + let _n = sample.get_number("my_long")?; + let _b = sample.get_boolean("my_boolean")?; + let _s = sample.get_string("my_string")?; + Ok(()) +} +``` + +## Accessing complex members + +Examples of field-name syntax for nested members, arrays, sequences, and unions +are available in the Connector JavaScript API documentation: + +[Accessing the data (field-name syntax examples)](https://community.rti.com/static/documentation/connector/current/api/javascript/data.html#.) + +## Type-independent access with SelectedValue + +For dynamic access, use [`crate::Instance::set_value`] and +[`crate::Sample::get_value`], which operate on [`crate::SelectedValue`]: + +```rust +use rtiddsconnector::{Instance, Sample, SelectedValue}; + +fn set_dynamic(instance: &mut Instance) -> rtiddsconnector::ConnectorFallible { + instance.set_value("my_double", SelectedValue::Number(2.14))?; + instance.set_value("my_boolean", SelectedValue::Boolean(true))?; + instance.set_value("my_string", SelectedValue::String("Hello".to_string()))?; + Ok(()) +} + +fn get_dynamic(sample: &Sample) -> rtiddsconnector::ConnectorFallible { + let _value = sample.get_value("my_double")?; + Ok(()) +} +``` + +## Performance guidance + +Typed getters and setters are generally faster than dynamic access with +`SelectedValue`. If you intend to access most or all members of a sample, +using JSON (`set_as_json`/`get_value_json`) can be more convenient and efficient +than setting or getting fields one by one. + +## 64-bit integer limitations + +RTI Connector uses a single number representation internally. This means that +64-bit integers may lose precision when converted to the internal numeric type. +If you need exact 64-bit integer values, consider representing them as strings +in your data model and converting explicitly in your application. + +## Typed serialization + +If you want to work with Rust structs, use Serde: + +* [`crate::Instance::serialize`]: serialize a struct and set it into the + instance. +* [`crate::Sample::deserialize`]: deserialize a sample into a struct. + +These methods allow you to keep strongly typed models in your application while +still using the dynamic RTI Connector API. diff --git a/docs/guide/errors.md b/docs/guide/errors.md new file mode 100644 index 0000000..8078805 --- /dev/null +++ b/docs/guide/errors.md @@ -0,0 +1,50 @@ +# Error handling + +Most operations return [`crate::ConnectorResult`] or +[`crate::ConnectorFallible`]. When an operation fails, you receive a +[`crate::ConnectorError`]. + +## Common patterns + +```rust +use rtiddsconnector::{Connector, ConnectorError}; + +fn try_connect() -> Result<(), ConnectorError> { + let _connector = Connector::new("MyLibrary::MyParticipant", "App.xml")?; + Ok(()) +} +``` + +Use helper methods to detect common cases: + +* [`crate::ConnectorError::is_timeout`] +* [`crate::ConnectorError::is_entity_not_found`] +* [`crate::ConnectorError::is_field_not_found`] +* [`crate::ConnectorError::is_native_error`] + +To inspect the last native error message, call +[`crate::ConnectorError::last_error_message`]. + +## Timeout example + +```rust +use rtiddsconnector::Input; + +fn wait_with_timeout(input: &Input) -> rtiddsconnector::ConnectorFallible { + match input.wait_with_timeout(std::time::Duration::from_secs(2)) { + Ok(()) => Ok(()), + Err(e) if e.is_timeout() => { + println!("Timed out waiting for data"); + Ok(()) + } + Err(e) => Err(e), + } +} +``` + +## Native error details + +If an operation fails because of a native RTI Connector error, the +`ConnectorError` will include the last error message from the native library. +This can provide additional context when debugging configuration or data access +issues. diff --git a/docs/guide/getting_started.md b/docs/guide/getting_started.md new file mode 100644 index 0000000..7aa3623 --- /dev/null +++ b/docs/guide/getting_started.md @@ -0,0 +1,60 @@ +# Getting started + +This crate is intended to be consumed from Cargo as a Git dependency. The +examples in `snippets/` and `examples/` are also included in the repository. + +## Add the dependency + +```console +cargo add --git https://github.com/rticommunity/rticonnextdds-connector-rs +``` + +If you need a specific branch, add `--branch `. + +## Ensure native libraries are available + +At build time, `build.rs` locates the RTI Connector C libraries in this order: + +1. `RTI_CONNECTOR_VERSION`: downloads the target-specific libraries from the + RTI Connector GitHub releases. +2. `RTI_CONNECTOR_DIR`: uses a local directory containing the libraries. +3. `CARGO_MANIFEST_DIR/rticonnextdds-connector`: uses a local directory next to + the crate. +4. `CONNECTOR_VERSION` file: falls back to a version file in the crate root. + +At runtime, ensure the native libraries are discoverable in your system's +library path (for example `DYLD_LIBRARY_PATH` on macOS). + +## Minimal example + +This is the typical flow: create a connector, obtain an output and input, write +one sample, then read samples back. + +```rust +use rtiddsconnector::{Connector, GlobalsDropGuard, Input, Output}; + +fn main() -> rtiddsconnector::ConnectorFallible { + let _globals = GlobalsDropGuard; + + let connector = Connector::new("MyLibrary::MyParticipant", "/path/to/App.xml")?; + let mut output: Output<'_> = connector.get_output("MyPublisher::MyWriter")?; + let mut input: Input<'_> = connector.get_input("MySubscriber::MyReader")?; + + let mut instance = output.instance(); + instance.set_number("x", 100.0)?; + instance.set_number("y", 200.0)?; + instance.set_string("color", "BLUE")?; + output.write()?; + + input.wait_with_timeout(std::time::Duration::from_secs(5))?; + input.take()?; + + for sample in input.into_iter().valid_only() { + println!("Sample: {}", sample); + } + + Ok(()) +} +``` + +For a larger example, see `examples/shapes`. diff --git a/docs/guide/index.md b/docs/guide/index.md new file mode 100644 index 0000000..2b25e2c --- /dev/null +++ b/docs/guide/index.md @@ -0,0 +1,17 @@ +# User Guide + +This guide provides a walkthrough-style introduction to RTI Connector for Rust, +covering setup, configuration, and common publishing/reading workflows. Each +section links to the relevant API reference where appropriate. + +## Contents + +* [Getting started](crate::guide::getting_started) +* [Configuration](crate::guide::configuration) +* [Connector lifecycle](crate::guide::connector) +* [Publishing data](crate::guide::output) +* [Reading data](crate::guide::input) +* [Data access and Serde](crate::guide::data) +* [Error handling](crate::guide::errors) +* [Threading and ownership](crate::guide::threading) +* [Advanced operations](crate::guide::advanced) diff --git a/docs/guide/input.md b/docs/guide/input.md new file mode 100644 index 0000000..5b33bd1 --- /dev/null +++ b/docs/guide/input.md @@ -0,0 +1,89 @@ +# Reading data + +[`crate::Input`] wraps a DDS `DataReader` and provides an iterator-based +interface over samples returned by the RTI Connector API. + +## Getting the input + +```rust +use rtiddsconnector::{Connector, Input}; + +fn get_input(connector: &Connector) -> rtiddsconnector::ConnectorResult> { + connector.get_input("MySubscriber::MyReader") +} +``` + +## Reading or taking the data + +* [`crate::Input::read`]: copies samples into the local cache without removing + them from the reader. +* [`crate::Input::take`]: removes samples from the reader and places them into + the local cache. + +After calling either, iterate over the cache: + +```rust +use rtiddsconnector::Input; + +fn process(input: &mut Input) -> rtiddsconnector::ConnectorFallible { + input.take()?; + + for sample in input.into_iter().valid_only() { + println!("Sample: {}", sample); + } + + Ok(()) +} +``` + +`valid_only()` skips samples with invalid data. + +## Waiting for data + +Use [`crate::Input::wait`] or [`crate::Input::wait_with_timeout`] to block until +data is available. These methods do not read data; call `read` or `take` +afterward. + +If you want to wait for data on any input owned by a connector, use +[`crate::Connector::wait_for_data`] or +[`crate::Connector::wait_for_data_with_timeout`]. These methods do not read +samples; call `read` or `take` afterward. + +## Accessing data samples + +`Sample` provides typed accessors and JSON access: + +* [`crate::Sample::get_number`] +* [`crate::Sample::get_boolean`] +* [`crate::Sample::get_string`] +* [`crate::Sample::get_value_json`] + +`Sample` implements `Display` to print the full JSON representation of the +sample. + +If you need to access meta-data fields (SampleInfo), see the next section. + +## Returning the loan + +If you used [`crate::Input::take`], return the loan when you are done using +[`crate::Input::return_loan`]. This allows the underlying reader to reuse +resources sooner. + +## Accessing sample meta-data + +Every sample includes associated meta-data (SampleInfo). You can access these +fields using [`crate::Sample::get_info`] and [`crate::Sample::get_info_json`]. + +If a sample has invalid data, it still carries meta-data. You can detect this +with [`crate::Sample::is_valid`]. For the list of available info fields and their +meaning, refer to the RTI Connector documentation. + +## Matching publications + +Use [`crate::Input::wait_for_publications`] or +[`crate::Input::wait_for_publications_with_timeout`] to wait for matched +writers. These methods return the change in the number of matched publications +since the last call. + +You can inspect the current list with +[`crate::Input::display_matched_publications`], which returns JSON. diff --git a/docs/guide/output.md b/docs/guide/output.md new file mode 100644 index 0000000..07fa01b --- /dev/null +++ b/docs/guide/output.md @@ -0,0 +1,113 @@ +# Publishing data + +[`crate::Output`] wraps a DDS `DataWriter` and exposes a single mutable +[`crate::Instance`] representing the next sample to write. + +## Getting the output + +```rust +use rtiddsconnector::{Connector, Output}; + +fn get_output(connector: &Connector) -> rtiddsconnector::ConnectorResult> { + connector.get_output("MyPublisher::MyWriter") +} +``` + +## Populating the data sample + +You can set fields member-by-member: + +```rust +use rtiddsconnector::Output; + +fn set_fields(output: &mut Output) -> rtiddsconnector::ConnectorFallible { + let mut instance = output.instance(); + instance.set_number("x", 1.0)?; + instance.set_number("y", 2.0)?; + instance.set_number("shapesize", 30.0)?; + instance.set_string("color", "BLUE")?; + Ok(()) +} +``` + +Or set the entire sample from JSON: + +```rust +use rtiddsconnector::Output; + +fn set_json(output: &mut Output) -> rtiddsconnector::ConnectorFallible { + let mut instance = output.instance(); + instance.set_as_json(r#"{"x":1,"y":2,"shapesize":30,"color":"BLUE"}"#)?; + Ok(()) +} +``` + +Field names correspond to the type assigned to the output in XML. For example: + +```xml + + + + + + +``` + +## Writing the data sample + +To write the values set in the instance, call [`crate::Output::write`]: + +```rust +use rtiddsconnector::Output; + +fn write_once(output: &mut Output) -> rtiddsconnector::ConnectorFallible { + output.write() +} +``` + +If the DataWriter QoS is reliable, use [`crate::Output::wait`] or +[`crate::Output::wait_with_timeout`] to wait for acknowledgments: + +```rust +use rtiddsconnector::Output; + +fn write_and_wait(output: &mut Output) -> rtiddsconnector::ConnectorFallible { + output.write()?; + output.wait() +} +``` + +To write with parameters such as a source timestamp, use +[`crate::WriteParams`] and [`crate::Output::write_with_params`]: + +```rust +use rtiddsconnector::{Output, WriteParams}; + +fn write_with_timestamp(output: &mut Output, ts: i64) -> rtiddsconnector::ConnectorFallible { + let params = WriteParams::write().with_source_timestamp(ts); + output.write_with_params(¶ms) +} +``` + +You can also dispose or unregister an instance: + +```rust +use rtiddsconnector::{Output, WriteParams}; + +fn dispose_instance(output: &mut Output) -> rtiddsconnector::ConnectorFallible { + let params = WriteParams::dispose(); + output.write_with_params(¶ms) +} +``` + +In these cases, only the key fields are relevant. + +## Matching with a subscription + +Use [`crate::Output::wait_for_subscriptions`] or +[`crate::Output::wait_for_subscriptions_with_timeout`] to detect matched or +unmatched subscriptions. These methods return the change in the number of +matches since the last call. + +You can inspect the current list of matched subscriptions as JSON with +[`crate::Output::display_matched_subscriptions`]. diff --git a/docs/guide/threading.md b/docs/guide/threading.md new file mode 100644 index 0000000..69de934 --- /dev/null +++ b/docs/guide/threading.md @@ -0,0 +1,23 @@ +# Threading and ownership + +The underlying RTI Connector C API is not thread-safe. The Rust bindings provide +synchronization around the native connector and enforce single-threaded +ownership of `Input` and `Output` handles. + +## Ownership rules + +* `Connector::get_input` and `Connector::get_output` return exclusive handles. +* If an entity is already owned by another thread, you will receive an error. +* Use `Connector::take_input` and `Connector::take_output` to block until the + entity is free. + +## Practical guidance + +Keep each `Input` or `Output` on a single thread at a time. If you need to share +work, consider a worker thread that owns the handle and communicates via +channels with the rest of your application. + +While the connector uses internal locks for native access, this is not a +guarantee of safe concurrent access to the same `Input` or `Output`. Treat the +API as single-threaded unless you control synchronization at the application +level. diff --git a/docs/input.md b/docs/input.md index 5656bc9..e02b5e0 100644 --- a/docs/input.md +++ b/docs/input.md @@ -1,8 +1,43 @@ -# Input, Sample and related utilities +# Input, Sample, and related utilities -The [`Input`] interface is used to read data samples from DDS topics. +The [`Input`] interface is used to read data samples from DDS topics. It wraps a +`DataReader` configured in your XML file and provides a cached view of samples +retrieved by [`Input::read`] or [`Input::take`]. -The [`Sample`] interface represents a data sample read from an [`Input`]. +## Reading data -The [`SampleIterator`] interface provides an iterator over valid samples -read from an [`Input`]. +Use [`Input::read`] to fill the local sample cache without removing samples from +DDS, or [`Input::take`] to remove them from the reader. After either call, iterate +samples using `for sample in input.into_iter()` or filter valid samples with +[`ValidSampleIterator`]: + +```text +input.take()?; + +for sample in input.into_iter().valid_only() { + println!("Sample: {}", sample); +} +``` + +If you call `take`, you can return the loan with [`Input::return_loan`] after you +finish processing. + +## Waiting for data + +To block until data is available, use [`Input::wait`] or +[`Input::wait_with_timeout`]. These calls do not read data; they only wait for +availability. You still need to call `read` or `take` to populate the cache. + +## Accessing fields + +A [`Sample`] provides typed accessors like [`Sample::get_number`], +[`Sample::get_string`], and [`Sample::get_boolean`]. For dynamic access, use +[`Sample::get_value`] which returns a [`SelectedValue`], or get a JSON string +using [`Sample::get_value_json`]. You can also access sample info fields via +[`Sample::get_info`] and [`Sample::get_info_json`]. + +## Matched publications + +Use [`Input::wait_for_publications`] or [`Input::wait_for_publications_with_timeout`] +to wait for writers, and [`Input::display_matched_publications`] to retrieve the +matched publications as JSON. diff --git a/docs/lib.md b/docs/lib.md index b442ffa..7843a60 100644 --- a/docs/lib.md +++ b/docs/lib.md @@ -1,11 +1,11 @@ -# A simple DDS API for Rust (Experimental) +# RTI Connector for Rust The `rtiddsconnector` crate provides a lightweight interface with which to access DDS domains from Rust using [RTI Connext][rti-pro] C libraries and the simplified _RTI Connector_ API. The API offered by `rtiddsconnector` does **NOT** match the -[standard DDS API][omg-dds]. Rather, it offers a simplified interface developed +[standard DDS API][omg-dds]. Rather, it offers a simplified interface developed for faster and easier integration in any programming language with access to native C code. @@ -37,7 +37,22 @@ the _RTI Connector_ API: [omg-dds-xml]: https://www.omg.org/spec/DDS-XML/ "OMG DDS XML Specification" [gh-connector]: https://github.com/rticommunity/rticonnextdds-connector "RTI Connector on Github" -## Overview +## User Guide + +Start here for a walkthrough-first tour of the crate: + +* [API Overview](#api-overview) +* [Getting started](crate::guide::getting_started) +* [Configuration](crate::guide::configuration) +* [Connector lifecycle](crate::guide::connector) +* [Publishing data](crate::guide::output) +* [Reading data](crate::guide::input) +* [Data access and Serde](crate::guide::data) +* [Error handling](crate::guide::errors) +* [Threading and ownership](crate::guide::threading) +* [Advanced operations](crate::guide::advanced) + +## API Overview The `rtiddsconnector` crate exposes the _RTI Connector_ API through the following main abstractions: @@ -50,65 +65,12 @@ The `rtiddsconnector` crate exposes the _RTI Connector_ API through the followin In addition to these main abstractions, the crate also exposes, among others, the following types: -* [`Sample`]: A trait representing a data sample read from an `Input`. -* [`SampleIterator`]: An iterator over valid samples read from an `Input`. +* [`Sample`]: A struct representing a data sample read from an `Input`. +* [`SampleIterator`]: An iterator over samples read from an `Input`. +* [`ValidSampleIterator`]: An iterator that filters only valid samples. * [`Instance`]: A struct representing a data sample to be written to an `Output`. +* [`SelectedValue`]: A variant type used to set or read fields without JSON. * [`ConnectorError`]: A struct representing errors that can occur when using the _Connector_ API. * [`ConnectorResult`]: A type alias for `Result`, used for error handling. -* [`ConnectorFallible`]: A type alias for `Result>`, used for fallible operations. +* [`ConnectorFallible`]: A type alias for `Result<(), ConnectorError>`, used for fallible operations. * [`GlobalsDropGuard`]: A struct that ensures proper cleanup of global resources used by the _Connector_ API. - -### Typed Data Support - -This crate provides Serde-based serialization and deserialization support -for working with strongly-typed data structures instead of raw JSON. -It extends the `Instance` and `Sample` types with methods to serialize -Rust structs to JSON and deserialize JSON to Rust structs, respectively. - -See the documentation for [`Instance::serialize`] and [`Sample::deserialize`]. - -### Error Handling - -Because many operations in the _RTI Connector_ API can fail due to various reasons, most of them handled -externally in the underlying C implementation, the `rtiddsconnector` crate provides -the [`ConnectorError`] struct as an opaque representation of errors that can occur when using the API. - -The [`ConnectorResult`] type alias is used throughout the crate to represent operations that can -succeed or fail with a [`ConnectorError`]. Most public methods in the crate return a [`ConnectorResult`], -where `T` is the expected return type of the operation. - -### Thread safety - -The `rtiddsconnector` crate attempts to provide safe abstractions over the underlying -C implementation, which is not thread-safe. This means that while the crate attempts to use -Rust's safety guarantees, developers must be careful when using multiple threads. - -### Build-time linking - -Because `rtiddsconnector` is built on top of [RTI Connext][rti-pro] C libraries, -applications using this crate must ensure that the required C libraries are -available at runtime. - -The `build.rs` script included in the crate can automatically configure -the linker to find the required libraries, namely: - -1. If the `RTI_CONNECTOR_VERSION` environment variable is defined, it will attempt to download - the target-specific C libraries from the [corresponding Github release][gh-connector-releases]. -2. If the `RTI_CONNECTOR_DIR` environment variable is defined, it will use the C libraries - found in the specified directory. -3. If neither of the above environment variables is defined, it will attempt to find the C libraries - in a default location based on common installation paths. - -If neither of these methods is successful, the build will fail with an error message -indicating that the C libraries could not be found. - -Once your application has been built, `cargo` commands will automatically pick up the -linker instructions generated by `build.rs`, so no additional configuration is needed -to link the [RTI Connext][rti-pro] C libraries when using `cargo test` or similar. - -However, when deploying your application, make sure that the required C libraries -are available in the system's library path, or in a location specified by -the appropriate environment variable (e.g., `LD_LIBRARY_PATH` on Linux, -`DYLD_LIBRARY_PATH` on macOS, or `PATH` on Windows). - -[gh-connector-releases]: https://github.com/rticommunity/rticonnextdds-connector/releases "RTI Connector Releases on Github" diff --git a/docs/output.md b/docs/output.md index 39ef0de..676a816 100644 --- a/docs/output.md +++ b/docs/output.md @@ -1,6 +1,34 @@ -# Output, Instance and related utilities +# Output, Instance, and related utilities -The [`Output`] interface is used to write data out to a DDS domain. +The [`Output`] interface is used to write data out to a DDS domain. It wraps a +`DataWriter` configured in your XML file and exposes a single writable +[`Instance`] that represents the next sample to be published. -The [`Instance`] interface is used to manipulate the data to be sent, -and can be accessed by means of [`Output::instance`]. +## Writing data + +Modify the instance with `set_*` methods or JSON, then publish it using +[`Output::write`]: + +```text +let mut instance = output.instance(); +instance.set_string("color", "BLUE")?; +instance.set_number("x", 100.0)?; +instance.set_number("y", 150.0)?; + +output.write()?; +``` + +For typed data, use [`Instance::serialize`] to serialize a struct via Serde. + +## Write parameters + +Use [`Output::write_with_params`] and [`WriteParams`] to control actions like +`dispose` or `unregister`, or to attach timestamps and identities. + +## Waiting and matching + +You can wait for acknowledgments with [`Output::wait`] or +[`Output::wait_with_timeout`], and you can wait for subscriptions with +[`Output::wait_for_subscriptions`] or [`Output::wait_for_subscriptions_with_timeout`]. +Use [`Output::display_matched_subscriptions`] to retrieve matched subscriptions +as JSON. diff --git a/docs/result.md b/docs/result.md index 351f251..3dfab08 100644 --- a/docs/result.md +++ b/docs/result.md @@ -1,12 +1,20 @@ -# Result types for Error Handling +# Result types for error handling -The [`ConnectorError`] enum represents possible errors that can occur -when using the Connector API. +The `rtiddsconnector` API uses a small set of result types: -The [`ConnectorResult`] type alias is used throughout the crate -to represent operations that can succeed or fail with a -[`ConnectorError`]. +* [`ConnectorResult`]: the standard result type for fallible operations. +* [`ConnectorFallible`]: a convenience alias for `Result<(), ConnectorError>`. +* [`ConnectorError`]: the error type used throughout the crate. -The [`ConnectorFallible`] type alias is used for operations -that can can fail with [`ConnectorError`] but that doesn't have a -meaningful return value (it is `()`). +## Inspecting errors + +`ConnectorError` exposes helper methods to classify errors: + +* [`ConnectorError::is_timeout`] +* [`ConnectorError::is_entity_not_found`] +* [`ConnectorError::is_field_not_found`] +* [`ConnectorError::is_native_error`] +* [`ConnectorError::last_error_message`] + +These helpers allow you to handle common cases without depending on internal +error kinds. diff --git a/src/guide/mod.rs b/src/guide/mod.rs new file mode 100644 index 0000000..4230ae8 --- /dev/null +++ b/src/guide/mod.rs @@ -0,0 +1,66 @@ +#![doc = include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/docs/guide/index.md"))] +#![doc(alias = "user guide")] + +#[doc(alias = "getting started")] +pub mod getting_started { + #![doc = include_str!(concat!( + env!("CARGO_MANIFEST_DIR"), + "/docs/guide/getting_started.md" + ))] +} + +pub mod configuration { + #![doc = include_str!(concat!( + env!("CARGO_MANIFEST_DIR"), + "/docs/guide/configuration.md" + ))] +} + +pub mod connector { + #![doc = include_str!(concat!( + env!("CARGO_MANIFEST_DIR"), + "/docs/guide/connector.md" + ))] +} + +pub mod input { + #![doc = include_str!(concat!( + env!("CARGO_MANIFEST_DIR"), + "/docs/guide/input.md" + ))] +} + +pub mod output { + #![doc = include_str!(concat!( + env!("CARGO_MANIFEST_DIR"), + "/docs/guide/output.md" + ))] +} + +pub mod data { + #![doc = include_str!(concat!( + env!("CARGO_MANIFEST_DIR"), + "/docs/guide/data.md" + ))] +} + +pub mod errors { + #![doc = include_str!(concat!( + env!("CARGO_MANIFEST_DIR"), + "/docs/guide/errors.md" + ))] +} + +pub mod threading { + #![doc = include_str!(concat!( + env!("CARGO_MANIFEST_DIR"), + "/docs/guide/threading.md" + ))] +} + +pub mod advanced { + #![doc = include_str!(concat!( + env!("CARGO_MANIFEST_DIR"), + "/docs/guide/advanced.md" + ))] +} diff --git a/src/lib.rs b/src/lib.rs index 42b5ea2..4afdd48 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -24,6 +24,7 @@ pub use result::{ConnectorError, ConnectorFallible, ConnectorResult}; mod connector; mod ffi; +pub mod guide; mod input; mod output; mod result; From 2185a22eaa34537bc6c589f4e83ce76fb48839f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20N=C3=BA=C3=B1ez?= Date: Wed, 14 Jan 2026 12:54:56 +0100 Subject: [PATCH 2/7] Make `guide` doc-only, flatten it --- src/guide/mod.rs | 66 -------------------------------------------- src/lib.rs | 71 +++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 70 insertions(+), 67 deletions(-) delete mode 100644 src/guide/mod.rs diff --git a/src/guide/mod.rs b/src/guide/mod.rs deleted file mode 100644 index 4230ae8..0000000 --- a/src/guide/mod.rs +++ /dev/null @@ -1,66 +0,0 @@ -#![doc = include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/docs/guide/index.md"))] -#![doc(alias = "user guide")] - -#[doc(alias = "getting started")] -pub mod getting_started { - #![doc = include_str!(concat!( - env!("CARGO_MANIFEST_DIR"), - "/docs/guide/getting_started.md" - ))] -} - -pub mod configuration { - #![doc = include_str!(concat!( - env!("CARGO_MANIFEST_DIR"), - "/docs/guide/configuration.md" - ))] -} - -pub mod connector { - #![doc = include_str!(concat!( - env!("CARGO_MANIFEST_DIR"), - "/docs/guide/connector.md" - ))] -} - -pub mod input { - #![doc = include_str!(concat!( - env!("CARGO_MANIFEST_DIR"), - "/docs/guide/input.md" - ))] -} - -pub mod output { - #![doc = include_str!(concat!( - env!("CARGO_MANIFEST_DIR"), - "/docs/guide/output.md" - ))] -} - -pub mod data { - #![doc = include_str!(concat!( - env!("CARGO_MANIFEST_DIR"), - "/docs/guide/data.md" - ))] -} - -pub mod errors { - #![doc = include_str!(concat!( - env!("CARGO_MANIFEST_DIR"), - "/docs/guide/errors.md" - ))] -} - -pub mod threading { - #![doc = include_str!(concat!( - env!("CARGO_MANIFEST_DIR"), - "/docs/guide/threading.md" - ))] -} - -pub mod advanced { - #![doc = include_str!(concat!( - env!("CARGO_MANIFEST_DIR"), - "/docs/guide/advanced.md" - ))] -} diff --git a/src/lib.rs b/src/lib.rs index 4afdd48..463d7a5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -24,7 +24,76 @@ pub use result::{ConnectorError, ConnectorFallible, ConnectorResult}; mod connector; mod ffi; -pub mod guide; mod input; mod output; mod result; + +#[cfg(doc)] +/// Guide module with in-depth documentation about various aspects of the crate. +pub mod guide { + #![doc = include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/docs/guide/index.md"))] + + /// A quick walkthrough to get started with the Connector. + pub mod getting_started { + #![doc = include_str!(concat!( + env!("CARGO_MANIFEST_DIR"), + "/docs/guide/getting_started.md" + ))] + } + /// Configuration options and details for the Connector. + pub mod configuration { + #![doc = include_str!(concat!( + env!("CARGO_MANIFEST_DIR"), + "/docs/guide/configuration.md" + ))] + } + /// Connector lifecycle: creating, using, and destroying a Connector. + pub mod connector { + #![doc = include_str!(concat!( + env!("CARGO_MANIFEST_DIR"), + "/docs/guide/connector.md" + ))] + } + /// Subscribing to data and reading samples from an Input. + pub mod input { + #![doc = include_str!(concat!( + env!("CARGO_MANIFEST_DIR"), + "/docs/guide/input.md" + ))] + } + /// Publishing data and writing samples to an Output. + pub mod output { + #![doc = include_str!(concat!( + env!("CARGO_MANIFEST_DIR"), + "/docs/guide/output.md" + ))] + } + /// Data access patterns and Serde integration. + pub mod data { + #![doc = include_str!(concat!( + env!("CARGO_MANIFEST_DIR"), + "/docs/guide/data.md" + ))] + } + /// Error handling and Connector errors. + pub mod errors { + #![doc = include_str!(concat!( + env!("CARGO_MANIFEST_DIR"), + "/docs/guide/errors.md" + ))] + } + /// Threading, ownership, and safety considerations. + pub mod threading { + #![doc = include_str!(concat!( + env!("CARGO_MANIFEST_DIR"), + "/docs/guide/threading.md" + ))] + } + /// Advanced operations and customization. + pub mod advanced { + #![doc = include_str!(concat!( + env!("CARGO_MANIFEST_DIR"), + "/docs/guide/advanced.md" + ))] + } +} From 4f2072a78a6dd635a00117a6b3881913b1c200f8 Mon Sep 17 00:00:00 2001 From: Alex Campos Date: Wed, 14 Jan 2026 11:27:17 -0800 Subject: [PATCH 3/7] PR feedback --- docs/guide/connector.md | 2 +- docs/guide/getting_started.md | 38 ++++++++++++------ docs/guide/output.md | 3 ++ docs/lib.md | 25 +----------- src/guide/mod.rs | 66 ------------------------------- src/lib.rs | 73 ++++++++++++++++++++++++++++++++++- 6 files changed, 104 insertions(+), 103 deletions(-) delete mode 100644 src/guide/mod.rs diff --git a/docs/guide/connector.md b/docs/guide/connector.md index 1dc5c6e..ae2a096 100644 --- a/docs/guide/connector.md +++ b/docs/guide/connector.md @@ -6,7 +6,7 @@ It owns native resources and creates `Input` and `Output` handles. ## Importing the crate ```rust -use rtiddsconnector::Connector; +use rtiddsconnector::{self, Connector}; ``` ## Creating a connector diff --git a/docs/guide/getting_started.md b/docs/guide/getting_started.md index 7aa3623..15fe239 100644 --- a/docs/guide/getting_started.md +++ b/docs/guide/getting_started.md @@ -11,19 +11,14 @@ cargo add --git https://github.com/rticommunity/rticonnextdds-connector-rs If you need a specific branch, add `--branch `. -## Ensure native libraries are available +## Running the examples -At build time, `build.rs` locates the RTI Connector C libraries in this order: +The repository includes: -1. `RTI_CONNECTOR_VERSION`: downloads the target-specific libraries from the - RTI Connector GitHub releases. -2. `RTI_CONNECTOR_DIR`: uses a local directory containing the libraries. -3. `CARGO_MANIFEST_DIR/rticonnextdds-connector`: uses a local directory next to - the crate. -4. `CONNECTOR_VERSION` file: falls back to a version file in the crate root. +* `examples/shapes` (publisher/subscriber example) +* `snippets` (read-only code snippets used in the docs) -At runtime, ensure the native libraries are discoverable in your system's -library path (for example `DYLD_LIBRARY_PATH` on macOS). +See `examples/shapes/README.md` for usage details. ## Minimal example @@ -57,4 +52,25 @@ fn main() -> rtiddsconnector::ConnectorFallible { } ``` -For a larger example, see `examples/shapes`. +## Advanced: Configure the native libraries + +At build time, `build.rs` locates the RTI Connector C libraries in this order: + +1. `RTI_CONNECTOR_VERSION`: downloads the target-specific libraries from the + RTI Connector GitHub releases. +2. `RTI_CONNECTOR_DIR`: uses a local directory containing the libraries. +3. `CARGO_MANIFEST_DIR/rticonnextdds-connector`: uses a local directory next to + the crate. +4. `CONNECTOR_VERSION` file: falls back to a version file in the crate root. + +If neither of these methods is successful, the build will fail with an error +message indicating that the C libraries could not be found. + +Once your application has been built, `cargo` commands will automatically pick +up the linker instructions generated by `build.rs`, so no additional +configuration is needed to link the RTI Connext C libraries when using +`cargo test` or similar. + +At runtime, ensure the native libraries are discoverable in your system's +library path (for example `DYLD_LIBRARY_PATH` on macOS, `LD_LIBRARY_PATH` on +Linux, or `PATH` on Windows). \ No newline at end of file diff --git a/docs/guide/output.md b/docs/guide/output.md index 07fa01b..62134d1 100644 --- a/docs/guide/output.md +++ b/docs/guide/output.md @@ -42,6 +42,9 @@ fn set_json(output: &mut Output) -> rtiddsconnector::ConnectorFallible { } ``` +For strongly-typed models, see [Data access and Serde](crate::guide::data) and +[`crate::Instance::serialize`]. + Field names correspond to the type assigned to the output in XML. For example: ```xml diff --git a/docs/lib.md b/docs/lib.md index 7843a60..6146f93 100644 --- a/docs/lib.md +++ b/docs/lib.md @@ -39,9 +39,8 @@ the _RTI Connector_ API: ## User Guide -Start here for a walkthrough-first tour of the crate: +Start here for a tour of the crate: -* [API Overview](#api-overview) * [Getting started](crate::guide::getting_started) * [Configuration](crate::guide::configuration) * [Connector lifecycle](crate::guide::connector) @@ -52,25 +51,3 @@ Start here for a walkthrough-first tour of the crate: * [Threading and ownership](crate::guide::threading) * [Advanced operations](crate::guide::advanced) -## API Overview - -The `rtiddsconnector` crate exposes the _RTI Connector_ API through the following main abstractions: - -* [`Connector`]: Represents a DDS _DomainParticipant_, and is used to create - `Input` and `Output` objects for reading and writing data. -* [`Input`]: Represents a DDS _DataReader_, and is used to read data samples - from DDS _Topics_. -* [`Output`]: Represents a DDS _DataWriter_, and is used to write data samples - to DDS _Topics_. - -In addition to these main abstractions, the crate also exposes, among others, the following types: - -* [`Sample`]: A struct representing a data sample read from an `Input`. -* [`SampleIterator`]: An iterator over samples read from an `Input`. -* [`ValidSampleIterator`]: An iterator that filters only valid samples. -* [`Instance`]: A struct representing a data sample to be written to an `Output`. -* [`SelectedValue`]: A variant type used to set or read fields without JSON. -* [`ConnectorError`]: A struct representing errors that can occur when using the _Connector_ API. -* [`ConnectorResult`]: A type alias for `Result`, used for error handling. -* [`ConnectorFallible`]: A type alias for `Result<(), ConnectorError>`, used for fallible operations. -* [`GlobalsDropGuard`]: A struct that ensures proper cleanup of global resources used by the _Connector_ API. diff --git a/src/guide/mod.rs b/src/guide/mod.rs deleted file mode 100644 index 4230ae8..0000000 --- a/src/guide/mod.rs +++ /dev/null @@ -1,66 +0,0 @@ -#![doc = include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/docs/guide/index.md"))] -#![doc(alias = "user guide")] - -#[doc(alias = "getting started")] -pub mod getting_started { - #![doc = include_str!(concat!( - env!("CARGO_MANIFEST_DIR"), - "/docs/guide/getting_started.md" - ))] -} - -pub mod configuration { - #![doc = include_str!(concat!( - env!("CARGO_MANIFEST_DIR"), - "/docs/guide/configuration.md" - ))] -} - -pub mod connector { - #![doc = include_str!(concat!( - env!("CARGO_MANIFEST_DIR"), - "/docs/guide/connector.md" - ))] -} - -pub mod input { - #![doc = include_str!(concat!( - env!("CARGO_MANIFEST_DIR"), - "/docs/guide/input.md" - ))] -} - -pub mod output { - #![doc = include_str!(concat!( - env!("CARGO_MANIFEST_DIR"), - "/docs/guide/output.md" - ))] -} - -pub mod data { - #![doc = include_str!(concat!( - env!("CARGO_MANIFEST_DIR"), - "/docs/guide/data.md" - ))] -} - -pub mod errors { - #![doc = include_str!(concat!( - env!("CARGO_MANIFEST_DIR"), - "/docs/guide/errors.md" - ))] -} - -pub mod threading { - #![doc = include_str!(concat!( - env!("CARGO_MANIFEST_DIR"), - "/docs/guide/threading.md" - ))] -} - -pub mod advanced { - #![doc = include_str!(concat!( - env!("CARGO_MANIFEST_DIR"), - "/docs/guide/advanced.md" - ))] -} diff --git a/src/lib.rs b/src/lib.rs index 4afdd48..3884501 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -24,7 +24,78 @@ pub use result::{ConnectorError, ConnectorFallible, ConnectorResult}; mod connector; mod ffi; -pub mod guide; +#[cfg(doc)] +pub mod guide { + #![doc = include_str!(concat!( + env!("CARGO_MANIFEST_DIR"), + "/docs/guide/index.md" + ))] + #![doc(alias = "user guide")] + + #[doc(alias = "getting started")] + pub mod getting_started { + #![doc = include_str!(concat!( + env!("CARGO_MANIFEST_DIR"), + "/docs/guide/getting_started.md" + ))] + } + + pub mod configuration { + #![doc = include_str!(concat!( + env!("CARGO_MANIFEST_DIR"), + "/docs/guide/configuration.md" + ))] + } + + pub mod connector { + #![doc = include_str!(concat!( + env!("CARGO_MANIFEST_DIR"), + "/docs/guide/connector.md" + ))] + } + + pub mod input { + #![doc = include_str!(concat!( + env!("CARGO_MANIFEST_DIR"), + "/docs/guide/input.md" + ))] + } + + pub mod output { + #![doc = include_str!(concat!( + env!("CARGO_MANIFEST_DIR"), + "/docs/guide/output.md" + ))] + } + + pub mod data { + #![doc = include_str!(concat!( + env!("CARGO_MANIFEST_DIR"), + "/docs/guide/data.md" + ))] + } + + pub mod errors { + #![doc = include_str!(concat!( + env!("CARGO_MANIFEST_DIR"), + "/docs/guide/errors.md" + ))] + } + + pub mod threading { + #![doc = include_str!(concat!( + env!("CARGO_MANIFEST_DIR"), + "/docs/guide/threading.md" + ))] + } + + pub mod advanced { + #![doc = include_str!(concat!( + env!("CARGO_MANIFEST_DIR"), + "/docs/guide/advanced.md" + ))] + } +} mod input; mod output; mod result; From 72a49fc22249248aefddf2929438d8fe59215201 Mon Sep 17 00:00:00 2001 From: Alex Campos Date: Wed, 14 Jan 2026 12:52:54 -0800 Subject: [PATCH 4/7] PR feedback (tech writer edits) --- docs/guide/configuration.md | 12 ++++++------ docs/guide/connector.md | 23 +++++++++++++---------- docs/guide/data.md | 9 ++++----- docs/guide/errors.md | 4 +++- docs/guide/getting_started.md | 23 +++++++++++++---------- docs/lib.md | 2 +- 6 files changed, 40 insertions(+), 33 deletions(-) diff --git a/docs/guide/configuration.md b/docs/guide/configuration.md index 63258cc..20cc2e0 100644 --- a/docs/guide/configuration.md +++ b/docs/guide/configuration.md @@ -4,9 +4,8 @@ RTI Connector for Rust uses an XML configuration file to define participants, readers, writers, topics, types, and QoS. The XML schema is the same one used by RTI Connext DDS XML-Based Application Creation. -For background on the XML format, see: - -* +For background on the XML format, see the +[RTI XML-Based Application Creation guide](https://community.rti.com/static/documentation/connext-dds/current/doc/manuals/connext_dds_professional/xml_application_creation/index.htm). ## Loading a configuration @@ -23,7 +22,7 @@ fn load_config() -> rtiddsconnector::ConnectorFallible { The `config_name` must match a `` element in the XML. -## XML tags and Connector API +## XML tags and Connector API mapping The table below summarizes the most common XML tags and how they map to the Connector API: @@ -73,7 +72,8 @@ Domains register types and define topics: ## Participants, readers, and writers -Participants contain publishers and subscribers, which contain writers/readers: +Participants contain publishers and subscribers, which in turn manage individual +writers and readers: ```xml @@ -114,7 +114,7 @@ QoS can be configured at the profile level or per-entity. Example profile: ## Examples in this repo -The repository includes XML examples you can adapt: +This repository includes XML examples you can adapt: * `examples/MyApplication.xml` * `examples/shapes/Shapes.xml` diff --git a/docs/guide/connector.md b/docs/guide/connector.md index ae2a096..470b862 100644 --- a/docs/guide/connector.md +++ b/docs/guide/connector.md @@ -1,10 +1,15 @@ # Connector lifecycle +This chapter covers creating a connector, acquiring inputs and outputs, and +cleaning up native resources. + [`crate::Connector`] represents a DDS `DomainParticipant` configured from XML. It owns native resources and creates `Input` and `Output` handles. ## Importing the crate +To import the crate: + ```rust use rtiddsconnector::{self, Connector}; ``` @@ -24,7 +29,7 @@ fn create_connector() -> rtiddsconnector::ConnectorFallible { ``` The XML file defines your types, QoS profiles, and DDS entities. The call above -loads a `` from a ``, for example: +loads a `` from a ``. For example: ```xml @@ -42,8 +47,8 @@ There is no explicit `close()` method in Rust. Instead, `Connector`, `Input`, an `Output` are released when they go out of scope. The crate uses RAII to free native resources. -If you want to force cleanup of Connext global resources at the end of a scope -(for example in tests), use [`crate::GlobalsDropGuard`]. +To force cleanup of Connext global resources at the end of a scope +(for example, in tests), use [`crate::GlobalsDropGuard`]. ## Getting inputs and outputs @@ -56,16 +61,14 @@ until the entity becomes available, use [`crate::Connector::take_input`] or See [Publishing data](crate::guide::output) and [Reading data](crate::guide::input) for the workflow that follows. -## Threading note - -Operations on the same `Connector` or its contained entities are not protected -for multi-threaded access. See [Threading and ownership](crate::guide::threading) -for guidance. +> **Note:** Multiple operations on the same `Connector`, or its contained +> entities, are not protected for multi-threaded access. See +> [Threading and ownership](crate::guide::threading) for guidance. -## Auto-enable considerations +## DataReader auto-enable considerations Connext DDS controls entity enablement through XML QoS settings (for example, `/`). If readers are enabled before you acquire an `Input`, data may already be available when you call -`get_input`. This behavior comes from Connext configuration rather than the +`get_input`. This behavior stems from your Connext configuration rather than the Rust API itself. diff --git a/docs/guide/data.md b/docs/guide/data.md index 4427e5f..6290e36 100644 --- a/docs/guide/data.md +++ b/docs/guide/data.md @@ -7,7 +7,7 @@ accessors for common primitive fields. The types you read and write can include nested structs, sequences, arrays, and unions. These types are defined in XML following RTI's XML-Based Application -Creation format. See +Creation format. For details, see [RTI XML-Based Application Creation](https://community.rti.com/static/documentation/connext-dds/current/doc/manuals/connext_dds_professional/xml_application_creation/xml_based_app_creation_guide/UnderstandingXMLBased/XMLTagsConfigEntities.htm). ## JSON vs member access @@ -46,9 +46,8 @@ fn get_basic(sample: &Sample) -> rtiddsconnector::ConnectorFallible { ## Accessing complex members Examples of field-name syntax for nested members, arrays, sequences, and unions -are available in the Connector JavaScript API documentation: - -[Accessing the data (field-name syntax examples)](https://community.rti.com/static/documentation/connector/current/api/javascript/data.html#.) +are available in the [Accessing the data (field-name syntax examples)](https://community.rti.com/static/documentation/connector/current/api/javascript/data.html#) +chapter of the Connector for JavaScript API documentation. ## Type-independent access with SelectedValue @@ -93,5 +92,5 @@ If you want to work with Rust structs, use Serde: instance. * [`crate::Sample::deserialize`]: deserialize a sample into a struct. -These methods allow you to keep strongly typed models in your application while +These methods allow you to keep strongly-typed models in your application while still using the dynamic RTI Connector API. diff --git a/docs/guide/errors.md b/docs/guide/errors.md index 8078805..c2da76d 100644 --- a/docs/guide/errors.md +++ b/docs/guide/errors.md @@ -27,6 +27,8 @@ To inspect the last native error message, call ## Timeout example +This example waits for data and treats a timeout as a non-fatal outcome. + ```rust use rtiddsconnector::Input; @@ -45,6 +47,6 @@ fn wait_with_timeout(input: &Input) -> rtiddsconnector::ConnectorFallible { ## Native error details If an operation fails because of a native RTI Connector error, the -`ConnectorError` will include the last error message from the native library. +[`crate::ConnectorError`] will include the last error message from the native library. This can provide additional context when debugging configuration or data access issues. diff --git a/docs/guide/getting_started.md b/docs/guide/getting_started.md index 15fe239..faa88ee 100644 --- a/docs/guide/getting_started.md +++ b/docs/guide/getting_started.md @@ -1,7 +1,8 @@ # Getting started This crate is intended to be consumed from Cargo as a Git dependency. The -examples in `snippets/` and `examples/` are also included in the repository. +examples in `snippets/` and `examples/` are also included in the +[rticonnextdds-connector-rust repository](https://github.com/rticommunity/rticonnextdds-connector-rust). ## Add the dependency @@ -9,7 +10,8 @@ examples in `snippets/` and `examples/` are also included in the repository. cargo add --git https://github.com/rticommunity/rticonnextdds-connector-rs ``` -If you need a specific branch, add `--branch `. +This command adds the Connector for Rust repository to your project. If you +need a specific branch, add `--branch `. ## Running the examples @@ -22,8 +24,9 @@ See `examples/shapes/README.md` for usage details. ## Minimal example -This is the typical flow: create a connector, obtain an output and input, write -one sample, then read samples back. +This is the typical flow for using Connector: create a connector, +obtain an output and input, write one sample, then read samples back. For +example: ```rust use rtiddsconnector::{Connector, GlobalsDropGuard, Input, Output}; @@ -56,14 +59,14 @@ fn main() -> rtiddsconnector::ConnectorFallible { At build time, `build.rs` locates the RTI Connector C libraries in this order: -1. `RTI_CONNECTOR_VERSION`: downloads the target-specific libraries from the +1. `RTI_CONNECTOR_VERSION` downloads the target-specific libraries from the RTI Connector GitHub releases. -2. `RTI_CONNECTOR_DIR`: uses a local directory containing the libraries. -3. `CARGO_MANIFEST_DIR/rticonnextdds-connector`: uses a local directory next to +2. `RTI_CONNECTOR_DIR` uses a local directory containing the libraries. +3. `CARGO_MANIFEST_DIR/rticonnextdds-connector` uses a local directory next to the crate. -4. `CONNECTOR_VERSION` file: falls back to a version file in the crate root. +4. `CONNECTOR_VERSION` file falls back to a version file in the crate root. -If neither of these methods is successful, the build will fail with an error +If none of the methods above is successful, the build will fail with an error message indicating that the C libraries could not be found. Once your application has been built, `cargo` commands will automatically pick @@ -73,4 +76,4 @@ configuration is needed to link the RTI Connext C libraries when using At runtime, ensure the native libraries are discoverable in your system's library path (for example `DYLD_LIBRARY_PATH` on macOS, `LD_LIBRARY_PATH` on -Linux, or `PATH` on Windows). \ No newline at end of file +Linux, or `PATH` on Windows). diff --git a/docs/lib.md b/docs/lib.md index 6146f93..da6ed54 100644 --- a/docs/lib.md +++ b/docs/lib.md @@ -37,7 +37,7 @@ the _RTI Connector_ API: [omg-dds-xml]: https://www.omg.org/spec/DDS-XML/ "OMG DDS XML Specification" [gh-connector]: https://github.com/rticommunity/rticonnextdds-connector "RTI Connector on Github" -## User Guide +# User Guide Start here for a tour of the crate: From ade2560789496d68c2b5c1d5c4138ee563037555 Mon Sep 17 00:00:00 2001 From: Alex Campos Date: Wed, 14 Jan 2026 13:45:20 -0800 Subject: [PATCH 5/7] Align wording with existing JS docs --- docs/guide/configuration.md | 3 +- docs/guide/connector.md | 38 +++++++-------- docs/guide/input.md | 92 ++++++++++++++++++++++++------------- docs/guide/output.md | 29 ++++++------ docs/guide/threading.md | 4 +- 5 files changed, 97 insertions(+), 69 deletions(-) diff --git a/docs/guide/configuration.md b/docs/guide/configuration.md index 20cc2e0..9fdc221 100644 --- a/docs/guide/configuration.md +++ b/docs/guide/configuration.md @@ -114,7 +114,8 @@ QoS can be configured at the profile level or per-entity. Example profile: ## Examples in this repo -This repository includes XML examples you can adapt: +This repository includes XML examples you can adapt. For an example +configuration file, see `examples/shapes/Shapes.xml`: * `examples/MyApplication.xml` * `examples/shapes/Shapes.xml` diff --git a/docs/guide/connector.md b/docs/guide/connector.md index 470b862..c30d852 100644 --- a/docs/guide/connector.md +++ b/docs/guide/connector.md @@ -16,8 +16,8 @@ use rtiddsconnector::{self, Connector}; ## Creating a connector -Create a connector with [`crate::Connector::new`], passing the namespaced -participant name and the XML file path: +To create a connector, pass an XML file and a configuration name to +[`crate::Connector::new`]: ```rust use rtiddsconnector::Connector; @@ -41,34 +41,30 @@ loads a `` from a ``. For exampl See a complete example in `examples/MyApplication.xml`. +> **Note:** Operations on the same `Connector` or its contained entities are not +> protected for multi-threaded access. See +> [Threading and ownership](crate::guide::threading) for guidance. + ## Closing a connector There is no explicit `close()` method in Rust. Instead, `Connector`, `Input`, and `Output` are released when they go out of scope. The crate uses RAII to free native resources. -To force cleanup of Connext global resources at the end of a scope -(for example, in tests), use [`crate::GlobalsDropGuard`]. +To force cleanup of Connext global resources at the end of a scope (for example, +in tests), use [`crate::GlobalsDropGuard`]. ## Getting inputs and outputs -[`crate::Connector::get_input`] and [`crate::Connector::get_output`] return -owned handles to the named reader/writer. The crate enforces single-threaded -ownership: if an entity is already in use, these calls return an error. To wait -until the entity becomes available, use [`crate::Connector::take_input`] or -[`crate::Connector::take_output`]. +Once you have created a connector, use [`crate::Connector::get_input`] and +[`crate::Connector::get_output`] to retrieve inputs and outputs. + +> **Note:** If the `` you load contains both `` +> and `` tags for the same topic and they have matching QoS, inputs +> may receive data before you call `get_input`. To avoid this, configure the +> `` that contains the `` with +> `//` set to +> `false`. Then inputs will only receive data after you call `get_input`. See [Publishing data](crate::guide::output) and [Reading data](crate::guide::input) for the workflow that follows. - -> **Note:** Multiple operations on the same `Connector`, or its contained -> entities, are not protected for multi-threaded access. See -> [Threading and ownership](crate::guide::threading) for guidance. - -## DataReader auto-enable considerations - -Connext DDS controls entity enablement through XML QoS settings (for example, -`/`). If readers are enabled before -you acquire an `Input`, data may already be available when you call -`get_input`. This behavior stems from your Connext configuration rather than the -Rust API itself. diff --git a/docs/guide/input.md b/docs/guide/input.md index 5b33bd1..3e6de3b 100644 --- a/docs/guide/input.md +++ b/docs/guide/input.md @@ -1,10 +1,12 @@ -# Reading data +# Reading data (Input) [`crate::Input`] wraps a DDS `DataReader` and provides an iterator-based interface over samples returned by the RTI Connector API. ## Getting the input +To read or take samples, first get a reference to the input: + ```rust use rtiddsconnector::{Connector, Input}; @@ -15,41 +17,48 @@ fn get_input(connector: &Connector) -> rtiddsconnector::ConnectorResult rtiddsconnector::ConnectorFallible { - input.take()?; - - for sample in input.into_iter().valid_only() { - println!("Sample: {}", sample); - } - - Ok(()) -} +input.take()?; ``` -`valid_only()` skips samples with invalid data. +Or call [`crate::Input::read`] to access samples but leave them available for a +future `read` or `take`: -## Waiting for data +```rust +input.read()?; +``` Use [`crate::Input::wait`] or [`crate::Input::wait_with_timeout`] to block until -data is available. These methods do not read data; call `read` or `take` -afterward. +new data is available on a specific input. These methods do not read data; call +`read` or `take` afterward. If you want to wait for data on any input owned by a connector, use [`crate::Connector::wait_for_data`] or [`crate::Connector::wait_for_data_with_timeout`]. These methods do not read samples; call `read` or `take` afterward. -## Accessing data samples +## Accessing the data samples + +After calling [`crate::Input::read`] or [`crate::Input::take`], iterate over the +samples: + +```rust +for sample in input.into_iter() { + if sample.is_valid()? { + println!("{}", sample); + } +} +``` + +To skip invalid samples, use `valid_only()`: + +```rust +for sample in input.into_iter().valid_only() { + println!("{}", sample); +} +``` `Sample` provides typed accessors and JSON access: @@ -61,7 +70,7 @@ samples; call `read` or `take` afterward. `Sample` implements `Display` to print the full JSON representation of the sample. -If you need to access meta-data fields (SampleInfo), see the next section. +If you need to access meta-data fields (SampleInfo), see [Accessing sample meta-data](#accessing-sample-meta-data). ## Returning the loan @@ -71,19 +80,36 @@ resources sooner. ## Accessing sample meta-data -Every sample includes associated meta-data (SampleInfo). You can access these -fields using [`crate::Sample::get_info`] and [`crate::Sample::get_info_json`]. +Every sample contains an associated SampleInfo with meta-data about the +sample: + +```rust +for sample in input.into_iter() { + let source_timestamp = sample.get_info("source_timestamp")?; + println!("source_timestamp: {:?}", source_timestamp); +} +``` + +See [`crate::Sample::get_info`] for the list of available meta-data fields. + +*Connext DDS* can produce samples with invalid data, which contain meta-data +only. For more information about this, see the Valid Data flag in the RTI +Connext DDS Core Libraries User's Manual: +. +These samples indicate a change in the instance state. Samples with invalid data +still provide the following information: -If a sample has invalid data, it still carries meta-data. You can detect this -with [`crate::Sample::is_valid`]. For the list of available info fields and their -meaning, refer to the RTI Connector documentation. +* The SampleInfo +* When an instance is disposed (`sample.get_info("instance_state")` is + `NOT_ALIVE_DISPOSED`), the sample data contains the value of the key that has + been disposed. You can access the key fields only. -## Matching publications +## Matching with a publication Use [`crate::Input::wait_for_publications`] or -[`crate::Input::wait_for_publications_with_timeout`] to wait for matched -writers. These methods return the change in the number of matched publications -since the last call. +[`crate::Input::wait_for_publications_with_timeout`] to detect when a +compatible publication is matched or unmatched. These methods return the change +in the number of matched publications since the last call. You can inspect the current list with [`crate::Input::display_matched_publications`], which returns JSON. diff --git a/docs/guide/output.md b/docs/guide/output.md index 62134d1..c10233a 100644 --- a/docs/guide/output.md +++ b/docs/guide/output.md @@ -1,10 +1,12 @@ -# Publishing data +# Publishing data (Output) -[`crate::Output`] wraps a DDS `DataWriter` and exposes a single mutable +[`crate::Output`] wraps a DDS DataWriter and exposes a single mutable [`crate::Instance`] representing the next sample to write. ## Getting the output +To write a data sample, first look up an output: + ```rust use rtiddsconnector::{Connector, Output}; @@ -15,7 +17,7 @@ fn get_output(connector: &Connector) -> rtiddsconnector::ConnectorResult rtiddsconnector::ConnectorFallible { } ``` -Or set the entire sample from JSON: +Or using JSON: ```rust use rtiddsconnector::Output; @@ -58,7 +60,8 @@ Field names correspond to the type assigned to the output in XML. For example: ## Writing the data sample -To write the values set in the instance, call [`crate::Output::write`]: +To write the values that have been set in the instance, call +[`crate::Output::write`]: ```rust use rtiddsconnector::Output; @@ -68,7 +71,7 @@ fn write_once(output: &mut Output) -> rtiddsconnector::ConnectorFallible { } ``` -If the DataWriter QoS is reliable, use [`crate::Output::wait`] or +If the DataWriter QoS is reliable, you can use [`crate::Output::wait`] or [`crate::Output::wait_with_timeout`] to wait for acknowledgments: ```rust @@ -80,8 +83,8 @@ fn write_and_wait(output: &mut Output) -> rtiddsconnector::ConnectorFallible { } ``` -To write with parameters such as a source timestamp, use -[`crate::WriteParams`] and [`crate::Output::write_with_params`]: +To write with parameters such as a source timestamp, use [`crate::WriteParams`] +with [`crate::Output::write_with_params`]: ```rust use rtiddsconnector::{Output, WriteParams}; @@ -92,7 +95,7 @@ fn write_with_timestamp(output: &mut Output, ts: i64) -> rtiddsconnector::Connec } ``` -You can also dispose or unregister an instance: +It is also possible to dispose or unregister an instance: ```rust use rtiddsconnector::{Output, WriteParams}; @@ -103,14 +106,14 @@ fn dispose_instance(output: &mut Output) -> rtiddsconnector::ConnectorFallible { } ``` -In these cases, only the key fields are relevant. +In these two cases, only the key fields are relevant. ## Matching with a subscription Use [`crate::Output::wait_for_subscriptions`] or -[`crate::Output::wait_for_subscriptions_with_timeout`] to detect matched or -unmatched subscriptions. These methods return the change in the number of -matches since the last call. +[`crate::Output::wait_for_subscriptions_with_timeout`] to detect when a +compatible subscription is matched or unmatched. These methods return the +change in the number of matches since the last call. You can inspect the current list of matched subscriptions as JSON with [`crate::Output::display_matched_subscriptions`]. diff --git a/docs/guide/threading.md b/docs/guide/threading.md index 69de934..e97d2ae 100644 --- a/docs/guide/threading.md +++ b/docs/guide/threading.md @@ -6,12 +6,14 @@ ownership of `Input` and `Output` handles. ## Ownership rules +Use the following ownership rules: + * `Connector::get_input` and `Connector::get_output` return exclusive handles. * If an entity is already owned by another thread, you will receive an error. * Use `Connector::take_input` and `Connector::take_output` to block until the entity is free. -## Practical guidance +## Practical guidance about threading Keep each `Input` or `Output` on a single thread at a time. If you need to share work, consider a worker thread that owns the handle and communicates via From 501c0972355262bb34ea071bb8de6af0e2c0994e Mon Sep 17 00:00:00 2001 From: Alex Campos Date: Wed, 14 Jan 2026 13:59:36 -0800 Subject: [PATCH 6/7] Revert internal .md files --- docs/connector.md | 33 ++------------------------------- docs/input.md | 45 +++++---------------------------------------- docs/output.md | 36 ++++-------------------------------- docs/result.md | 26 +++++++++----------------- 4 files changed, 20 insertions(+), 120 deletions(-) diff --git a/docs/connector.md b/docs/connector.md index 57b328f..04c4006 100644 --- a/docs/connector.md +++ b/docs/connector.md @@ -1,33 +1,4 @@ # Connector and related utilities -The [`Connector`] type is the entry point to the RTI Connector for Rust API. -It wraps a DDS `DomainParticipant` configured from an XML file and is used -to acquire [`Input`] and [`Output`] handles for reading and writing data. - -## Typical flow - -1. Create a `Connector` with [`Connector::new`], passing a participant name and - the path to an XML configuration file. -2. Acquire an [`Input`] or [`Output`] with [`Connector::get_input`] and - [`Connector::get_output`]. -3. Use the `Input`/`Output` APIs to read or write samples. - -```text -let connector = Connector::new("MyLibrary::MyParticipant", "/path/to/App.xml")?; -let input = connector.get_input("MySubscriber::MyReader")?; -let output = connector.get_output("MyPublisher::MyWriter")?; -``` - -## Ownership and blocking acquisition - -`Connector` enforces thread-aware ownership for `Input` and `Output` instances. -If a named entity is already in use, [`Connector::get_input`] and -[`Connector::get_output`] will return an error. Use [`Connector::take_input`] -or [`Connector::take_output`] to wait until the entity becomes available. - -## Waiting for data - -You can wait for any `Input` owned by the connector to receive data using -[`Connector::wait_for_data`] or [`Connector::wait_for_data_with_timeout`]. -These calls do not read data; you still need to call [`Input::read`] or -[`Input::take`] on the specific `Input` you want to process. +This module contains everything related to the [`Connector`] abstraction, +including methods to create [`Input`] and [`Output`] objects. diff --git a/docs/input.md b/docs/input.md index e02b5e0..5656bc9 100644 --- a/docs/input.md +++ b/docs/input.md @@ -1,43 +1,8 @@ -# Input, Sample, and related utilities +# Input, Sample and related utilities -The [`Input`] interface is used to read data samples from DDS topics. It wraps a -`DataReader` configured in your XML file and provides a cached view of samples -retrieved by [`Input::read`] or [`Input::take`]. +The [`Input`] interface is used to read data samples from DDS topics. -## Reading data +The [`Sample`] interface represents a data sample read from an [`Input`]. -Use [`Input::read`] to fill the local sample cache without removing samples from -DDS, or [`Input::take`] to remove them from the reader. After either call, iterate -samples using `for sample in input.into_iter()` or filter valid samples with -[`ValidSampleIterator`]: - -```text -input.take()?; - -for sample in input.into_iter().valid_only() { - println!("Sample: {}", sample); -} -``` - -If you call `take`, you can return the loan with [`Input::return_loan`] after you -finish processing. - -## Waiting for data - -To block until data is available, use [`Input::wait`] or -[`Input::wait_with_timeout`]. These calls do not read data; they only wait for -availability. You still need to call `read` or `take` to populate the cache. - -## Accessing fields - -A [`Sample`] provides typed accessors like [`Sample::get_number`], -[`Sample::get_string`], and [`Sample::get_boolean`]. For dynamic access, use -[`Sample::get_value`] which returns a [`SelectedValue`], or get a JSON string -using [`Sample::get_value_json`]. You can also access sample info fields via -[`Sample::get_info`] and [`Sample::get_info_json`]. - -## Matched publications - -Use [`Input::wait_for_publications`] or [`Input::wait_for_publications_with_timeout`] -to wait for writers, and [`Input::display_matched_publications`] to retrieve the -matched publications as JSON. +The [`SampleIterator`] interface provides an iterator over valid samples +read from an [`Input`]. diff --git a/docs/output.md b/docs/output.md index 676a816..39ef0de 100644 --- a/docs/output.md +++ b/docs/output.md @@ -1,34 +1,6 @@ -# Output, Instance, and related utilities +# Output, Instance and related utilities -The [`Output`] interface is used to write data out to a DDS domain. It wraps a -`DataWriter` configured in your XML file and exposes a single writable -[`Instance`] that represents the next sample to be published. +The [`Output`] interface is used to write data out to a DDS domain. -## Writing data - -Modify the instance with `set_*` methods or JSON, then publish it using -[`Output::write`]: - -```text -let mut instance = output.instance(); -instance.set_string("color", "BLUE")?; -instance.set_number("x", 100.0)?; -instance.set_number("y", 150.0)?; - -output.write()?; -``` - -For typed data, use [`Instance::serialize`] to serialize a struct via Serde. - -## Write parameters - -Use [`Output::write_with_params`] and [`WriteParams`] to control actions like -`dispose` or `unregister`, or to attach timestamps and identities. - -## Waiting and matching - -You can wait for acknowledgments with [`Output::wait`] or -[`Output::wait_with_timeout`], and you can wait for subscriptions with -[`Output::wait_for_subscriptions`] or [`Output::wait_for_subscriptions_with_timeout`]. -Use [`Output::display_matched_subscriptions`] to retrieve matched subscriptions -as JSON. +The [`Instance`] interface is used to manipulate the data to be sent, +and can be accessed by means of [`Output::instance`]. diff --git a/docs/result.md b/docs/result.md index 3dfab08..351f251 100644 --- a/docs/result.md +++ b/docs/result.md @@ -1,20 +1,12 @@ -# Result types for error handling +# Result types for Error Handling -The `rtiddsconnector` API uses a small set of result types: +The [`ConnectorError`] enum represents possible errors that can occur +when using the Connector API. -* [`ConnectorResult`]: the standard result type for fallible operations. -* [`ConnectorFallible`]: a convenience alias for `Result<(), ConnectorError>`. -* [`ConnectorError`]: the error type used throughout the crate. +The [`ConnectorResult`] type alias is used throughout the crate +to represent operations that can succeed or fail with a +[`ConnectorError`]. -## Inspecting errors - -`ConnectorError` exposes helper methods to classify errors: - -* [`ConnectorError::is_timeout`] -* [`ConnectorError::is_entity_not_found`] -* [`ConnectorError::is_field_not_found`] -* [`ConnectorError::is_native_error`] -* [`ConnectorError::last_error_message`] - -These helpers allow you to handle common cases without depending on internal -error kinds. +The [`ConnectorFallible`] type alias is used for operations +that can can fail with [`ConnectorError`] but that doesn't have a +meaningful return value (it is `()`). From ed4c211fa3ae7b1075f554eb9a3b75ebac52b494 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20N=C3=BA=C3=B1ez?= Date: Mon, 19 Jan 2026 10:39:07 +0100 Subject: [PATCH 7/7] Add information to valid info fields --- src/input.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/input.rs b/src/input.rs index aa66807..6f681bd 100644 --- a/src/input.rs +++ b/src/input.rs @@ -21,6 +21,18 @@ use crate::{ /// ```rust #[doc = include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/snippets/input/using_sample.rs"))] /// ``` +/// +/// In addition to the data itself, each instance contains metadata which can be +/// accessed with [`Sample::get_info`] and related methods. +/// The list of available info fields include, but is not limited to: +/// +/// - `valid_data`: A boolean indicating whether the sample contains valid data. +/// - `source_timestamp`: A string representing the source timestamp of the sample. +/// - `reception_timestamp`: A string representing the reception timestamp of the sample. +/// - `instance_state`: A string representing the instance state of the sample. +/// - `view_state`: A string representing the view state of the sample. +/// - `sample_state`: A string representing the sample state of the sample. +/// - `identity`: A string representing the identity of the sample publisher. #[derive(Debug)] pub struct Sample<'a> { /// The index of the sample within the [`Input`]'s samples cache.