From ab8a08bcf864af75f86f2e36b1a13d156835193d Mon Sep 17 00:00:00 2001 From: Piotr Chodorowski Date: Wed, 10 Dec 2025 12:26:11 +0100 Subject: [PATCH] Initial iceoryx integration --- MODULE.bazel | 2 +- score/mw/com/example/com-api-example/BUILD | 4 + .../basic-consumer-producer.rs | 8 + .../example/com-api-example/com-api-gen/BUILD | 12 +- .../com-api-gen/com_api_gen.rs | 7 + score/mw/com/flags/BUILD | 15 +- .../impl/rust/com-api/com-api-concept/BUILD | 16 +- .../com-api-concept/com_api_concept.rs | 15 + .../rust/com-api/com-api-concept/reloc.rs | 10 + .../com-api/com-api-runtime-iceoryx/BUILD | 30 + .../com-api-runtime-iceoryx/runtime.rs | 688 ++++++++++++++++++ score/mw/com/impl/rust/com-api/com-api/BUILD | 20 +- .../com/impl/rust/com-api/com-api/com_api.rs | 17 +- 13 files changed, 829 insertions(+), 15 deletions(-) create mode 100644 score/mw/com/impl/rust/com-api/com-api-runtime-iceoryx/BUILD create mode 100644 score/mw/com/impl/rust/com-api/com-api-runtime-iceoryx/runtime.rs diff --git a/MODULE.bazel b/MODULE.bazel index 847493c5f..156b0a344 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -98,7 +98,7 @@ bazel_dep(name = "score_crates", version = "0.0.4", repo_name = "crate_index") # Temporary: Use latest GitHub main with regenerated BUILD file including paste and arrayvec git_override( module_name = "score_crates", - commit = "636a5add5ffd53177fd0fdf70b672043ac2664c4", + commit = "dcbc6a4d36c9293549397893650c3a7068b0682d", remote = "https://github.com/eclipse-score/score-crates.git", ) diff --git a/score/mw/com/example/com-api-example/BUILD b/score/mw/com/example/com-api-example/BUILD index 2d646337d..b07aadf24 100644 --- a/score/mw/com/example/com-api-example/BUILD +++ b/score/mw/com/example/com-api-example/BUILD @@ -16,6 +16,10 @@ load("@rules_rust//rust:defs.bzl", "rust_binary", "rust_test") rust_binary( name = "com-api-example", srcs = ["basic-consumer-producer.rs"], + crate_features = select({ + "//score/mw/com/flags:use_iceoryx_flag": ["iceoryx"], + "//conditions:default": [], + }), visibility = ["//visibility:public"], deps = [ "//score/mw/com/example/com-api-example/com-api-gen", diff --git a/score/mw/com/example/com-api-example/basic-consumer-producer.rs b/score/mw/com/example/com-api-example/basic-consumer-producer.rs index 743bc28b0..bc7980722 100644 --- a/score/mw/com/example/com-api-example/basic-consumer-producer.rs +++ b/score/mw/com/example/com-api-example/basic-consumer-producer.rs @@ -92,6 +92,14 @@ fn run_with_runtime(name: &str, runtime: &R) { println!("=== {} runtime completed ===\n", name); } +#[cfg(feature = "iceoryx")] +fn main() { + let iceoryx_runtime_builder = IceoryxRuntimeBuilderImpl::new(); + let iceoryx_runtime = Builder::::build(iceoryx_runtime_builder).unwrap(); + run_with_runtime("Iceoryx", &iceoryx_runtime); +} + +#[cfg(not(feature = "iceoryx"))] fn main() { let mock_runtime_builder = MockRuntimeBuilderImpl::new(); let mock_runtime = Builder::::build(mock_runtime_builder).unwrap(); diff --git a/score/mw/com/example/com-api-example/com-api-gen/BUILD b/score/mw/com/example/com-api-example/com-api-gen/BUILD index 61d3ed3ab..15db5dc2c 100644 --- a/score/mw/com/example/com-api-example/com-api-gen/BUILD +++ b/score/mw/com/example/com-api-example/com-api-gen/BUILD @@ -16,10 +16,16 @@ rust_library( name = "com-api-gen", srcs = ["com_api_gen.rs"], crate_name = "com_api_gen", + crate_features = select({ + "//score/mw/com/flags:use_iceoryx_flag": ["iceoryx"], + "//conditions:default": [], + }), visibility = [ "//visibility:public", # platform_only ], - deps = [ - "//score/mw/com/impl/rust/com-api/com-api", - ], + deps = ["//score/mw/com/impl/rust/com-api/com-api",] + + select({ + "//score/mw/com/flags:use_iceoryx_flag": ["@crate_index//:iceoryx2_qnx8",], + "//conditions:default": [], + }), ) diff --git a/score/mw/com/example/com-api-example/com-api-gen/com_api_gen.rs b/score/mw/com/example/com-api-example/com-api-gen/com_api_gen.rs index de22c1e55..a4270bb41 100644 --- a/score/mw/com/example/com-api-example/com-api-gen/com_api_gen.rs +++ b/score/mw/com/example/com-api-example/com-api-gen/com_api_gen.rs @@ -10,6 +10,8 @@ * * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ +#[cfg(feature = "iceoryx")] +use iceoryx2_qnx8::prelude::ZeroCopySend; use com_api::{ Consumer, Interface, OfferedProducer, Producer, Publisher, Reloc, Runtime, Subscriber, @@ -18,11 +20,16 @@ use com_api::{ #[derive(Debug)] pub struct Tire {} unsafe impl Reloc for Tire {} +#[cfg(feature = "iceoryx")] +unsafe impl ZeroCopySend for Tire {} #[derive(Debug)] pub struct Exhaust {} unsafe impl Reloc for Exhaust {} +#[cfg(feature = "iceoryx")] +unsafe impl ZeroCopySend for Exhaust {} +#[derive(Debug)] pub struct VehicleInterface {} /// Generic diff --git a/score/mw/com/flags/BUILD b/score/mw/com/flags/BUILD index 8a47acad8..1e4258caf 100644 --- a/score/mw/com/flags/BUILD +++ b/score/mw/com/flags/BUILD @@ -11,7 +11,7 @@ # SPDX-License-Identifier: Apache-2.0 # ******************************************************************************* -load("@bazel_skylib//rules:common_settings.bzl", "string_flag") +load("@bazel_skylib//rules:common_settings.bzl", "string_flag", "bool_flag") string_flag( name = "tracing_library", @@ -37,3 +37,16 @@ config_setting( "//score/mw/com/impl/tracing:__subpackages__", ], ) + +bool_flag( + name = "use_iceoryx", + build_setting_default = False, +) + +config_setting( + name = "use_iceoryx_flag", + flag_values = { + ":use_iceoryx": "True", + }, + visibility = ["//visibility:public"], +) diff --git a/score/mw/com/impl/rust/com-api/com-api-concept/BUILD b/score/mw/com/impl/rust/com-api/com-api-concept/BUILD index 294f4893a..bb7e8054b 100644 --- a/score/mw/com/impl/rust/com-api/com-api-concept/BUILD +++ b/score/mw/com/impl/rust/com-api/com-api-concept/BUILD @@ -22,7 +22,21 @@ rust_library( visibility = [ "//visibility:public", # platform_only ], - deps = [], +) + +rust_library( + name = "com-api-concept-iceoryx", + srcs = [ + "com_api_concept.rs", + "reloc.rs", + ], + crate_features = ["iceoryx"], + crate_name = "com_api_concept", + crate_root = "com_api_concept.rs", + visibility = [ + "//visibility:public", # platform_only + ], + deps = ["@crate_index//:iceoryx2_qnx8"], ) rust_test( diff --git a/score/mw/com/impl/rust/com-api/com-api-concept/com_api_concept.rs b/score/mw/com/impl/rust/com-api/com-api-concept/com_api_concept.rs index c8078498d..8dd1c57eb 100644 --- a/score/mw/com/impl/rust/com-api/com-api-concept/com_api_concept.rs +++ b/score/mw/com/impl/rust/com-api/com-api-concept/com_api_concept.rs @@ -90,9 +90,15 @@ pub trait Builder { /// the implementation. pub trait Runtime { /// ServiceDiscovery types for Discovers available service instances of a specific interface + #[cfg(feature = "iceoryx")] + type ServiceDiscovery: ServiceDiscovery; + #[cfg(not(feature = "iceoryx"))] type ServiceDiscovery: ServiceDiscovery; /// Subscriber types for Manages subscriptions to event notifications + #[cfg(feature = "iceoryx")] + type Subscriber: Subscriber; + #[cfg(not(feature = "iceoryx"))] type Subscriber: Subscriber; /// ProducerBuilder types for Constructs producer instances for offering services @@ -103,6 +109,9 @@ pub trait Runtime { >; /// Publisher types for Publishes event data to subscribers + #[cfg(feature = "iceoryx")] + type Publisher: Publisher; + #[cfg(not(feature = "iceoryx"))] type Publisher: Publisher; /// ProviderInfo types for Configuration data for service producers instances @@ -123,6 +132,12 @@ pub trait Runtime { /// /// # Returns /// Service discovery handle for querying available instances + #[cfg(feature = "iceoryx")] + fn find_service( + &self, + instance_specifier: FindServiceSpecifier, + ) -> Self::ServiceDiscovery; + #[cfg(not(feature = "iceoryx"))] fn find_service( &self, instance_specifier: FindServiceSpecifier, diff --git a/score/mw/com/impl/rust/com-api/com-api-concept/reloc.rs b/score/mw/com/impl/rust/com-api/com-api-concept/reloc.rs index 8cbdc2b4a..84bc9c8b9 100644 --- a/score/mw/com/impl/rust/com-api/com-api-concept/reloc.rs +++ b/score/mw/com/impl/rust/com-api/com-api-concept/reloc.rs @@ -10,7 +10,12 @@ * * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ +#[cfg(feature = "iceoryx")] +use iceoryx2_qnx8::prelude::ZeroCopySend; +#[cfg(feature = "iceoryx")] +pub unsafe trait Reloc: ZeroCopySend {} +#[cfg(not(feature = "iceoryx"))] pub unsafe trait Reloc {} unsafe impl Reloc for () {} @@ -38,8 +43,13 @@ unsafe impl Reloc for [T; N] {} unsafe impl Reloc for core::mem::MaybeUninit {} // Tuples (up to 5 elements) +#[cfg(not(feature = "iceoryx"))] unsafe impl Reloc for (T1,) {} +#[cfg(not(feature = "iceoryx"))] unsafe impl Reloc for (T1, T2) {} +#[cfg(not(feature = "iceoryx"))] unsafe impl Reloc for (T1, T2, T3) {} +#[cfg(not(feature = "iceoryx"))] unsafe impl Reloc for (T1, T2, T3, T4) {} +#[cfg(not(feature = "iceoryx"))] unsafe impl Reloc for (T1, T2, T3, T4, T5) {} diff --git a/score/mw/com/impl/rust/com-api/com-api-runtime-iceoryx/BUILD b/score/mw/com/impl/rust/com-api/com-api-runtime-iceoryx/BUILD new file mode 100644 index 000000000..2a07cbb6d --- /dev/null +++ b/score/mw/com/impl/rust/com-api/com-api-runtime-iceoryx/BUILD @@ -0,0 +1,30 @@ +# ******************************************************************************* +# Copyright (c) 2025 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0 +# +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* +load("@rules_rust//rust:defs.bzl", "rust_library") + +rust_library( + name = "com-api-runtime-iceoryx", + srcs = ["runtime.rs"], + crate_features = select({ + "//score/mw/com/flags:use_iceoryx_flag": ["iceoryx"], + "//conditions:default": [], + }), + visibility = [ + "//visibility:public", # platform_only + ], + deps = [ + "//score/mw/com/impl/rust/com-api/com-api-concept:com-api-concept-iceoryx", + "@crate_index//:futures", + "@crate_index//:iceoryx2_qnx8", + ], +) diff --git a/score/mw/com/impl/rust/com-api/com-api-runtime-iceoryx/runtime.rs b/score/mw/com/impl/rust/com-api/com-api-runtime-iceoryx/runtime.rs new file mode 100644 index 000000000..6582fbdfd --- /dev/null +++ b/score/mw/com/impl/rust/com-api/com-api-runtime-iceoryx/runtime.rs @@ -0,0 +1,688 @@ +/******************************************************************************** + * Copyright (c) 2025 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0 + * + * SPDX-License-Identifier: Apache-2.0 + ********************************************************************************/ + +//! This crate provides a Iceoryx implementation of the COM API. +//! It is meant to be used in conjunction with the `com-api` crate. + +#![allow(dead_code)] + +use com_api_concept::Reloc; +use core::cmp::Ordering; +use core::fmt::Debug; +use core::future::Future; +use core::marker::PhantomData; +use core::mem::MaybeUninit; +use core::ops::{Deref, DerefMut}; +use core::sync::atomic::AtomicUsize; +use iceoryx2_qnx8::prelude::*; +use std::collections::HashSet; +use std::collections::VecDeque; +use std::path::Path; +use std::sync::Arc; + +use com_api_concept::{ + Builder, Consumer, ConsumerBuilder, ConsumerDescriptor, FindServiceSpecifier, + InstanceSpecifier, Interface, Producer, ProducerBuilder, Result, Runtime, SampleContainer, + ServiceDiscovery, Subscriber, Subscription, +}; + +pub struct IceoryxRuntimeImpl { + node: Arc>, +} + +// Note: ProviderInfo is currently unused but will be utilized +// with the Producer::offer() method in future implementations. +#[derive(Clone)] +pub struct IceoryxProviderInfo { + instance_specifier: InstanceSpecifier, + node: Arc>, +} + +#[derive(Clone)] +pub struct IceoryxConsumerInfo { + instance_specifier: InstanceSpecifier, + node: Arc>, +} + +impl Runtime for IceoryxRuntimeImpl { + type ServiceDiscovery = SampleConsumerDiscovery; + type Subscriber = SubscribableImpl; + type ProducerBuilder> = SampleProducerBuilder; + type Publisher = Publisher; + type ProviderInfo = IceoryxProviderInfo; + type ConsumerInfo = IceoryxConsumerInfo; + + fn find_service( + &self, + instance_specifier: FindServiceSpecifier, + ) -> Self::ServiceDiscovery { + SampleConsumerDiscovery { + instance_specifier: instance_specifier, + _interface: PhantomData, + node: Arc::clone(&self.node), + } + } + + fn producer_builder>( + &self, + instance_specifier: InstanceSpecifier, + ) -> Self::ProducerBuilder { + SampleProducerBuilder::new(self, instance_specifier) + } +} + +#[derive(Debug)] +struct IceoryxEvent { + event: PhantomData, +} + +#[derive(Debug)] +struct IceoryxBinding<'a, T> +where + T: Send + Reloc + Debug + ZeroCopySend, +{ + data: iceoryx2_qnx8::sample::Sample, + event: &'a IceoryxEvent, +} + +unsafe impl<'a, T> Send for IceoryxBinding<'a, T> where T: Send + Reloc + Debug + ZeroCopySend {} + +#[derive(Debug)] +enum SampleBinding<'a, T> +where + T: Send + Reloc + Debug + ZeroCopySend, +{ + Iceoryx(IceoryxBinding<'a, T>), + Test(Box), +} + +#[derive(Debug)] +pub struct Sample<'a, T> +where + T: Reloc + Send + Debug + ZeroCopySend, +{ + id: usize, + inner: SampleBinding<'a, T>, +} + +static ID_COUNTER: AtomicUsize = AtomicUsize::new(0); + +impl<'a, T> From for Sample<'a, T> +where + T: Reloc + Send + Debug + ZeroCopySend, +{ + fn from(value: T) -> Self { + Self { + id: ID_COUNTER.fetch_add(1, core::sync::atomic::Ordering::Relaxed), + inner: SampleBinding::Test(Box::new(value)), + } + } +} + +impl<'a, T> Deref for Sample<'a, T> +where + T: Reloc + Send + Debug + ZeroCopySend, +{ + type Target = T; + + fn deref(&self) -> &Self::Target { + match &self.inner { + SampleBinding::Iceoryx(_iceoryx) => _iceoryx.data.payload(), + SampleBinding::Test(test) => test.as_ref(), + } + } +} + +impl<'a, T> com_api_concept::Sample for Sample<'a, T> where T: Send + Reloc + Debug + ZeroCopySend +{} + +impl<'a, T> PartialEq for Sample<'a, T> +where + T: Send + Reloc + Debug + ZeroCopySend, +{ + fn eq(&self, other: &Self) -> bool { + self.id == other.id + } +} + +impl<'a, T> Eq for Sample<'a, T> where T: Send + Reloc + Debug + ZeroCopySend {} + +impl<'a, T> PartialOrd for Sample<'a, T> +where + T: Send + Reloc + Debug + ZeroCopySend, +{ + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +impl<'a, T> Ord for Sample<'a, T> +where + T: Send + Reloc + Debug + ZeroCopySend, +{ + fn cmp(&self, other: &Self) -> Ordering { + self.id.cmp(&other.id) + } +} + +#[derive(Debug)] +pub struct SampleMut<'a, T> +where + T: Reloc + Debug + ZeroCopySend, +{ + data: iceoryx2_qnx8::sample_mut::SampleMut, + lifetime: PhantomData<&'a T>, +} + +impl<'a, T> com_api_concept::SampleMut for SampleMut<'a, T> +where + T: Reloc + Send + Debug + ZeroCopySend, +{ + type Sample = Sample<'a, T>; + + fn into_sample(self) -> Self::Sample { + todo!() + } + + fn send(self) -> com_api_concept::Result<()> { + let return_value = self.data.send(); + match return_value { + Err(e) => panic!("Failed to send data {e}"), + Ok(_subscriber_ok) => Ok(()), + } + } +} + +impl<'a, T> Deref for SampleMut<'a, T> +where + T: Reloc + Debug + ZeroCopySend, +{ + type Target = T; + + fn deref(&self) -> &Self::Target { + &self.data + } +} + +impl<'a, T> DerefMut for SampleMut<'a, T> +where + T: Reloc + Debug + ZeroCopySend, +{ + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.data + } +} + +pub struct SampleMaybeUninit<'a, T> +where + T: Reloc + Send + ZeroCopySend, +{ + data: iceoryx2_qnx8::sample_mut_uninit::SampleMutUninit< + ipc_threadsafe::Service, + MaybeUninit, + (), + >, + lifetime: PhantomData<&'a T>, +} + +impl<'a, T> Debug for SampleMaybeUninit<'a, T> +where + T: Reloc + Send + ZeroCopySend, +{ + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "SampleMaybeUninit") + } +} + +impl<'a, T> com_api_concept::SampleMaybeUninit for SampleMaybeUninit<'a, T> +where + T: Reloc + Send + Debug + ZeroCopySend, +{ + type SampleMut = SampleMut<'a, T>; + + fn write(self, val: T) -> SampleMut<'a, T> { + SampleMut { + data: self.data.write_payload(val), + lifetime: PhantomData, + } + } + + unsafe fn assume_init(self) -> SampleMut<'a, T> { + SampleMut { + data: unsafe { self.data.assume_init() }, + lifetime: PhantomData, + } + } +} + +impl<'a, T> AsMut> for SampleMaybeUninit<'a, T> +where + T: Reloc + Send + Debug, +{ + fn as_mut(&mut self) -> &mut core::mem::MaybeUninit { + todo!() + //&mut self.data + } +} + +pub struct SubscribableImpl { + identifier: String, + instance_info: Option, + data: PhantomData, + service: Option< + Arc< + iceoryx2_qnx8::service::port_factory::publish_subscribe::PortFactory< + ipc_threadsafe::Service, + T, + (), + >, + >, + >, +} + +impl Default for SubscribableImpl { + fn default() -> Self { + Self { + identifier: String::new(), + instance_info: None, + data: PhantomData, + service: None, + } + } +} + +impl Subscriber + for SubscribableImpl +{ + type Subscription = SubscriberImpl; + fn new(identifier: &str, instance_info: IceoryxConsumerInfo) -> com_api_concept::Result { + let specifier = instance_info.instance_specifier.as_ref(); + let service_name = format!("{}/{}", specifier, identifier); + let service_name_iceoryx_result = ServiceName::new(service_name.as_str()); + let service_name_iceoryx = match service_name_iceoryx_result { + Err(e) => { + println!("Failed to create service name: {e}"); + return Err(com_api_concept::Error::SubscribeFailed); + } + Ok(name) => name, + }; + println!("Creating subscriber for service name: {}", service_name); + let service_result = instance_info + .node + .service_builder(&service_name_iceoryx) + .publish_subscribe::() + .open(); + match service_result { + Err(e) => { + println!("Failed to create subscriber: {e}"); + return Err(com_api_concept::Error::SubscribeFailed); + } + Ok(service) => { + return Ok(Self { + identifier: identifier.to_string(), + instance_info: Some(instance_info), + data: PhantomData, + service: Some(Arc::new(service)), + }); + } + } + } + fn subscribe(&self, _max_num_samples: usize) -> com_api_concept::Result { + println!("Subscribing to service: {}", self.identifier.as_str()); + match &self.service { + None => return Err(com_api_concept::Error::SubscribeFailed), + Some(service) => return Ok(SubscriberImpl::new(Arc::clone(service))), + } + } +} + +pub struct SubscriberImpl +where + T: Reloc + Send + Debug + ZeroCopySend, +{ + data: VecDeque, + subscriber: iceoryx2_qnx8::port::subscriber::Subscriber, +} + +impl SubscriberImpl +where + T: Reloc + Send + Debug + ZeroCopySend, +{ + pub fn new( + service: Arc< + iceoryx2_qnx8::service::port_factory::publish_subscribe::PortFactory< + ipc_threadsafe::Service, + T, + (), + >, + >, + ) -> Self { + let subscriber = service.subscriber_builder().create(); + match subscriber { + Err(e) => panic!("Failed to create subscriber: {e}"), + Ok(subscriber_ok) => { + return Self { + data: Default::default(), + subscriber: subscriber_ok, + }; + } + } + } + + pub fn add_data(&mut self, data: T) { + self.data.push_front(data); + } +} + +impl Subscription for SubscriberImpl +where + T: Reloc + Send + Debug + ZeroCopySend, +{ + type Subscriber = SubscribableImpl; + type Sample<'a> + = Sample<'a, T> + where + T: 'a; + + fn unsubscribe(self) -> Self::Subscriber { + Default::default() + } + + fn try_receive<'a>( + &'a self, + _scratch: &'_ mut SampleContainer>, + _max_samples: usize, + ) -> com_api_concept::Result { + let _result = self.subscriber.receive(); + match _result { + Ok(option) => match option { + Some(sample) => { + let _res = _scratch.push_back(Sample { + id: ID_COUNTER.fetch_add(1, std::sync::atomic::Ordering::Relaxed), + inner: SampleBinding::Iceoryx(IceoryxBinding { + data: sample, + event: &IceoryxEvent { event: PhantomData }, + }), + }); + return Ok(1); + } + None => return Ok(0), + }, + Err(_e) => Err(com_api_concept::Error::Fail), + } + } + + #[allow(clippy::manual_async_fn)] + fn receive<'a>( + &'a self, + _scratch: &'_ mut SampleContainer>, + _new_samples: usize, + _max_samples: usize, + ) -> impl Future> + Send { + async { todo!() } + } +} + +pub struct Publisher { + _data: PhantomData, + publisher: iceoryx2_qnx8::port::publisher::Publisher, +} + +// impl Default for Publisher +// where +// T: Reloc + Send, +// { +// fn default() -> Self { +// Self::new() +// } +// } + +impl Publisher where T: Reloc + Send {} + +impl com_api_concept::Publisher for Publisher +where + T: Reloc + Send + Debug, +{ + type SampleMaybeUninit<'a> + = SampleMaybeUninit<'a, T> + where + Self: 'a; + + fn new(identifier: &str, instance_info: IceoryxProviderInfo) -> com_api_concept::Result { + let specifier = instance_info.instance_specifier.as_ref(); + let service_name = format!("{}/{}", specifier, identifier); + let service_name_iceoryx_result = ServiceName::new(service_name.as_str()); + let service_name_iceoryx = match service_name_iceoryx_result { + Err(e) => { + println!("Failed to create service name: {e}"); + return Err(com_api_concept::Error::SubscribeFailed); + } + Ok(name) => name, + }; + println!("Creating publisher for service name: {}", service_name); + let service_result = instance_info + .node + .service_builder(&service_name_iceoryx) + .publish_subscribe::() + .create(); + match service_result { + Err(e) => { + println!("Failed to create publisher: {e}"); + return Err(com_api_concept::Error::Fail); + } + Ok(service) => { + let publisher_result = service.publisher_builder().create(); + match publisher_result { + Err(e) => { + println!("Failed to create publisher: {e}"); + return Err(com_api_concept::Error::Fail); + } + Ok(publisher) => { + return Ok(Self { + _data: PhantomData, + publisher: publisher, + }); + } + } + } + } + } + + fn allocate<'a>(&'a self) -> com_api_concept::Result> { + let data_result = self.publisher.loan_uninit(); + match data_result { + Err(_e) => return Err(com_api_concept::Error::AllocateFailed), + Ok(data_result_ok) => { + return Ok(SampleMaybeUninit { + data: data_result_ok, + lifetime: PhantomData, + }); + } + } + } +} + +pub struct SampleConsumerDiscovery { + pub instance_specifier: FindServiceSpecifier, + _interface: PhantomData, + node: Arc>, +} + +impl SampleConsumerDiscovery { + fn new(_runtime: &IceoryxRuntimeImpl, _instance_specifier: FindServiceSpecifier) -> Self { + Self { + instance_specifier: _instance_specifier, + _interface: PhantomData, + node: Arc::clone(&_runtime.node), + } + } +} + +impl ServiceDiscovery for SampleConsumerDiscovery +where + SampleConsumerBuilder: ConsumerBuilder, +{ + type ConsumerBuilder = SampleConsumerBuilder; + type ServiceEnumerator = Vec>; + + fn get_available_instances(&self) -> com_api_concept::Result { + let mut result: Vec> = Vec::new(); + let mut result_temp: HashSet = HashSet::new(); + + let _ = ipc::Service::list(Config::global_config(), |service| { + let mut service_name = service.static_details.name().to_string(); + let pos = service_name.rfind('/').unwrap_or(0); + if pos > 0 { + service_name = service_name.split_at(pos).0.to_string(); + } + match self.instance_specifier { + FindServiceSpecifier::Specific(ref s) => { + match service_name.cmp(&s.as_ref().to_string()) { + Ordering::Equal => { + result_temp.insert(service_name); + CallbackProgression::Stop + } + _ => CallbackProgression::Continue, + } + } + FindServiceSpecifier::Any => { + result_temp.insert(service_name); + CallbackProgression::Continue + } + } + }); + + result_temp.iter().for_each(|service_name| { + result.push(SampleConsumerBuilder { + instance_specifier: InstanceSpecifier::new(service_name).unwrap(), + _interface: PhantomData, + node: Arc::clone(&self.node), + }); + }); + + Ok(result) + } + + #[allow(clippy::manual_async_fn)] + fn get_available_instances_async( + &self, + ) -> impl Future> { + async { Ok(Vec::new()) } + } +} + +pub struct SampleProducerBuilder { + instance_specifier: InstanceSpecifier, + _interface: PhantomData, + pub node: Arc>, +} + +impl SampleProducerBuilder { + fn new(_runtime: &IceoryxRuntimeImpl, instance_specifier: InstanceSpecifier) -> Self { + Self { + instance_specifier, + _interface: PhantomData, + node: Arc::clone(&_runtime.node), + } + } +} + +impl> + ProducerBuilder for SampleProducerBuilder +{ +} + +impl> Builder

+ for SampleProducerBuilder +{ + fn build(self) -> Result

{ + let instance_info = IceoryxProviderInfo { + instance_specifier: self.instance_specifier.clone(), + node: Arc::clone(&self.node), + }; + return P::new(instance_info); + } +} + +pub struct SampleConsumerDescriptor { + _interface: PhantomData, +} + +impl Clone for SampleConsumerDescriptor { + fn clone(&self) -> Self { + Self { + _interface: PhantomData, + } + } +} + +pub struct SampleConsumerBuilder { + instance_specifier: InstanceSpecifier, + _interface: PhantomData, + pub node: Arc>, +} + +impl ConsumerDescriptor for SampleConsumerBuilder { + fn get_instance_identifier(&self) -> &InstanceSpecifier { + println!( + "Getting instance identifier: {}", + self.instance_specifier.as_ref().to_string() + ); + &self.instance_specifier + } +} + +impl ConsumerBuilder for SampleConsumerBuilder {} + +impl Builder> for SampleConsumerBuilder { + fn build(self) -> com_api_concept::Result> { + let instance_info = IceoryxConsumerInfo { + instance_specifier: self.instance_specifier.clone(), + node: Arc::clone(&self.node), + }; + + Ok(I::Consumer::new(instance_info)) + } +} + +pub struct RuntimeBuilderImpl {} + +impl Builder for RuntimeBuilderImpl { + fn build(self) -> com_api_concept::Result { + let node = NodeBuilder::new().create::(); + match node { + Ok(n) => Ok(IceoryxRuntimeImpl { node: Arc::new(n) }), + Err(_e) => Err(com_api_concept::Error::Fail), + } + } +} + +/// Entry point for the default implementation for the com module of s-core +impl com_api_concept::RuntimeBuilder for RuntimeBuilderImpl { + fn load_config(&mut self, _config: &Path) -> &mut Self { + self + } +} + +impl Default for RuntimeBuilderImpl { + fn default() -> Self { + Self::new() + } +} + +impl RuntimeBuilderImpl { + /// Creates a new instance of the default implementation for the com module of s-core + pub fn new() -> Self { + Self {} + } +} diff --git a/score/mw/com/impl/rust/com-api/com-api/BUILD b/score/mw/com/impl/rust/com-api/com-api/BUILD index 867378f48..7716346b0 100644 --- a/score/mw/com/impl/rust/com-api/com-api/BUILD +++ b/score/mw/com/impl/rust/com-api/com-api/BUILD @@ -16,13 +16,23 @@ load("@rules_rust//rust:defs.bzl", "rust_library") rust_library( name = "com-api", srcs = ["com_api.rs"], + crate_features = select({ + "//score/mw/com/flags:use_iceoryx_flag": ["iceoryx"], + "//conditions:default": [], + }), crate_name = "com_api", visibility = [ "//visibility:public", # platform_only ], - deps = [ - "//score/mw/com/impl/rust/com-api/com-api-concept", - "//score/mw/com/impl/rust/com-api/com-api-runtime-lola", - "//score/mw/com/impl/rust/com-api/com-api-runtime-mock", - ], + deps = select({ + "//score/mw/com/flags:use_iceoryx_flag": [ + "//score/mw/com/impl/rust/com-api/com-api-concept:com-api-concept-iceoryx", + "//score/mw/com/impl/rust/com-api/com-api-runtime-iceoryx", + ], + "//conditions:default": [ + "//score/mw/com/impl/rust/com-api/com-api-concept", + "//score/mw/com/impl/rust/com-api/com-api-runtime-lola", + "//score/mw/com/impl/rust/com-api/com-api-runtime-mock", + ], + }), ) diff --git a/score/mw/com/impl/rust/com-api/com-api/com_api.rs b/score/mw/com/impl/rust/com-api/com-api/com_api.rs index 8ef96c839..04b27d539 100644 --- a/score/mw/com/impl/rust/com-api/com-api/com_api.rs +++ b/score/mw/com/impl/rust/com-api/com-api/com_api.rs @@ -11,10 +11,19 @@ * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ -pub use com_api_runtime_lola::LolaRuntimeImpl; -pub use com_api_runtime_lola::RuntimeBuilderImpl as LolaRuntimeBuilderImpl; -pub use com_api_runtime_mock::MockRuntimeImpl; -pub use com_api_runtime_mock::RuntimeBuilderImpl as MockRuntimeBuilderImpl; +#[cfg(feature = "iceoryx")] +pub use { + com_api_runtime_iceoryx::IceoryxRuntimeImpl, + com_api_runtime_iceoryx::RuntimeBuilderImpl as IceoryxRuntimeBuilderImpl, +}; + +#[cfg(not(feature = "iceoryx"))] +pub use { + com_api_runtime_lola::LolaRuntimeImpl, + com_api_runtime_lola::RuntimeBuilderImpl as LolaRuntimeBuilderImpl, + com_api_runtime_mock::MockRuntimeImpl, + com_api_runtime_mock::RuntimeBuilderImpl as MockRuntimeBuilderImpl, +}; pub use com_api_concept::{ Builder, Consumer, ConsumerBuilder, ConsumerDescriptor, Error, FindServiceSpecifier,