Skip to content

Rust::com Field APIs design and example of usage - #700

Open
bharatGoswami8 wants to merge 11 commits into
eclipse-score:mainfrom
bharatGoswami8:Rust_Field_APIs_Desing_and_Example
Open

Rust::com Field APIs design and example of usage#700
bharatGoswami8 wants to merge 11 commits into
eclipse-score:mainfrom
bharatGoswami8:Rust_Field_APIs_Desing_and_Example

Conversation

@bharatGoswami8

Copy link
Copy Markdown
Contributor
  • Added field-based publish/subscribe with field get/set and asynchronous field subscriptions.
  • Extended interface macros to support field members and generated producer/consumer and compile-time offer API enable.
  • Added a new example demonstrating offered field producers and consumer field updates.

#579

* Created field interface APIs
* Updated SampleMut to use in field as well
* Added field related files on build target
* Created impl block in Lola Runtime for field Producer and Consumer trait
* Mock Runtime impl block added for field APIs
* Updated Interface macro to generate field related types and APIs
* Create proc macro for field init and set handler validation before offer call
* Updated Runtime GATs for field public types
* Updated Runtime implementation
* Updated example file with Field APIs usage
/// "left_tire" and "exhaust" events.
/// - `VehicleOfferedProducer<R>` struct that implements `OfferedProducer` trait for offering
/// "left_tire" and "exhaust" events.
// TODO: We need to enable the support for mixed types (Event, Method, Field) in the same interface definition.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ticket for same - #701

* Updated the TODOs and documentation
@bharatGoswami8
bharatGoswami8 force-pushed the Rust_Field_APIs_Desing_and_Example branch 2 times, most recently from 6921668 to 6faaa6c Compare July 14, 2026 06:11
* Clone bound removed from fieldPublisher trait and impl block
@bharatGoswami8
bharatGoswami8 force-pushed the Rust_Field_APIs_Desing_and_Example branch from 6faaa6c to 21d958d Compare July 14, 2026 06:23
* Producer trait offer API limitation added to avoid direct use
@bharatGoswami8
bharatGoswami8 force-pushed the Rust_Field_APIs_Desing_and_Example branch from 30e0af1 to 8589c65 Compare July 19, 2026 08:53
@anmittag anmittag moved this from Backlog to In Progress in COM - Communication FT Jul 21, 2026
Comment on lines +191 to +195
// Below function just demonstrate the field APIs usage
// This build fine but it can not run because we have not implemented the field APIs in Lola runtime yet.

// Producer creation and intialization of fields with initial values and set handlers for the fields
// It will return the offered producer instance which can be used to update the fields.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// Below function just demonstrate the field APIs usage
// This build fine but it can not run because we have not implemented the field APIs in Lola runtime yet.
// Producer creation and intialization of fields with initial values and set handlers for the fields
// It will return the offered producer instance which can be used to update the fields.
// Below function demonstrate the field APIs usage
// This builds fine, but it cannot run as the field APIs in Lola runtime are not implemented yet.
// Producer creation and intialization of fields with initial values and set handlers for the fields
// It will return the offered producer instance which can be used to update the fields.

// TODO: in working example add that logic to demonstrate the set handler usage.
// Note: I think producer may be need clone ?
})
.expect("Failed to register set handlers")

@rpreddyhv rpreddyhv Jul 20, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why would register_* ever fail? As discussed for Method, it shouldn't return Result.

.register_set_handler_left_tire(move |val: &Tire| {
println!("Received tire pressure update: {:?}", val);
// Additional logic to handle the tire pressure update can be added here
// For example, we can increment value or conver unit and update the field again.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// For example, we can increment value or conver unit and update the field again.
// For example, we can increment value or convert unit and update the field again.

@darkwisebear darkwisebear left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mainly reviewed the concept part; I think we need to nail that part before it makes sense to look at the rest.

* SPDX-License-Identifier: Apache-2.0
********************************************************************************/

#![allow(unused)]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please put this to the specific places and do not globally turn it on for the module.

// Must register handlers and initialize all fields before offer() is available
let offered = producer
.init_field()
.register_set_handler_left_tire(move |val: &Tire| {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder whether &Tire is correct. Why not hand over ownership to the callable? This way, the implementer wouldn't have to clone the value in the likely case the value is written somewhere.

println!("Received exhaust update");
})
.expect("Failed to register set handlers")
.update_left_tire(&initial_tire_value)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why by-reference? This forces cloning as the implementation most likely has to clone the value to send it across the network. It might be a corner case, though.

use std::fmt::Debug;
use std::future::Future;

#[allow(dead_code)]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this dead code?

#[allow(dead_code)]
// Temp for build test
// We will remove this once memory layout of same created in rust side like SamplePtr.
#[repr(C)]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't this trigger an "improper_ctypes" lint? Result isn't #[repr(C)], so it cannot be used here properly.

// or by default we will enable for user,
// -> we can keep it default enable as of now,
// and later we can add tag based mechanism if required because Interface side we need to check how we can do this
// 2. We are offering get method after subscrption async but before subscription it is sync,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just turn the one before subscription into async. Or is there anything that prevents you from doing so?

// we will create a module which will have common trait for event and field which will be used by both event and field as a super trait and
// for this we need to create marker trait for event.

use crate::*;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please import specific types. Yes, it's tedious, but being explicit here also saves some headaches.

/// # Returns
/// Return the result of `Result<()>` which contains the status of the register operation.
// TODO: Do we need to make callback lifetime 'static or we keep same as field publisher lifetime.
fn register_set_handler<'a>(&self, callback: impl Fn(&T) + Send + 'a) -> Result<()>;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no equivalent method for registering the get handler. It may sound weird, but the C++ counterpart has that, since mw::com treats set and get as ordinary methods.

/// # Returns
/// Return the result of `Result<()>` which contains the status of the register operation.
// TODO: Do we need to make callback lifetime 'static or we keep same as field publisher lifetime.
fn register_set_handler<'a>(&self, callback: impl Fn(&T) + Send + 'a) -> Result<()>;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TO me this feels as if we're treating ordinary methods and field methods in a distinct way. Maybe we should think about getting methods ready first and then incorporate them as the foundation of set and get here.

@@ -329,18 +342,10 @@ where
///
/// # Type Parameters
/// * `T` - The relocatable event data type
pub trait SampleMut<T>: DerefMut<Target = T> + Debug
pub trait EventSampleMut<T>: SampleMut<T>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this just because of update vs send (aka naming)?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

Status: In Progress

Development

Successfully merging this pull request may close these issues.

4 participants