diff --git a/BUILD b/BUILD index 6385a532d8..a64d2a9470 100644 --- a/BUILD +++ b/BUILD @@ -76,6 +76,7 @@ format_multirun( name = "format", cc = "@clang_format//:executable", python = "@aspect_rules_lint//lint:ruff_bin", + rust = "//tools/lint:rustfmt_with_config", starlark = "@buildifier_prebuilt//:buildifier", target_compatible_with = ["@platforms//os:linux"], ) @@ -85,6 +86,7 @@ format_test( cc = "@clang_format//:executable", no_sandbox = True, python = "@aspect_rules_lint//lint:ruff_bin", + rust = "//tools/lint:rustfmt_with_config", starlark = "@buildifier_prebuilt//:buildifier", tags = ["no-flaky-test-detection"], target_compatible_with = ["@platforms//os:linux"], diff --git a/CI.md b/CI.md index 1ba8cfa4b0..873ae562b3 100644 --- a/CI.md +++ b/CI.md @@ -115,6 +115,11 @@ The goal is not to ensure a specific format but to have consistency in the proje Ensure that the modified Python files are formatted following our decided style. The goal is not to ensure a specific format but to have consistency in the project. +#### Formatting of Rust files + +Ensure that the modified Rust files are formatted following our decided style. +The goal is not to ensure a specific format but to have consistency in the project. + #### Build everything and run unit tests (x86-64 linux) Builds everything and runs all unit tests for all languages (C++, Rust, Python, etc.). diff --git a/score/mw/com/example/com-api-example/BUILD b/score/mw/com/example/com-api-example/BUILD index 10e0250298..20335d25bd 100644 --- a/score/mw/com/example/com-api-example/BUILD +++ b/score/mw/com/example/com-api-example/BUILD @@ -17,7 +17,7 @@ rust_library( name = "com-api-example-lib", srcs = glob(["src/**/*.rs"]), crate_name = "com_api_example", - edition = "2024", + edition = "2021", features = ["link_std_cpp_lib"], deps = [ "//score/mw/com/example/com-api-example/com-api-gen", @@ -35,7 +35,7 @@ rust_binary( "etc/logging.json", "etc/mw_com_config.json", ], - edition = "2024", + edition = "2021", env = { "MW_LOG_CONFIG_FILE": "score/mw/com/example/com-api-example/etc/logging.json", }, @@ -55,7 +55,7 @@ rust_test( name = "com-api-example-tokio-integration-test", srcs = ["tests_using_tokio_runtime.rs"], data = ["etc/mw_com_config.json"], - edition = "2024", + edition = "2021", features = ["link_std_cpp_lib"], tags = ["manual"], deps = [ diff --git a/score/mw/com/example/com-api-example/main.rs b/score/mw/com/example/com-api-example/main.rs index 6e7394d529..a20420dc60 100644 --- a/score/mw/com/example/com-api-example/main.rs +++ b/score/mw/com/example/com-api-example/main.rs @@ -86,62 +86,54 @@ const ASYNC_PRODUCER_STARTUP_DELAY_MS: u64 = 2000; // Run the consumer with the specified runtime and example type fn run_consumer(name: &str, example_type: &ExampleType, runtime: &R) { log::info!("Running with {} runtime", name); - let service_id = InstanceSpecifier::new("/Vehicle/Service1/Instance") - .expect("Failed to create InstanceSpecifier"); + let service_id = InstanceSpecifier::new("/Vehicle/Service1/Instance").expect("Failed to create InstanceSpecifier"); if matches!(example_type, ExampleType::Sync) { - std::thread::sleep(std::time::Duration::from_millis( - SYNC_CONSUMER_STARTUP_DELAY_MS, - )); + std::thread::sleep(std::time::Duration::from_millis(SYNC_CONSUMER_STARTUP_DELAY_MS)); } let consumer_monitor = match example_type { // it does the service discovery and receving data synchronously ExampleType::Sync => { - let consumer_monitor = - VehicleMonitorConsumer::find_available_instances(runtime, service_id) - .expect("Failed to create consumer"); + let consumer_monitor = VehicleMonitorConsumer::find_available_instances(runtime, service_id) + .expect("Failed to create consumer"); consumer_monitor .read_tire_data(SAMPLE_COUNT) .expect("Failed to read tire data synchronously"); consumer_monitor - } + }, // it does the service discovery asynchronously and receving data synchronously ExampleType::AsyncServiceDiscovery => { - let consumer_monitor = futures::executor::block_on( - VehicleMonitorConsumer::find_available_instances_async(runtime, service_id), - ) + let consumer_monitor = futures::executor::block_on(VehicleMonitorConsumer::find_available_instances_async( + runtime, service_id, + )) .expect("Failed to create consumer"); consumer_monitor .read_tire_data(SAMPLE_COUNT) .expect("Failed to read tire data synchronously"); consumer_monitor - } + }, // it does the service discovery asynchronously and receving data asynchronously without timeout // for the receive operation, it will wait until the data is received. ExampleType::AsyncReceive => { - let consumer_monitor = futures::executor::block_on( - VehicleMonitorConsumer::find_available_instances_async(runtime, service_id), - ) + let consumer_monitor = futures::executor::block_on(VehicleMonitorConsumer::find_available_instances_async( + runtime, service_id, + )) .expect("Failed to create consumer"); - futures::executor::block_on( - consumer_monitor.read_tire_data_async_without_timeout(SAMPLE_COUNT), - ) - .expect("Failed to read tire data asynchronously"); + futures::executor::block_on(consumer_monitor.read_tire_data_async_without_timeout(SAMPLE_COUNT)) + .expect("Failed to read tire data asynchronously"); consumer_monitor - } + }, // it does the service discovery asynchronously and receving data asynchronously with timeout // for the receive operation, it will wait until the data is received or timeout occurs. ExampleType::AsyncReceiveWithTimeout => { - let consumer_monitor = futures::executor::block_on( - VehicleMonitorConsumer::find_available_instances_async(runtime, service_id), - ) + let consumer_monitor = futures::executor::block_on(VehicleMonitorConsumer::find_available_instances_async( + runtime, service_id, + )) .expect("Failed to create consumer"); - futures::executor::block_on( - consumer_monitor.read_tire_data_async_with_timeout(SAMPLE_COUNT), - ) - .expect("Failed to read tire data asynchronously with timeout"); + futures::executor::block_on(consumer_monitor.read_tire_data_async_with_timeout(SAMPLE_COUNT)) + .expect("Failed to read tire data asynchronously with timeout"); consumer_monitor - } + }, // it does the service discovery asynchronously and receving data asynchronously with streaming ExampleType::Streaming => { let mut consumer_monitor = futures::executor::block_on( @@ -150,7 +142,7 @@ fn run_consumer(name: &str, example_type: &ExampleType, runtime: &R) .expect("Failed to create consumer"); futures::executor::block_on(consumer_monitor.read_tire_data_stream(SAMPLE_COUNT)); consumer_monitor - } + }, }; consumer_monitor.unsubscribe(); log::info!("runtime execution completed"); @@ -159,16 +151,12 @@ fn run_consumer(name: &str, example_type: &ExampleType, runtime: &R) // Run the producer with the specified runtime and example type fn run_producer(name: &str, example_type: &ExampleType, runtime: &R) { log::info!("Running with {} runtime", name); - let service_id = InstanceSpecifier::new("/Vehicle/Service1/Instance") - .expect("Failed to create InstanceSpecifier"); + let service_id = InstanceSpecifier::new("/Vehicle/Service1/Instance").expect("Failed to create InstanceSpecifier"); // In async examples, we will not wait before offering the service to simulate async discovery. if !matches!(example_type, ExampleType::Sync) { - std::thread::sleep(std::time::Duration::from_millis( - ASYNC_PRODUCER_STARTUP_DELAY_MS, - )); + std::thread::sleep(std::time::Duration::from_millis(ASYNC_PRODUCER_STARTUP_DELAY_MS)); } - let producer_monitor = - VehicleMonitorProducer::new(runtime, service_id).expect("Failed to create producer"); + let producer_monitor = VehicleMonitorProducer::new(runtime, service_id).expect("Failed to create producer"); log::info!("Producer created and offered successfully"); producer_monitor.run_publish_loop(INITIAL_TIRE_PRESSURE, SAMPLE_COUNT); producer_monitor.unoffer(); @@ -199,11 +187,7 @@ fn main() { init_logging(); let args = Arguments::parse(); let lola_runtime_builder = create_lola_runtime_builder(&args.service_instance_manifest); - let lola_runtime = Arc::new( - lola_runtime_builder - .build() - .expect("Failed to build Lola runtime"), - ); + let lola_runtime = Arc::new(lola_runtime_builder.build().expect("Failed to build Lola runtime")); let example_type = args.example_type.clone(); let runtime_producer = Arc::clone(&lola_runtime); diff --git a/score/mw/com/example/com-api-example/src/consumer.rs b/score/mw/com/example/com-api-example/src/consumer.rs index 4c09817dc7..c7e74fc71b 100644 --- a/score/mw/com/example/com-api-example/src/consumer.rs +++ b/score/mw/com/example/com-api-example/src/consumer.rs @@ -11,13 +11,13 @@ * SPDX-License-Identifier: Apache-2.0 ********************************************************************************/ -use score_com::{ - ConsumerBuilder, FindServiceSpecifier, InstanceSpecifier, Result, Runtime, SampleContainer, - ServiceDiscovery, Subscriber, Subscription, -}; use com_api_gen::{Exhaust, Tire, VehicleInterface}; use futures::channel::oneshot; use futures::{FutureExt, StreamExt}; +use score_com::{ + ConsumerBuilder, FindServiceSpecifier, InstanceSpecifier, Result, Runtime, SampleContainer, ServiceDiscovery, + Subscriber, Subscription, +}; use std::sync::mpsc; use std::thread; use std::time::Duration; @@ -31,8 +31,7 @@ const SYNC_RECEIVE_POLL_INTERVAL_MS: u64 = 1000; pub struct VehicleMonitorConsumer { tire_subscriber: <::Subscriber as Subscriber>::Subscription, - _exhaust_subscriber: - <::Subscriber as Subscriber>::Subscription, + _exhaust_subscriber: <::Subscriber as Subscriber>::Subscription, } impl VehicleMonitorConsumer { @@ -65,11 +64,9 @@ impl VehicleMonitorConsumer { match result { Ok(0) => log::info!("No tire data received"), Ok(x) => { - let sample = sample_buf - .pop_front() - .expect("Sample buffer pop operation error"); + let sample = sample_buf.pop_front().expect("Sample buffer pop operation error"); log::info!("{} samples received: sample[0] = {:?}", x, *sample); - } + }, Err(e) => log::error!("Error receiving tire data: {:?}", e), } } @@ -77,20 +74,15 @@ impl VehicleMonitorConsumer { /// Finds available service instances and constructs a VehicleMonitorConsumer. /// It will return immediately regardless of whether any instances are available or not. pub fn find_available_instances(runtime: &R, service_id: InstanceSpecifier) -> Result { - let consumer_discovery = - runtime.find_service::(FindServiceSpecifier::Specific(service_id)); + let consumer_discovery = runtime.find_service::(FindServiceSpecifier::Specific(service_id)); let instances = consumer_discovery.get_available_instances()?; Self::from_service_instances(instances) } /// Finds available service instances asynchronously and constructs a VehicleMonitorConsumer. /// It will wait for the service availability and return once an instance is found. - pub async fn find_available_instances_async( - runtime: &R, - service_id: InstanceSpecifier, - ) -> Result { - let consumer_discovery = - runtime.find_service::(FindServiceSpecifier::Specific(service_id)); + pub async fn find_available_instances_async(runtime: &R, service_id: InstanceSpecifier) -> Result { + let consumer_discovery = runtime.find_service::(FindServiceSpecifier::Specific(service_id)); let instances = consumer_discovery.get_available_instances_async().await?; Self::from_service_instances(instances) } @@ -136,9 +128,7 @@ impl VehicleMonitorConsumer { for _ in 0..count { // Request a timeout from the shared timer thread. let (tx, rx) = oneshot::channel(); - timer_tx - .send(tx) - .expect("Timer thread unexpectedly stopped"); + timer_tx.send(tx).expect("Timer thread unexpectedly stopped"); // Map the receiver to resolve to () instead of Result<(), Canceled> let timeout_future = rx.map(|_| ()); @@ -162,7 +152,7 @@ impl VehicleMonitorConsumer { None => { log::info!("Stream ended"); break; - } + }, } } } diff --git a/score/mw/com/example/com-api-example/src/lib.rs b/score/mw/com/example/com-api-example/src/lib.rs index fb4e37ff71..126bc4ffb0 100644 --- a/score/mw/com/example/com-api-example/src/lib.rs +++ b/score/mw/com/example/com-api-example/src/lib.rs @@ -16,12 +16,11 @@ pub mod producer; pub use consumer::VehicleMonitorConsumer; pub use producer::VehicleMonitorProducer; -use score_com::{Interface, Producer}; use com_api_gen::VehicleInterface; +use score_com::{Interface, Producer}; // Type aliases for generated consumer and offered producer types for the Vehicle interface // VehicleConsumer is the consumer type generated for the Vehicle interface, parameterized by the runtime R pub type VehicleConsumer = ::Consumer; // VehicleOfferedProducer is the offered producer type generated for the Vehicle interface, parameterized by the runtime R -pub type VehicleOfferedProducer = - <::Producer as Producer>::OfferedProducer; +pub type VehicleOfferedProducer = <::Producer as Producer>::OfferedProducer; diff --git a/score/mw/com/example/com-api-example/src/producer.rs b/score/mw/com/example/com-api-example/src/producer.rs index 6d78801671..8d653b8ce6 100644 --- a/score/mw/com/example/com-api-example/src/producer.rs +++ b/score/mw/com/example/com-api-example/src/producer.rs @@ -12,11 +12,10 @@ ********************************************************************************/ use crate::VehicleOfferedProducer; +use com_api_gen::{Tire, VehicleInterface}; use score_com::{ - Builder, InstanceSpecifier, OfferedProducer, Producer, Publisher, Result, Runtime, - SampleMaybeUninit, SampleMut, + Builder, InstanceSpecifier, OfferedProducer, Producer, Publisher, Result, Runtime, SampleMaybeUninit, SampleMut, }; -use com_api_gen::{Tire, VehicleInterface}; use std::thread; use std::time::Duration; @@ -34,9 +33,7 @@ impl VehicleMonitorProducer { /// Create a new VehicleMonitorProducer pub fn new(runtime: &R, service_id: InstanceSpecifier) -> Result { let producer_builder = runtime.producer_builder::(service_id); - let producer = producer_builder - .build() - .expect("Failed to build producer instance"); + let producer = producer_builder.build().expect("Failed to build producer instance"); let producer = producer.offer().expect("Failed to offer producer instance"); Ok(Self { producer }) } diff --git a/score/mw/com/example/com-api-example/tests_using_tokio_runtime.rs b/score/mw/com/example/com-api-example/tests_using_tokio_runtime.rs index 28c5cb92f5..b87504a9dd 100644 --- a/score/mw/com/example/com-api-example/tests_using_tokio_runtime.rs +++ b/score/mw/com/example/com-api-example/tests_using_tokio_runtime.rs @@ -31,12 +31,12 @@ #[cfg(test)] mod test { + use com_api_gen::{Tire, VehicleInterface, VehicleOfferedProducer}; use score_com::{ - Builder, FindServiceSpecifier, InstanceSpecifier, LolaRuntimeBuilderImpl, OfferedProducer, - Producer, Publisher, Runtime, RuntimeBuilder, SampleContainer, SampleMaybeUninit, - SampleMut, ServiceDiscovery, Subscriber, Subscription, + Builder, FindServiceSpecifier, InstanceSpecifier, LolaRuntimeBuilderImpl, OfferedProducer, Producer, Publisher, + Runtime, RuntimeBuilder, SampleContainer, SampleMaybeUninit, SampleMut, ServiceDiscovery, Subscriber, + Subscription, }; - use com_api_gen::{Tire, VehicleInterface, VehicleOfferedProducer}; use futures::stream::StreamExt; use std::sync::OnceLock; @@ -57,8 +57,7 @@ mod test { // as it prints warning if backend is initialized more than once. fn get_test_runtime() -> &'static score_com::LolaRuntimeImpl { LOLA_RUNTIME.get_or_init(|| { - let lola_runtime_builder = - init_lola_runtime_builder(std::path::Path::new(TEST_CONFIG_PATH)); + let lola_runtime_builder = init_lola_runtime_builder(std::path::Path::new(TEST_CONFIG_PATH)); lola_runtime_builder.build().unwrap() }) } @@ -69,10 +68,7 @@ mod test { if config_path.exists() { lola_runtime_builder.load_config(config_path); } else { - eprintln!( - "Provided config path does not exist: {}", - config_path.display() - ); + eprintln!("Provided config path does not exist: {}", config_path.display()); } lola_runtime_builder } @@ -83,9 +79,7 @@ mod test { service_id: InstanceSpecifier, ) -> com_api_gen::VehicleOfferedProducer { let producer_builder = runtime.producer_builder::(service_id); - let producer = producer_builder - .build() - .expect("Failed to build producer instance"); + let producer = producer_builder.build().expect("Failed to build producer instance"); producer.offer().expect("Failed to offer producer instance") } @@ -94,8 +88,7 @@ mod test { runtime: &R, service_id: InstanceSpecifier, ) -> com_api_gen::VehicleConsumer { - let consumer_discovery = - runtime.find_service::(FindServiceSpecifier::Specific(service_id)); + let consumer_discovery = runtime.find_service::(FindServiceSpecifier::Specific(service_id)); let available_service_instances = consumer_discovery .get_available_instances_async() .await @@ -107,9 +100,7 @@ mod test { .nth(handle_index) .expect("Failed to get consumer builder at specified handle index"); - consumer_builder - .build() - .expect("Failed to build consumer instance") + consumer_builder.build().expect("Failed to build consumer instance") } //sender will send data in each 1 second @@ -122,7 +113,7 @@ mod test { Err(e) => { eprintln!("[SENDER] Failed to allocate sample: {:?}", e); continue; - } + }, }; let sample = uninit_sample.write(Tire { pressure: INITIAL_TIRE_PRESSURE + i as f32, @@ -139,16 +130,12 @@ mod test { //receiver function which use async receive to get data, it waits for new data and process it once it arrives, //it will receive data 10 times and print the received samples - async fn async_data_processor_fn( - subscribed: impl Subscription, - is_timeout: bool, - ) { + async fn async_data_processor_fn(subscribed: impl Subscription, is_timeout: bool) { println!("[RECEIVER] Async data processor started"); let mut buffer = SampleContainer::new(SAMPLE_COUNT); for _ in 0..CONSUMER_ITERATIONS { let (returned_buf, result) = if is_timeout { - let timeout = - tokio::time::sleep(tokio::time::Duration::from_millis(RECEIVE_TIMEOUT_MS)); + let timeout = tokio::time::sleep(tokio::time::Duration::from_millis(RECEIVE_TIMEOUT_MS)); subscribed.cancellable_receive(buffer, 1, 3, timeout).await } else { subscribed.receive(buffer, 1, 3).await @@ -171,24 +158,16 @@ mod test { println!("[RECEIVER] Stream processor started"); while cnt > 0 { // Use timeout to avoid waiting indefinitely in case of issues with the producer or subscription - match tokio::time::timeout( - tokio::time::Duration::from_millis(SAMPLE_INTERVAL_MS), - stream.next(), - ) - .await - { + match tokio::time::timeout(tokio::time::Duration::from_millis(SAMPLE_INTERVAL_MS), stream.next()).await { Ok(Some(Ok(sample))) => { - println!( - "[RECEIVER] Stream received sample: {:.2} psi", - sample.pressure - ) - } + println!("[RECEIVER] Stream received sample: {:.2} psi", sample.pressure) + }, Ok(Some(Err(e))) => eprintln!("[RECEIVER] Stream error: {:?}", e), Ok(None) => break, Err(_) => { eprintln!("[RECEIVER] Timeout while waiting for stream sample"); break; - } + }, } cnt -= 1; } @@ -199,18 +178,15 @@ mod test { #[tokio::test(flavor = "multi_thread")] async fn receive_and_send_using_multi_thread() { println!("Starting async subscription test with Lola runtime"); - let service_id = InstanceSpecifier::new("/Vehicle/Service3/Instance") - .expect("Failed to create InstanceSpecifier"); + let service_id = + InstanceSpecifier::new("/Vehicle/Service3/Instance").expect("Failed to create InstanceSpecifier"); let service_id_clone = service_id.clone(); //consumer create let consumer_runtime = get_test_runtime(); //starting service discovery in async way, so that it can be discovered when producer offer service after some delay, and consumer is waiting for discovery result let consumer = tokio::spawn(create_consumer_async(consumer_runtime, service_id)); //simulate some delay before producer offer service, so that consumer is waiting for discovery - tokio::time::sleep(tokio::time::Duration::from_millis( - TIMEOUT_FOR_SIMULATION_MS, - )) - .await; + tokio::time::sleep(tokio::time::Duration::from_millis(TIMEOUT_FOR_SIMULATION_MS)).await; //Producer create let producer_runtime = get_test_runtime(); let producer = create_producer(producer_runtime, service_id_clone); @@ -222,9 +198,7 @@ mod test { let subscribed = consumer.left_tire.subscribe(SAMPLE_COUNT).unwrap(); let processor_join_handle = tokio::spawn(async_data_processor_fn(subscribed, false)); - processor_join_handle - .await - .expect("Error returned from task"); + processor_join_handle.await.expect("Error returned from task"); let producer = sender_join_handle.await.expect("Error returned from task"); match producer.unoffer() { @@ -240,18 +214,15 @@ mod test { async fn receive_with_timeout_and_send_using_multi_thread() { println!("Starting async subscription test with Lola runtime"); //Intentionally using service instance of test1, if you face issue add new service instance in config file and use it here. - let service_id = InstanceSpecifier::new("/Vehicle/Service1/Instance") - .expect("Failed to create InstanceSpecifier"); + let service_id = + InstanceSpecifier::new("/Vehicle/Service1/Instance").expect("Failed to create InstanceSpecifier"); let service_id_clone = service_id.clone(); //consumer create let consumer_runtime = get_test_runtime(); //starting service discovery in async way, so that it can be discovered when producer offer service after some delay, and consumer is waiting for discovery result let consumer = tokio::spawn(create_consumer_async(consumer_runtime, service_id)); //simulate some delay before producer offer service, so that consumer is waiting for discovery - tokio::time::sleep(tokio::time::Duration::from_millis( - TIMEOUT_FOR_SIMULATION_MS, - )) - .await; + tokio::time::sleep(tokio::time::Duration::from_millis(TIMEOUT_FOR_SIMULATION_MS)).await; //Producer create let producer_runtime = get_test_runtime(); let producer = create_producer(producer_runtime, service_id_clone); @@ -263,9 +234,7 @@ mod test { let subscribed = consumer.left_tire.subscribe(SAMPLE_COUNT).unwrap(); let processor_join_handle = tokio::spawn(async_data_processor_fn(subscribed, true)); - processor_join_handle - .await - .expect("Error returned from task"); + processor_join_handle.await.expect("Error returned from task"); let producer = sender_join_handle.await.expect("Error returned from task"); @@ -282,18 +251,15 @@ mod test { #[tokio::test(flavor = "multi_thread")] async fn stream_and_send_using_multi_thread() { println!("Starting async subscription test with Lola runtime"); - let service_id = InstanceSpecifier::new("/Vehicle/Service1/Instance") - .expect("Failed to create InstanceSpecifier"); + let service_id = + InstanceSpecifier::new("/Vehicle/Service1/Instance").expect("Failed to create InstanceSpecifier"); let service_id_clone = service_id.clone(); //consumer create let consumer_runtime = get_test_runtime(); //starting service discovery in async way, so that it can be discovered when producer offer service after some delay, and consumer is waiting for discovery result let consumer = tokio::spawn(create_consumer_async(consumer_runtime, service_id)); //simulate some delay before producer offer service, so that consumer is waiting for discovery - tokio::time::sleep(tokio::time::Duration::from_millis( - TIMEOUT_FOR_SIMULATION_MS, - )) - .await; + tokio::time::sleep(tokio::time::Duration::from_millis(TIMEOUT_FOR_SIMULATION_MS)).await; //Producer create let producer_runtime = get_test_runtime(); let producer = create_producer(producer_runtime, service_id_clone); diff --git a/score/mw/com/impl/plumbing/rust/sample_allocatee_ptr.rs b/score/mw/com/impl/plumbing/rust/sample_allocatee_ptr.rs index c8e5d4a25d..6e4edc9a10 100644 --- a/score/mw/com/impl/plumbing/rust/sample_allocatee_ptr.rs +++ b/score/mw/com/impl/plumbing/rust/sample_allocatee_ptr.rs @@ -18,11 +18,7 @@ use core::fmt::Debug; use std::mem::ManuallyDrop; use common_rs::{ - BlankBinding, - ConsumerEventDataControlLocalView, - CxxOptional, - CustomDeleter, - ProviderEventDataControlLocalView, + BlankBinding, ConsumerEventDataControlLocalView, CustomDeleter, CxxOptional, ProviderEventDataControlLocalView, SlotIndexType, }; @@ -99,9 +95,7 @@ impl Debug for SampleAllocateePtr { _ => "Unknown", }; - f.debug_struct("SampleAllocateePtr") - .field("state", &state) - .finish() + f.debug_struct("SampleAllocateePtr").field("state", &state).finish() } } @@ -132,21 +126,13 @@ mod tests { #[test] fn test_sample_allocatee_ptr_variant_user_defined_type_size() { let cpp_size = SampleAllocateePtrLola::get_variant_user_defined_type(); - verify_size_and_align!( - SampleAllocateePtr, - cpp_size, - "SampleAllocateePtr" - ); + verify_size_and_align!(SampleAllocateePtr, cpp_size, "SampleAllocateePtr"); } #[test] fn test_event_data_control_composite_size() { let cpp_size = SampleAllocateePtrLola::get_event_data_control_composite_size(); - verify_size_and_align!( - EventDataControlComposite, - cpp_size, - "EventDataControlComposite" - ); + verify_size_and_align!(EventDataControlComposite, cpp_size, "EventDataControlComposite"); } #[test] @@ -164,10 +150,7 @@ mod tests { fn test_negative_allocatee_ptr_size_mismatch() { let cpp_size = SampleAllocateePtrLola::get_variant_int32(); let incorrect = cpp_size.size + 1; - assert_eq!( - incorrect, cpp_size.size, - "SampleAllocateePtr size mismatch!" - ); + assert_eq!(incorrect, cpp_size.size, "SampleAllocateePtr size mismatch!"); } #[test] @@ -175,9 +158,6 @@ mod tests { fn test_negative_allocatee_ptr_align_mismatch() { let cpp_size = SampleAllocateePtrLola::get_variant_int32(); let incorrect = cpp_size.align + 1; - assert_eq!( - incorrect, cpp_size.align, - "SampleAllocateePtr align mismatch!" - ); + assert_eq!(incorrect, cpp_size.align, "SampleAllocateePtr align mismatch!"); } } diff --git a/score/mw/com/impl/plumbing/rust/sample_ptr.rs b/score/mw/com/impl/plumbing/rust/sample_ptr.rs index b943b009a0..229a6c2e31 100644 --- a/score/mw/com/impl/plumbing/rust/sample_ptr.rs +++ b/score/mw/com/impl/plumbing/rust/sample_ptr.rs @@ -14,13 +14,7 @@ use core::fmt::Debug; use std::mem::ManuallyDrop; use common_rs::{ - BlankBinding, - CxxOptional, - EventDataControl, - SlotIndexType, - TransactionLogIndex, - UniquePtr, - CustomDeleter, + BlankBinding, CustomDeleter, CxxOptional, EventDataControl, SlotIndexType, TransactionLogIndex, UniquePtr, }; type MockBinding = UniquePtr; diff --git a/score/mw/com/impl/rust/com-api/com-api-ffi-lola/BUILD b/score/mw/com/impl/rust/com-api/com-api-ffi-lola/BUILD index 164615febe..30ecab6512 100644 --- a/score/mw/com/impl/rust/com-api/com-api-ffi-lola/BUILD +++ b/score/mw/com/impl/rust/com-api/com-api-ffi-lola/BUILD @@ -37,7 +37,7 @@ rust_library( "common.rs", ], crate_root = "bridge_ffi.rs", - edition = "2024", + edition = "2021", visibility = [ "//score/mw/com:__subpackages__", ], @@ -50,7 +50,7 @@ rust_library( rust_library( name = "bridge_ffi_mock", srcs = ["bridge_ffi_mock.rs"], - edition = "2024", + edition = "2021", visibility = [ "//score/mw/com:__subpackages__", ], @@ -64,7 +64,7 @@ rust_library( rust_library( name = "bridge_ffi_lola", srcs = ["bridge_ffi_lola.rs"], - edition = "2024", + edition = "2021", visibility = [ "//score/mw/com:__subpackages__", ], diff --git a/score/mw/com/impl/rust/com-api/com-api-ffi-lola/bridge_ffi.rs b/score/mw/com/impl/rust/com-api/com-api-ffi-lola/bridge_ffi.rs index 7ee6a52719..c9d7ebdecd 100644 --- a/score/mw/com/impl/rust/com-api/com-api-ffi-lola/bridge_ffi.rs +++ b/score/mw/com/impl/rust/com-api/com-api-ffi-lola/bridge_ffi.rs @@ -71,9 +71,7 @@ use std::path::Path; use std::ptr::NonNull; pub mod common; -pub use common::{ - HandleContainer, HandleType, InstanceSpecifier, NativeHandleContainer, NativeInstanceSpecifier, -}; +pub use common::{HandleContainer, HandleType, InstanceSpecifier, NativeHandleContainer, NativeInstanceSpecifier}; /// Opaque C++ void* pointer wrapper pub type CVoidPtr = *const std::ffi::c_void; @@ -100,11 +98,7 @@ pub trait FFIBridge: Send + Sync + Clone + Debug + 'static + Unpin + Default { /// # Safety /// `allocatee_ptr` must be a valid pointer previously returned by `get_allocatee_ptr` /// and `type_ops` must be the corresponding `TypeOperationsManager` for the type T. - unsafe fn delete_allocatee_ptr( - &self, - allocatee_ptr: *mut std::ffi::c_void, - type_ops: &TypeOperationsManager, - ); + unsafe fn delete_allocatee_ptr(&self, allocatee_ptr: *mut std::ffi::c_void, type_ops: &TypeOperationsManager); /// # Safety /// `allocatee_ptr` must be a valid pointer previously returned by `get_allocatee_ptr` @@ -138,11 +132,7 @@ pub trait FFIBridge: Send + Sync + Clone + Debug + 'static + Unpin + Default { /// # Safety /// `sample_ptr` must be a valid pointer to a `SamplePtr` of the specified `type_name`, /// and must not be used after this call. - unsafe fn sample_ptr_delete( - &self, - sample_ptr: *mut std::ffi::c_void, - type_ops: &TypeOperationsManager, - ); + unsafe fn sample_ptr_delete(&self, sample_ptr: *mut std::ffi::c_void, type_ops: &TypeOperationsManager); /// # Safety /// `skeleton_ptr` must be a valid, non-null pointer to a `SkeletonBase` previously created @@ -224,11 +214,7 @@ pub trait FFIBridge: Send + Sync + Clone + Debug + 'static + Unpin + Default { /// # Safety /// `event_ptr` must be a valid pointer to a `ProxyEventBase` obtained from /// `get_event_from_proxy`. Must be called before `get_samples_from_event`. - unsafe fn subscribe_to_event( - &self, - event_ptr: *mut ProxyEventBase, - max_sample_count: u32, - ) -> bool; + unsafe fn subscribe_to_event(&self, event_ptr: *mut ProxyEventBase, max_sample_count: u32) -> bool; /// # Safety /// `event_ptr` must be a valid pointer to a `ProxyEventBase` obtained from @@ -240,11 +226,7 @@ pub trait FFIBridge: Send + Sync + Clone + Debug + 'static + Unpin + Default { /// `proxy_event_ptr` must be a valid pointer to a `ProxyEventBase` obtained from /// `get_event_from_proxy`. `handler` must be a valid `FatPtr` referencing a callable /// compatible with the receive-handler signature expected by the implementation. - unsafe fn set_event_receive_handler( - &self, - proxy_event_ptr: *mut ProxyEventBase, - handler: &FatPtr, - ) -> bool; + unsafe fn set_event_receive_handler(&self, proxy_event_ptr: *mut ProxyEventBase, handler: &FatPtr) -> bool; /// # Safety /// `proxy_event_ptr` must be a valid pointer to a `ProxyEventBase` obtained from @@ -269,11 +251,7 @@ pub trait FFIBridge: Send + Sync + Clone + Debug + 'static + Unpin + Default { /// Caller must ensure that the provided interface_id and member_name correspond to /// a valid TypeOperations instance in the C++ registry. The returned TypeOperationsManager /// must not be used after the underlying TypeOperations instance is destroyed on the C++ side. - unsafe fn get_type_ops_instance( - &self, - interface_id: &str, - member_name: &str, - ) -> Option; + unsafe fn get_type_ops_instance(&self, interface_id: &str, member_name: &str) -> Option; /// Find all service instances matching `instance_specifier`. /// diff --git a/score/mw/com/impl/rust/com-api/com-api-ffi-lola/bridge_ffi_lola.rs b/score/mw/com/impl/rust/com-api/com-api-ffi-lola/bridge_ffi_lola.rs index 2f24948113..0ec941b304 100644 --- a/score/mw/com/impl/rust/com-api/com-api-ffi-lola/bridge_ffi_lola.rs +++ b/score/mw/com/impl/rust/com-api/com-api-ffi-lola/bridge_ffi_lola.rs @@ -34,8 +34,7 @@ unsafe extern "C" fn mw_com_impl_call_dyn_fnmut(ptr: *const FatPtr) { // SAFETY: caller guarantees ptr is valid; transmute reconstructs the fat pointer. let dyn_fnmut: *mut (dyn FnMut() + Send + 'static) = unsafe { std::mem::transmute(*ptr) }; // SAFETY: the box is still alive (C++ only calls dispose after all invocations finish). - if std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| unsafe { (*dyn_fnmut)() })).is_err() - { + if std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| unsafe { (*dyn_fnmut)() })).is_err() { log::error!("Panic caught in mw_com_impl_call_dyn_fnmut: aborting to prevent unwind across FFI boundary"); // Abort to prevent a Rust panic from unwinding across the C++ stack boundary. std::process::abort(); @@ -63,10 +62,7 @@ unsafe extern "C" fn mw_com_impl_delete_boxed_fnmut(ptr: *mut FatPtr) { /// - `ptr` must point to a valid FatPtr /// - `sample_ptr` must point to valid placement-new storage containing SamplePtr #[unsafe(no_mangle)] -unsafe extern "C" fn mw_com_impl_call_dyn_ref_fnmut_sample( - ptr: *const FatPtr, - sample_ptr: *mut std::ffi::c_void, -) { +unsafe extern "C" fn mw_com_impl_call_dyn_ref_fnmut_sample(ptr: *const FatPtr, sample_ptr: *mut std::ffi::c_void) { if ptr.is_null() || sample_ptr.is_null() { return; } @@ -81,7 +77,9 @@ unsafe extern "C" fn mw_com_impl_call_dyn_ref_fnmut_sample( // Invoke the closure with the void* sample pointer. // catch_unwind prevents a Rust panic from unwinding across the C++ stack boundary. if std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| callable(sample_ptr))).is_err() { - log::error!("Panic caught in mw_com_impl_call_dyn_ref_fnmut_sample: aborting to prevent unwind across FFI boundary"); + log::error!( + "Panic caught in mw_com_impl_call_dyn_ref_fnmut_sample: aborting to prevent unwind across FFI boundary" + ); // Abort to prevent unwinding across FFI boundary std::process::abort(); } @@ -109,8 +107,7 @@ unsafe extern "C" fn mw_com_impl_call_dyn_ref_fnmut_find_service( } // Reconstruct the closure from FatPtr - let callable: &mut dyn FnMut(HandleContainer, NativeFindServiceHandle) = - unsafe { std::mem::transmute(*ptr) }; + let callable: &mut dyn FnMut(HandleContainer, NativeFindServiceHandle) = unsafe { std::mem::transmute(*ptr) }; // Invoke with correct types. // catch_unwind prevents a Rust panic from unwinding across the C++ stack boundary. @@ -122,7 +119,9 @@ unsafe extern "C" fn mw_com_impl_call_dyn_ref_fnmut_find_service( })) .is_err() { - log::error!("Panic caught in mw_com_impl_call_dyn_ref_fnmut_find_service: aborting to prevent unwind across FFI boundary"); + log::error!( + "Panic caught in mw_com_impl_call_dyn_ref_fnmut_find_service: aborting to prevent unwind across FFI boundary" + ); // Abort to prevent unwinding across FFI boundary std::process::abort(); } @@ -302,10 +301,7 @@ unsafe extern "C" { /// # Arguments /// * `allocatee_ptr` - Pointer to SampleAllocateePtr /// * `type_ops` - Pointer to TypeOperations instance - fn mw_com_delete_allocatee_ptr( - allocatee_ptr: *mut std::ffi::c_void, - type_ops: *const TypeOperations, - ); + fn mw_com_delete_allocatee_ptr(allocatee_ptr: *mut std::ffi::c_void, type_ops: *const TypeOperations); /// Get allocatee data pointer from allocatee of specific type /// @@ -343,10 +339,7 @@ unsafe extern "C" { /// /// # Returns /// True if handler was set successfully, false otherwise - fn mw_com_proxy_set_event_receive_handler( - proxy_event_ptr: *mut ProxyEventBase, - handler: *const FatPtr, - ) -> bool; + fn mw_com_proxy_set_event_receive_handler(proxy_event_ptr: *mut ProxyEventBase, handler: *const FatPtr) -> bool; /// Clear event receive handler for proxy event /// @@ -387,10 +380,7 @@ unsafe extern "C" { /// /// # Returns /// Pointer to TypeOperations instance, or nullptr on failure - fn mw_com_get_type_ops_instance( - interface_id: StringView, - member_name: StringView, - ) -> *mut TypeOperations; + fn mw_com_get_type_ops_instance(interface_id: StringView, member_name: StringView) -> *mut TypeOperations; /// Find available service instances and return a pointer to NativeHandleContainer /// @@ -399,9 +389,7 @@ unsafe extern "C" { /// /// # Returns /// Pointer to NativeHandleContainer containing available service instances, or nullptr if none found - fn mw_com_impl_find_service( - instance_specifier: *mut NativeInstanceSpecifier, - ) -> *mut NativeHandleContainer; + fn mw_com_impl_find_service(instance_specifier: *mut NativeInstanceSpecifier) -> *mut NativeHandleContainer; /// Initialize the communication implementation with the provided configuration. /// @@ -454,11 +442,7 @@ impl FFIBridge for LolaFFIBridge { /// # Safety /// `allocatee_ptr` must be a valid pointer previously returned by `get_allocatee_ptr` /// and `type_ops` must be the corresponding `TypeOperationsManager` for the type T. - unsafe fn delete_allocatee_ptr( - &self, - allocatee_ptr: *mut std::ffi::c_void, - type_ops: &TypeOperationsManager, - ) { + unsafe fn delete_allocatee_ptr(&self, allocatee_ptr: *mut std::ffi::c_void, type_ops: &TypeOperationsManager) { // SAFETY: allocatee_ptr is valid which is created using get_allocatee_ptr() and // type_ops provides the correct type operations for this allocatee. unsafe { @@ -545,11 +529,7 @@ impl FFIBridge for LolaFFIBridge { /// # Safety /// `sample_ptr` must be a valid pointer to a `SamplePtr` of the specified `type_name`, /// and must not be used after this call. - unsafe fn sample_ptr_delete( - &self, - sample_ptr: *mut std::ffi::c_void, - type_ops: &TypeOperationsManager, - ) { + unsafe fn sample_ptr_delete(&self, sample_ptr: *mut std::ffi::c_void, type_ops: &TypeOperationsManager) { // SAFETY: sample_ptr is guaranteed to be valid per the caller's contract. // The C++ implementation handles type checking and deletion safely using type_ops. unsafe { @@ -747,14 +727,7 @@ impl FFIBridge for LolaFFIBridge { // SAFETY: event_ptr and callback are guaranteed to be valid per the caller's contract. // type_ops provides the correct type operations for sample handling. // The C++ implementation handles sample retrieval and callback invocation safely. - unsafe { - mw_com_type_registry_get_samples_from_event( - event_ptr, - type_ops.as_ptr(), - callback, - max_samples, - ) - } + unsafe { mw_com_type_registry_get_samples_from_event(event_ptr, type_ops.as_ptr(), callback, max_samples) } } /// Unsafe wrapper around mw_com_skeleton_send_event @@ -793,11 +766,7 @@ impl FFIBridge for LolaFFIBridge { /// event_ptr must be a valid pointer to a ProxyEventBase previously obtained /// from get_event_from_proxy(). /// This function must be called before attempting to retrieve samples via get_samples_from_event(). - unsafe fn subscribe_to_event( - &self, - event_ptr: *mut ProxyEventBase, - max_sample_count: u32, - ) -> bool { + unsafe fn subscribe_to_event(&self, event_ptr: *mut ProxyEventBase, max_sample_count: u32) -> bool { // SAFETY: event_ptr is guaranteed to be valid per the caller's contract. // The C++ implementation handles subscription and buffer allocation safely. unsafe { mw_com_proxy_event_subscribe(event_ptr, max_sample_count) } @@ -832,11 +801,7 @@ impl FFIBridge for LolaFFIBridge { /// `proxy_event_ptr` must be a valid pointer to a `ProxyEventBase` obtained from /// `get_event_from_proxy`. `handler` must be a valid `FatPtr` referencing a callable /// compatible with the receive-handler signature expected by the implementation. - unsafe fn set_event_receive_handler( - &self, - proxy_event_ptr: *mut ProxyEventBase, - handler: &FatPtr, - ) -> bool { + unsafe fn set_event_receive_handler(&self, proxy_event_ptr: *mut ProxyEventBase, handler: &FatPtr) -> bool { // SAFETY: proxy_event_ptr must be valid per the caller's contract, // and handler must be a valid FatPtr referencing a callable compatible with the callback // signature expected by the C++ implementation. @@ -905,11 +870,7 @@ impl FFIBridge for LolaFFIBridge { /// Caller must ensure that the provided interface_id and member_name correspond to /// a valid TypeOperations instance in the C++ registry. The returned TypeOperationsManager /// must not be used after the underlying TypeOperations instance is destroyed on the C++ side. - unsafe fn get_type_ops_instance( - &self, - interface_id: &str, - member_name: &str, - ) -> Option { + unsafe fn get_type_ops_instance(&self, interface_id: &str, member_name: &str) -> Option { let interface_id = StringView::from(interface_id); let member_name = StringView::from(member_name); // SAFETY: interface_id and member_name are valid ids that correspond to a TypeOperations instance in the C++ registry, as per the caller's contract. diff --git a/score/mw/com/impl/rust/com-api/com-api-ffi-lola/bridge_ffi_mock.rs b/score/mw/com/impl/rust/com-api/com-api-ffi-lola/bridge_ffi_mock.rs index 57806e3826..bf8777d616 100644 --- a/score/mw/com/impl/rust/com-api/com-api-ffi-lola/bridge_ffi_mock.rs +++ b/score/mw/com/impl/rust/com-api/com-api-ffi-lola/bridge_ffi_mock.rs @@ -72,8 +72,7 @@ use bridge_ffi_rs::{ FatPtr, FindServiceCallable, FindServiceHandle, HandleContainer, HandleType, InstanceSpecifier, - NativeInstanceSpecifier, ProxyBase, ProxyEventBase, SkeletonBase, SkeletonEventBase, - TypeOperationsManager, + NativeInstanceSpecifier, ProxyBase, ProxyEventBase, SkeletonBase, SkeletonEventBase, TypeOperationsManager, }; use mockall::mock; @@ -249,17 +248,10 @@ impl bridge_ffi_rs::FFIBridge for SharedMockBridge { type_ops: &TypeOperationsManager, ) -> bool { //Safety: This is just forwarding the call to the inner mock, which is expected to be configured correctly in tests using mockall's expectations. - unsafe { - self.locked() - .get_allocatee_ptr(event_ptr, allocatee_ptr, type_ops) - } + unsafe { self.locked().get_allocatee_ptr(event_ptr, allocatee_ptr, type_ops) } } - unsafe fn delete_allocatee_ptr( - &self, - allocatee_ptr: *mut std::ffi::c_void, - type_ops: &TypeOperationsManager, - ) { + unsafe fn delete_allocatee_ptr(&self, allocatee_ptr: *mut std::ffi::c_void, type_ops: &TypeOperationsManager) { //Safety: This is just forwarding the call to the inner mock, which is expected to be configured correctly in tests using mockall's expectations. unsafe { self.locked().delete_allocatee_ptr(allocatee_ptr, type_ops) } } @@ -270,10 +262,7 @@ impl bridge_ffi_rs::FFIBridge for SharedMockBridge { type_ops: &TypeOperationsManager, ) -> *mut std::ffi::c_void { //Safety: This is just forwarding the call to the inner mock, which is expected to be configured correctly in tests using mockall's expectations. - unsafe { - self.locked() - .get_allocatee_data_ptr(allocatee_ptr, type_ops) - } + unsafe { self.locked().get_allocatee_data_ptr(allocatee_ptr, type_ops) } } unsafe fn skeleton_event_send_sample_allocatee( @@ -297,11 +286,7 @@ impl bridge_ffi_rs::FFIBridge for SharedMockBridge { unsafe { self.locked().sample_ptr_get(sample_ptr, type_ops) } } - unsafe fn sample_ptr_delete( - &self, - sample_ptr: *mut std::ffi::c_void, - type_ops: &TypeOperationsManager, - ) { + unsafe fn sample_ptr_delete(&self, sample_ptr: *mut std::ffi::c_void, type_ops: &TypeOperationsManager) { unsafe { self.locked().sample_ptr_delete(sample_ptr, type_ops) } } @@ -346,10 +331,7 @@ impl bridge_ffi_rs::FFIBridge for SharedMockBridge { event_id: &str, ) -> *mut ProxyEventBase { //Safety: This is just forwarding the call to the inner mock, which is expected to be configured correctly in tests using mockall's expectations. - unsafe { - self.locked() - .get_event_from_proxy(proxy_ptr, interface_id, event_id) - } + unsafe { self.locked().get_event_from_proxy(proxy_ptr, interface_id, event_id) } } unsafe fn get_event_from_skeleton( @@ -365,11 +347,7 @@ impl bridge_ffi_rs::FFIBridge for SharedMockBridge { } } - unsafe fn subscribe_to_event( - &self, - event_ptr: *mut ProxyEventBase, - max_num_samples: u32, - ) -> bool { + unsafe fn subscribe_to_event(&self, event_ptr: *mut ProxyEventBase, max_num_samples: u32) -> bool { //Safety: This is just forwarding the call to the inner mock, which is expected to be configured correctly in tests using mockall's expectations. unsafe { self.locked().subscribe_to_event(event_ptr, max_num_samples) } } @@ -399,17 +377,10 @@ impl bridge_ffi_rs::FFIBridge for SharedMockBridge { data_ptr: *const std::ffi::c_void, ) -> bool { //Safety: This is just forwarding the call to the inner mock, which is expected to be configured correctly in tests using mockall's expectations. - unsafe { - self.locked() - .skeleton_send_event(event_ptr, type_ops, data_ptr) - } + unsafe { self.locked().skeleton_send_event(event_ptr, type_ops, data_ptr) } } - unsafe fn set_event_receive_handler( - &self, - event_ptr: *mut ProxyEventBase, - callback: &FatPtr, - ) -> bool { + unsafe fn set_event_receive_handler(&self, event_ptr: *mut ProxyEventBase, callback: &FatPtr) -> bool { //Safety: This is just forwarding the call to the inner mock, which is expected to be configured correctly in tests using mockall's expectations. unsafe { self.locked().set_event_receive_handler(event_ptr, callback) } } @@ -432,16 +403,9 @@ impl bridge_ffi_rs::FFIBridge for SharedMockBridge { unsafe { self.locked().stop_find_service(find_service_handle) } } - unsafe fn get_type_ops_instance( - &self, - interface_id: &str, - member_name: &str, - ) -> Option { + unsafe fn get_type_ops_instance(&self, interface_id: &str, member_name: &str) -> Option { //Safety: This is just forwarding the call to the inner mock, which is expected to be configured correctly in tests using mockall's expectations. - unsafe { - self.locked() - .get_type_ops_instance(interface_id, member_name) - } + unsafe { self.locked().get_type_ops_instance(interface_id, member_name) } } fn find_service(&self, instance_specifier: InstanceSpecifier) -> Result { @@ -482,10 +446,7 @@ impl MockPointerAllocator { pub fn allocate(&self) -> *mut T { let mut allocs = self.locked(); allocs.push(Box::default()); - allocs - .last_mut() - .expect("Failed to allocate pointer") - .as_mut() as *mut T + allocs.last_mut().expect("Failed to allocate pointer").as_mut() as *mut T } /// Free a previously allocated pointer. diff --git a/score/mw/com/impl/rust/com-api/com-api-ffi-lola/common.rs b/score/mw/com/impl/rust/com-api/com-api-ffi-lola/common.rs index 8f9518fd8d..b439cd2cf1 100644 --- a/score/mw/com/impl/rust/com-api/com-api-ffi-lola/common.rs +++ b/score/mw/com/impl/rust/com-api/com-api-ffi-lola/common.rs @@ -41,20 +41,13 @@ pub struct NativeInstanceSpecifier { } unsafe extern "C" { - pub(crate) fn mw_com_impl_instance_specifier_create( - value: *const u8, - len: u32, - ) -> *mut NativeInstanceSpecifier; + pub(crate) fn mw_com_impl_instance_specifier_create(value: *const u8, len: u32) -> *mut NativeInstanceSpecifier; pub(crate) fn mw_com_impl_instance_specifier_clone( instance_specifier: *const NativeInstanceSpecifier, ) -> *mut NativeInstanceSpecifier; - pub(crate) fn mw_com_impl_instance_specifier_delete( - instance_specifier: *mut NativeInstanceSpecifier, - ); + pub(crate) fn mw_com_impl_instance_specifier_delete(instance_specifier: *mut NativeInstanceSpecifier); pub(crate) fn mw_com_impl_handle_container_delete(container: *mut NativeHandleContainer); - pub(crate) fn mw_com_impl_handle_container_get_size( - container: *const NativeHandleContainer, - ) -> u32; + pub(crate) fn mw_com_impl_handle_container_get_size(container: *const NativeHandleContainer) -> u32; pub(crate) fn mw_com_impl_handle_container_get_handle_at( container: *const NativeHandleContainer, pos: u32, @@ -84,8 +77,7 @@ impl TryFrom<&'_ str> for InstanceSpecifier { fn try_from(value: &'_ str) -> Result { // SAFETY: value points to a valid UTF-8 string; len matches the slice length. - let inner = - unsafe { mw_com_impl_instance_specifier_create(value.as_ptr(), value.len() as u32) }; + let inner = unsafe { mw_com_impl_instance_specifier_create(value.as_ptr(), value.len() as u32) }; if inner.is_null() { Err(()) } else { diff --git a/score/mw/com/impl/rust/com-api/com-api-runtime-lola/BUILD b/score/mw/com/impl/rust/com-api/com-api-runtime-lola/BUILD index 4657059844..84a01a7208 100644 --- a/score/mw/com/impl/rust/com-api/com-api-runtime-lola/BUILD +++ b/score/mw/com/impl/rust/com-api/com-api-runtime-lola/BUILD @@ -21,7 +21,7 @@ rust_library( "producer.rs", "runtime.rs", ], - edition = "2024", + edition = "2021", visibility = ["//score/mw/com:__subpackages__"], deps = [ "//score/mw/com/impl/plumbing/rust:sample_allocatee_ptr_rs", @@ -37,7 +37,7 @@ rust_library( rust_test( name = "com-api-runtime-lola-tests", crate = ":com-api-runtime-lola", - edition = "2024", + edition = "2021", #tag will be removed wwhen sanitizer issue resolved for this tags = ["manual"], deps = [ diff --git a/score/mw/com/impl/rust/com-api/com-api-runtime-lola/consumer.rs b/score/mw/com/impl/rust/com-api/com-api-runtime-lola/consumer.rs index 99aa7e688c..89589c72e9 100644 --- a/score/mw/com/impl/rust/com-api/com-api-runtime-lola/consumer.rs +++ b/score/mw/com/impl/rust/com-api/com-api-runtime-lola/consumer.rs @@ -47,9 +47,9 @@ use std::sync::Arc; use score_log as log; use score_com_concept::{ - Builder, CommData, Consumer, ConsumerBuilder, ConsumerDescriptor, ConsumerFailedReason, Error, - EventFailedReason, InstanceSpecifier, Interface, ReceiveFailedReason, Result, Sample, - SampleContainer, ServiceDiscovery, ServiceFailedReason, Subscriber, Subscription, + Builder, CommData, Consumer, ConsumerBuilder, ConsumerDescriptor, ConsumerFailedReason, Error, EventFailedReason, + InstanceSpecifier, Interface, ReceiveFailedReason, Result, Sample, SampleContainer, ServiceDiscovery, + ServiceFailedReason, Subscriber, Subscription, }; use bridge_ffi_rs::*; @@ -130,9 +130,7 @@ where std::ptr::from_ref(&(*self.inner.data)) as *const std::ffi::c_void, &self.inner.type_ops, ); - (data_ptr as *const T) - .as_ref() - .expect("Data pointer is null") + (data_ptr as *const T).as_ref().expect("Data pointer is null") } } } @@ -242,9 +240,8 @@ impl NativeProxyBase { //SAFETY: It is safe to create the proxy because interface_id and handle are valid //Handle received at the time of get_avaible_instances called with correct interface_id let raw_proxy_ptr = unsafe { bridge.create_proxy(interface_id, handle) }; - let proxy = std::ptr::NonNull::new(raw_proxy_ptr).ok_or(Error::ConsumerError( - ConsumerFailedReason::ProxyCreationFailed, - ))?; + let proxy = std::ptr::NonNull::new(raw_proxy_ptr) + .ok_or(Error::ConsumerError(ConsumerFailedReason::ProxyCreationFailed))?; Ok(Self { proxy, bridge: bridge.clone(), @@ -278,14 +275,12 @@ impl NativeProxyEventBase { //SAFETY: It is safe as we are passing valid proxy pointer and interface id to get event // proxy pointer is created during consumer creation let raw_event_ptr = unsafe { - instance_info.bridge.get_event_from_proxy( - proxy.as_ptr(), - instance_info.interface_id, - identifier, - ) + instance_info + .bridge + .get_event_from_proxy(proxy.as_ptr(), instance_info.interface_id, identifier) }; - let proxy_event_ptr = std::ptr::NonNull::new(raw_event_ptr) - .ok_or(Error::EventError(EventFailedReason::EventCreationFailed))?; + let proxy_event_ptr = + std::ptr::NonNull::new(raw_event_ptr).ok_or(Error::EventError(EventFailedReason::EventCreationFailed))?; Ok(Self { proxy_event_ptr }) } @@ -311,9 +306,7 @@ pub struct LolaSubscribableImpl { data: PhantomData, } -impl Subscriber> - for LolaSubscribableImpl -{ +impl Subscriber> for LolaSubscribableImpl { type Subscription = LolaSubscriberImpl; fn new(identifier: &'static str, instance_info: LolaConsumerInfo) -> Result { log::info!( @@ -321,11 +314,10 @@ impl Subscriber> identifier, instance_info.interface_id ); - let handle = instance_info.get_handle().ok_or(Error::ConsumerError( - ConsumerFailedReason::ServiceHandleNotFound, - ))?; - let native_proxy = - NativeProxyBase::new(&instance_info.bridge, instance_info.interface_id, handle)?; + let handle = instance_info + .get_handle() + .ok_or(Error::ConsumerError(ConsumerFailedReason::ServiceHandleNotFound))?; + let native_proxy = NativeProxyBase::new(&instance_info.bridge, instance_info.interface_id, handle)?; let proxy_instance = ProxyInstanceManager(Arc::new(native_proxy)); Ok(Self { identifier, @@ -349,11 +341,8 @@ impl Subscriber> return Err(Error::EventError(EventFailedReason::InvalidMaxSamples)); } let instance_info = self.instance_info.clone(); - let event_instance = NativeProxyEventBase::new::( - &self.proxy_instance.0.proxy, - &instance_info, - self.identifier, - )?; + let event_instance = + NativeProxyEventBase::new::(&self.proxy_instance.0.proxy, &instance_info, self.identifier)?; let max_num_samples_u32 = u32::try_from(max_num_samples).map_err(|_| { Error::EventError(EventFailedReason::MaxSampleOutOfBounds { max: u32::MAX as usize, @@ -386,7 +375,7 @@ impl Subscriber> // Store in SubscriberImpl with event, max_num_samples Ok(LolaSubscriberImpl { event: ProxyEventManager::new( - std::ptr::from_ref(event_instance.get_proxy_event_base()) as *mut ProxyEventBase, + std::ptr::from_ref(event_instance.get_proxy_event_base()) as *mut ProxyEventBase ), event_id: self.identifier, max_num_samples, @@ -432,10 +421,7 @@ impl ProxyEventManager { //Acquire the lock to ensure that only one receive call can access the proxy event at a time //Relaxed ordering is not sufficient here because we need to ensure that the in_progress // flag is updated before any receive call can access the proxy event - if self - .in_progress - .swap(true, std::sync::atomic::Ordering::Acquire) - { + if self.in_progress.swap(true, std::sync::atomic::Ordering::Acquire) { panic!("Concurrent receive calls are not allowed on the same subscriber instance"); } ProxyEventManagerGuard { manager: self } @@ -517,13 +503,9 @@ impl Drop for LolaSubscriberImpl { if self.async_init_status.get().is_some() // Check if the async receive callback was initialized { - self.instance_info - .bridge - .clear_event_receive_handler(guard.deref_mut()); + self.instance_info.bridge.clear_event_receive_handler(guard.deref_mut()); } - self.instance_info - .bridge - .unsubscribe_to_event(guard.deref_mut()); + self.instance_info.bridge.unsubscribe_to_event(guard.deref_mut()); } } } @@ -562,30 +544,24 @@ impl LolaSubscriberImpl { /// does not exceed the maximum allowed and that the input values are within acceptable bounds. fn validate_receive_params(&self, new_samples: usize, max_samples: usize) -> Result<()> { if new_samples == 0 { - return Err(Error::ReceiveError( - ReceiveFailedReason::InputValueOutOfBounds { - max: self.max_num_samples, - requested: 0, - }, - )); + return Err(Error::ReceiveError(ReceiveFailedReason::InputValueOutOfBounds { + max: self.max_num_samples, + requested: 0, + })); } if new_samples > max_samples { - return Err(Error::ReceiveError( - ReceiveFailedReason::InputValueOutOfBounds { - max: max_samples, - requested: new_samples, - }, - )); + return Err(Error::ReceiveError(ReceiveFailedReason::InputValueOutOfBounds { + max: max_samples, + requested: new_samples, + })); } if max_samples > self.max_num_samples || new_samples > self.max_num_samples { - return Err(Error::ReceiveError( - ReceiveFailedReason::InputValueOutOfBounds { - max: self.max_num_samples, - requested: max_samples.max(new_samples), - }, - )); + return Err(Error::ReceiveError(ReceiveFailedReason::InputValueOutOfBounds { + max: self.max_num_samples, + requested: max_samples.max(new_samples), + })); } Ok(()) @@ -731,9 +707,7 @@ struct ReceiveFuture<'a, T: CommData + Debug, F: Future, B: FFIBrid type_ops: TypeOperationsManager, } -impl<'a, T: CommData + Debug, F: Future, B: FFIBridge> Future - for ReceiveFuture<'a, T, F, B> -{ +impl<'a, T: CommData + Debug, F: Future, B: FFIBridge> Future for ReceiveFuture<'a, T, F, B> { type Output = (SampleContainer>, Result); fn poll(mut self: Pin<&mut Self>, ctx: &mut Context<'_>) -> Poll { @@ -747,9 +721,7 @@ impl<'a, T: CommData + Debug, F: Future, B: FFIBridge> Future if self.cancellation.as_mut().poll(ctx).is_ready() { self.event_guard = None; return Poll::Ready(( - self.scratch - .take() - .expect("SampleContainer missing on cancellation"), + self.scratch.take().expect("SampleContainer missing on cancellation"), Err(Error::ReceiveError(ReceiveFailedReason::Cancelled)), )); } @@ -783,25 +755,25 @@ impl<'a, T: CommData + Debug, F: Future, B: FFIBridge> Future // Release the event guard to allow new receive calls to access the proxy event this.event_guard = None; Poll::Ready(( - this.scratch.take().expect( - "SampleContainer is not available when returning Future result", - ), + this.scratch + .take() + .expect("SampleContainer is not available when returning Future result"), Ok(this.total_received), )) } else { // Have some samples but not enough yet, wait for more via waker Poll::Pending } - } + }, Err(e) => { this.event_guard = None; Poll::Ready(( - this.scratch.take().expect( - "SampleContainer unavailable on error; was receive polled after completion?", - ), + this.scratch + .take() + .expect("SampleContainer unavailable on error; was receive polled after completion?"), Err(e), )) - } + }, } } } @@ -898,8 +870,7 @@ impl LolaConsumerDiscovery { } } -impl ServiceDiscovery> - for LolaConsumerDiscovery +impl ServiceDiscovery> for LolaConsumerDiscovery where LolaConsumerBuilder: ConsumerBuilder>, { @@ -909,9 +880,8 @@ where fn get_available_instances(&self) -> Result { //If ANY Support is added in Lola, then we need to return all available instances //Once FFI layer error handling is in place (SWP-253124), we should convert this error to a proper FFI error instead of using map_err here - let instance_specifier_lola = - bridge_ffi_rs::InstanceSpecifier::try_from(self.instance_specifier.as_ref()) - .map_err(|_| Error::ServiceError(ServiceFailedReason::InstanceSpecifierInvalid))?; + let instance_specifier_lola = bridge_ffi_rs::InstanceSpecifier::try_from(self.instance_specifier.as_ref()) + .map_err(|_| Error::ServiceError(ServiceFailedReason::InstanceSpecifierInvalid))?; let service_handle = self .bridge @@ -944,16 +914,13 @@ where /// The implementation uses an AtomicWaker to wake up the future when discovery results are /// received from the C++ callback, /// and it manages the shared state of discovery results using a Mutex. - fn get_available_instances_async( - &self, - ) -> impl Future> + Send { + fn get_available_instances_async(&self) -> impl Future> + Send { let instance_specifier = self.instance_specifier.clone(); // Convert to Lola InstanceSpecifier early //Once FFI layer error handling is in place (SWP-253124), we should convert this error to a proper FFI error instead of using map_err here - let instance_specifier_lola = - bridge_ffi_rs::InstanceSpecifier::try_from(instance_specifier.as_ref()) - .map_err(|_| Error::ServiceError(ServiceFailedReason::InstanceSpecifierInvalid)); + let instance_specifier_lola = bridge_ffi_rs::InstanceSpecifier::try_from(instance_specifier.as_ref()) + .map_err(|_| Error::ServiceError(ServiceFailedReason::InstanceSpecifierInvalid)); let waker_storage = Arc::new(futures::task::AtomicWaker::new()); @@ -968,18 +935,15 @@ where // intentionally ignored because the same handle is already captured // synchronously from `start_find_service`'s return value and stored // directly in `ServiceDiscoveryFuture`, eliminating the double-write race. - let discovery_callback = Box::new( - move |handles: HandleContainer, _find_handle: NativeFindServiceHandle| { - if let Ok(mut state) = state_ref.lock() { - state.handles = Some(handles); - } - waker_ref.wake(); - }, - ); + let discovery_callback = Box::new(move |handles: HandleContainer, _find_handle: NativeFindServiceHandle| { + if let Ok(mut state) = state_ref.lock() { + state.handles = Some(handles); + } + waker_ref.wake(); + }); - let dyn_callback: Box< - dyn FnMut(HandleContainer, NativeFindServiceHandle) + Send + 'static, - > = discovery_callback; + let dyn_callback: Box = + discovery_callback; // SAFETY: dyn_callback has the signature FnMut(HandleContainer, NativeFindServiceHandle) // which matches the find-service callback contract required by FindServiceCallable. @@ -992,9 +956,7 @@ where // stop_find_service is always called in Drop. let raw_handle = bridge.start_find_service(&callable, spec); if raw_handle.is_null() { - Err(Error::ServiceError( - ServiceFailedReason::FailedToStartDiscovery, - )) + Err(Error::ServiceError(ServiceFailedReason::FailedToStartDiscovery)) } else { // Single authoritative source of find_handle — return value only. // Callback's find_handle argument is ignored to prevent double-write. @@ -1049,10 +1011,7 @@ impl Drop for ServiceDiscoveryFuture { impl Future for ServiceDiscoveryFuture { type Output = Result>>; - fn poll( - self: std::pin::Pin<&mut Self>, - ctx: &mut std::task::Context<'_>, - ) -> std::task::Poll { + fn poll(self: std::pin::Pin<&mut Self>, ctx: &mut std::task::Context<'_>) -> std::task::Poll { // Register the waker so C++ callback can wake us up self.waker_storage.register(ctx.waker()); @@ -1095,14 +1054,9 @@ impl Future for ServiceDiscoveryFuture { } } -impl ConsumerBuilder> - for LolaConsumerBuilder -{ -} +impl ConsumerBuilder> for LolaConsumerBuilder {} -impl Builder>> - for LolaConsumerBuilder -{ +impl Builder>> for LolaConsumerBuilder { fn build(self) -> Result>> { Ok(Consumer::new(self.instance_info)) } @@ -1113,9 +1067,7 @@ pub struct LolaConsumerBuilder { pub _interface: PhantomData, } -impl ConsumerDescriptor> - for LolaConsumerBuilder -{ +impl ConsumerDescriptor> for LolaConsumerBuilder { fn get_instance_identifier(&self) -> &InstanceSpecifier { //if InstanceSpecifier::ANY support enable by lola //then this API should get InstanceSpecifier from FFI Call @@ -1145,20 +1097,16 @@ fn try_receive_samples( type_ops: &TypeOperationsManager, ) -> Result { if max_samples == 0 { - return Err(Error::ReceiveError( - ReceiveFailedReason::InputValueOutOfBounds { - max: max_num_samples, - requested: 0, - }, - )); + return Err(Error::ReceiveError(ReceiveFailedReason::InputValueOutOfBounds { + max: max_num_samples, + requested: 0, + })); } if max_samples > max_num_samples { - return Err(Error::ReceiveError( - ReceiveFailedReason::SampleCountOutOfBounds { - max: max_num_samples, - requested: max_samples, - }, - )); + return Err(Error::ReceiveError(ReceiveFailedReason::SampleCountOutOfBounds { + max: max_num_samples, + requested: max_samples, + })); } // Create a callback that will be called by the C++ side for each new sample arrival let mut callback = create_sample_callback::(bridge, scratch, max_samples, type_ops); @@ -1169,21 +1117,13 @@ fn try_receive_samples( let fat_ptr: FatPtr = unsafe { std::mem::transmute(dyn_callback) }; // SAFETY: event is a valid ProxyEventBase pointer obtained during subscription. // The lifetime of the callback is managed by Rust and will not outlive this function call. - let count = unsafe { - bridge.get_samples_from_event( - event as *mut ProxyEventBase, - type_ops, - &fat_ptr, - max_samples as u32, - ) - }; + let count = + unsafe { bridge.get_samples_from_event(event as *mut ProxyEventBase, type_ops, &fat_ptr, max_samples as u32) }; if count > max_samples as u32 { - return Err(Error::ReceiveError( - ReceiveFailedReason::SampleCountOutOfBounds { - max: max_samples, - requested: count as usize, - }, - )); + return Err(Error::ReceiveError(ReceiveFailedReason::SampleCountOutOfBounds { + max: max_samples, + requested: count as usize, + })); } Ok(count as usize) } @@ -1314,8 +1254,7 @@ mod test { .in_sequence(&mut seq) .returning(move |_, _| { Some(TypeOperationsManager::new( - NonNull::new(type_ops_alloc.allocate()) - .expect("Failed to allocate TypeOperations for mock"), + NonNull::new(type_ops_alloc.allocate()).expect("Failed to allocate TypeOperations for mock"), )) }); @@ -1329,14 +1268,9 @@ mod test { ); }); let prox_cleanup = proxy_alloc.clone(); - mock.expect_destroy_proxy() - .in_sequence(&mut seq) - .returning(move |ptr| { - assert!( - prox_cleanup.free(ptr), - "destroy_proxy called with unknown pointer" - ); - }); + mock.expect_destroy_proxy().in_sequence(&mut seq).returning(move |ptr| { + assert!(prox_cleanup.free(ptr), "destroy_proxy called with unknown pointer"); + }); // Create a single shared mock with all necessary expectations let bridge = SharedMockBridge::new(mock); @@ -1384,8 +1318,7 @@ mod test { .in_sequence(&mut seq) .returning(move |_, _| { Some(TypeOperationsManager::new( - NonNull::new(type_ops_alloc.allocate()) - .expect("Failed to allocate TypeOperations for mock"), + NonNull::new(type_ops_alloc.allocate()).expect("Failed to allocate TypeOperations for mock"), )) }); mock.expect_get_samples_from_event() @@ -1406,14 +1339,9 @@ mod test { "unsubscribe_to_event called with unknown pointer" ); }); - mock.expect_destroy_proxy() - .in_sequence(&mut seq) - .returning(move |ptr| { - assert!( - proxy_alloc.free(ptr), - "destroy_proxy called with unknown pointer" - ); - }); + mock.expect_destroy_proxy().in_sequence(&mut seq).returning(move |ptr| { + assert!(proxy_alloc.free(ptr), "destroy_proxy called with unknown pointer"); + }); // Create a single shared mock with all necessary expectations let bridge = SharedMockBridge::new(mock); @@ -1464,14 +1392,9 @@ mod test { .returning(|_, _| None); let prox_cleanup = proxy_alloc.clone(); - mock.expect_destroy_proxy() - .in_sequence(&mut seq) - .returning(move |ptr| { - assert!( - prox_cleanup.free(ptr), - "destroy_proxy called with unknown pointer" - ); - }); + mock.expect_destroy_proxy().in_sequence(&mut seq).returning(move |ptr| { + assert!(prox_cleanup.free(ptr), "destroy_proxy called with unknown pointer"); + }); let bridge = SharedMockBridge::new(mock); let subscribable = LolaSubscribableImpl:: { @@ -1483,10 +1406,7 @@ mod test { let result = subscribable.subscribe(3); assert!( - matches!( - result, - Err(Error::EventError(EventFailedReason::EventNotAvailable)) - ), + matches!(result, Err(Error::EventError(EventFailedReason::EventNotAvailable))), "subscribe must return EventNotAvailable when get_type_ops_instance returns None" ); diff --git a/score/mw/com/impl/rust/com-api/com-api-runtime-lola/lib.rs b/score/mw/com/impl/rust/com-api/com-api-runtime-lola/lib.rs index 1f9d80df66..e7b72b45e0 100644 --- a/score/mw/com/impl/rust/com-api/com-api-runtime-lola/lib.rs +++ b/score/mw/com/impl/rust/com-api/com-api-runtime-lola/lib.rs @@ -30,9 +30,7 @@ mod producer; mod runtime; pub use consumer::{LolaConsumerDiscovery, LolaConsumerInfo, LolaSample, LolaSubscribableImpl}; -pub use producer::{ - LolaProducerBuilder, LolaProviderInfo, LolaPublisher, LolaSampleMaybeUninit, LolaSampleMut, -}; +pub use producer::{LolaProducerBuilder, LolaProviderInfo, LolaPublisher, LolaSampleMaybeUninit, LolaSampleMut}; pub use runtime::{LolaRuntimeImpl, RuntimeBuilderImpl}; use core::fmt::Debug; diff --git a/score/mw/com/impl/rust/com-api/com-api-runtime-lola/producer.rs b/score/mw/com/impl/rust/com-api/com-api-runtime-lola/producer.rs index ad172f54e3..03dca7bcc9 100644 --- a/score/mw/com/impl/rust/com-api/com-api-runtime-lola/producer.rs +++ b/score/mw/com/impl/rust/com-api/com-api-runtime-lola/producer.rs @@ -39,9 +39,9 @@ use std::sync::Arc; use score_log as log; use score_com_concept::{ - AllocationFailureReason, Builder, CommData, Error, EventFailedReason, InstanceSpecifier, - Interface, Producer, ProducerBuilder, ProducerFailedReason, ProviderInfo, Publisher, Result, - SampleMaybeUninit, SampleMut, ServiceFailedReason, + AllocationFailureReason, Builder, CommData, Error, EventFailedReason, InstanceSpecifier, Interface, Producer, + ProducerBuilder, ProducerFailedReason, ProviderInfo, Publisher, Result, SampleMaybeUninit, SampleMut, + ServiceFailedReason, }; use bridge_ffi_rs::*; @@ -133,8 +133,7 @@ where } } -impl AsRef> - for AllocateePtrWrapper +impl AsRef> for AllocateePtrWrapper where T: CommData + Debug, { @@ -214,13 +213,11 @@ where // We've taken ownership via self (consumed, not borrowed), and // FFI call will complete before drop run on AllocateePtrWrapper and NativeSkeletonEventBase let status = unsafe { - self.allocatee_ptr - .bridge - .skeleton_event_send_sample_allocatee( - self.skeleton_event.skeleton_event_ptr.as_ptr(), - &self.allocatee_ptr.type_ops, - std::ptr::from_ref(self.allocatee_ptr.as_ref()) as *const std::ffi::c_void, - ) + self.allocatee_ptr.bridge.skeleton_event_send_sample_allocatee( + self.skeleton_event.skeleton_event_ptr.as_ptr(), + &self.allocatee_ptr.type_ops, + std::ptr::from_ref(self.allocatee_ptr.as_ref()) as *const std::ffi::c_void, + ) }; if !status { log::error!("Failed to send sample"); @@ -265,9 +262,7 @@ where type SampleMut = LolaSampleMut<'a, T, B>; fn write(mut self, val: T) -> LolaSampleMut<'a, T, B> { - let data_ptr = self - .get_allocatee_data_ptr() - .expect("Allocatee data pointer is null"); + let data_ptr = self.get_allocatee_data_ptr().expect("Allocatee data pointer is null"); //It is safe to write the value because data_ptr is valid // and we are writing the value of type T which is same as allocatee_ptr type @@ -294,8 +289,7 @@ where T: CommData + Debug, { fn as_mut(&mut self) -> &mut core::mem::MaybeUninit { - self.get_allocatee_data_ptr() - .expect("Allocatee data pointer is null") + self.get_allocatee_data_ptr().expect("Allocatee data pointer is null") } } @@ -336,17 +330,11 @@ unsafe impl Sync for NativeSkeletonHandle {} unsafe impl Send for NativeSkeletonHandle {} impl NativeSkeletonHandle { - pub fn new( - bridge: &B, - interface_id: &str, - instance_specifier: &bridge_ffi_rs::InstanceSpecifier, - ) -> Result { + pub fn new(bridge: &B, interface_id: &str, instance_specifier: &bridge_ffi_rs::InstanceSpecifier) -> Result { //SAFETY: It is safe as we are passing valid type id and instance specifier to create skeleton - let raw_handle = - unsafe { bridge.create_skeleton(interface_id, instance_specifier.as_native()) }; - let handle = std::ptr::NonNull::new(raw_handle).ok_or(Error::ProducerError( - ProducerFailedReason::SkeletonCreationFailed, - ))?; + let raw_handle = unsafe { bridge.create_skeleton(interface_id, instance_specifier.as_native()) }; + let handle = std::ptr::NonNull::new(raw_handle) + .ok_or(Error::ProducerError(ProducerFailedReason::SkeletonCreationFailed))?; Ok(Self { handle, bridge: bridge.clone(), @@ -378,10 +366,7 @@ pub struct NativeSkeletonEventBase { unsafe impl Send for NativeSkeletonEventBase {} impl NativeSkeletonEventBase { - pub fn new( - instance_info: &LolaProviderInfo, - identifier: &str, - ) -> Result { + pub fn new(instance_info: &LolaProviderInfo, identifier: &str) -> Result { //SAFETY: It is safe as we are passing valid skeleton handle and interface id to get event // skeleton handle is created during producer offer call let raw_event_ptr = unsafe { @@ -391,9 +376,8 @@ impl NativeSkeletonEventBase { identifier, ) }; - let skeleton_event_ptr = std::ptr::NonNull::new(raw_event_ptr).ok_or( - Error::ProducerError(ProducerFailedReason::SkeletonCreationFailed), - )?; + let skeleton_event_ptr = std::ptr::NonNull::new(raw_event_ptr) + .ok_or(Error::ProducerError(ProducerFailedReason::SkeletonCreationFailed))?; Ok(Self { skeleton_event_ptr }) } } @@ -436,8 +420,7 @@ where // allocatee_ptr is same type pointer which is allocated for T type and // it will be constructed in cpp side and moved back to rust side let allocatee_ptr = unsafe { - let mut sample = - core::mem::MaybeUninit::>::uninit(); + let mut sample = core::mem::MaybeUninit::>::uninit(); let status = self.skeleton_instance.0.bridge.get_allocatee_ptr( self.skeleton_event.skeleton_event_ptr.as_ptr(), sample.as_mut_ptr() as *mut std::ffi::c_void, @@ -496,26 +479,17 @@ impl LolaProducerBuilder { } } -impl ProducerBuilder> - for LolaProducerBuilder -{ -} +impl ProducerBuilder> for LolaProducerBuilder {} -impl Builder>> - for LolaProducerBuilder -{ +impl Builder>> for LolaProducerBuilder { fn build(self) -> Result>> { //Once FFI layer error handling is in place (SWP-253124), we should convert this error to a proper FFI error instead of using map_err here - let instance_specifier_runtime = bridge_ffi_rs::InstanceSpecifier::try_from( - self.instance_specifier.as_ref(), - ) - .map_err(|_| Error::ProducerError(ProducerFailedReason::InstanceSpecifierInvalid))?; - - let skeleton_handle = NativeSkeletonHandle::::new( - &self.bridge, - I::INTERFACE_ID, - &instance_specifier_runtime, - )?; + let instance_specifier_runtime = + bridge_ffi_rs::InstanceSpecifier::try_from(self.instance_specifier.as_ref()) + .map_err(|_| Error::ProducerError(ProducerFailedReason::InstanceSpecifierInvalid))?; + + let skeleton_handle = + NativeSkeletonHandle::::new(&self.bridge, I::INTERFACE_ID, &instance_specifier_runtime)?; let instance_info = LolaProviderInfo { instance_specifier: self.instance_specifier, interface_id: I::INTERFACE_ID, @@ -531,9 +505,9 @@ impl Builder>> mod test { use super::*; use bridge_ffi_mock::{MockFFIBridge, MockPointerAllocator, SharedMockBridge}; - use score_com_concept::{InstanceSpecifier}; use mockall::predicate::*; use mockall::Sequence; + use score_com_concept::InstanceSpecifier; #[derive(Debug, Default)] #[repr(C)] @@ -549,20 +523,15 @@ mod test { // Creates a `NativeSkeletonHandle` . fn make_skeleton_handle(bridge: &SharedMockBridge) -> NativeSkeletonHandle { - let spec = bridge_ffi_rs::InstanceSpecifier::try_from("/test_instance") - .expect("valid instance specifier"); + let spec = bridge_ffi_rs::InstanceSpecifier::try_from("/test_instance").expect("valid instance specifier"); NativeSkeletonHandle::::new(&bridge, "", &spec) .expect("SharedMockBridge::create_skeleton should not fail") } // Creates a `LolaProviderInfo` with a valid heap-backed skeleton handle. - fn make_provider_info( - interface_id: &'static str, - bridge: &SharedMockBridge, - ) -> LolaProviderInfo { + fn make_provider_info(interface_id: &'static str, bridge: &SharedMockBridge) -> LolaProviderInfo { LolaProviderInfo { - instance_specifier: InstanceSpecifier::new("/test_instance") - .expect("valid instance specifier"), + instance_specifier: InstanceSpecifier::new("/test_instance").expect("valid instance specifier"), interface_id, skeleton_handle: SkeletonInstanceManager(Arc::new(make_skeleton_handle(&bridge))), bridge: bridge.clone(), @@ -594,10 +563,7 @@ mod test { mock.expect_destroy_skeleton() .in_sequence(&mut seq) .returning(move |ptr| { - assert!( - skel_cleanup.free(ptr), - "destroy_skeleton called with unknown pointer" - ); + assert!(skel_cleanup.free(ptr), "destroy_skeleton called with unknown pointer"); }); let bridge = SharedMockBridge::new(mock); @@ -639,8 +605,7 @@ mod test { .in_sequence(&mut seq) .returning(move |_, _| { Some(TypeOperationsManager::new( - NonNull::new(type_ops_alloc.allocate()) - .expect("Failed to allocate TypeOperations for mock"), + NonNull::new(type_ops_alloc.allocate()).expect("Failed to allocate TypeOperations for mock"), )) }); @@ -676,15 +641,12 @@ mod test { }); let bridge = SharedMockBridge::new(mock); - let spec = bridge_ffi_rs::InstanceSpecifier::try_from("/test_instance") - .expect("valid instance specifier"); - let skeleton_handle = - NativeSkeletonHandle::::new(&bridge, "TestData", &spec) - .expect("SharedMockBridge::create_skeleton should not fail"); + let spec = bridge_ffi_rs::InstanceSpecifier::try_from("/test_instance").expect("valid instance specifier"); + let skeleton_handle = NativeSkeletonHandle::::new(&bridge, "TestData", &spec) + .expect("SharedMockBridge::create_skeleton should not fail"); let instance_info = LolaProviderInfo { - instance_specifier: InstanceSpecifier::new("/test_instance") - .expect("valid instance specifier"), + instance_specifier: InstanceSpecifier::new("/test_instance").expect("valid instance specifier"), interface_id: "TestData", skeleton_handle: SkeletonInstanceManager(Arc::new(skeleton_handle)), bridge: bridge.clone(), diff --git a/score/mw/com/impl/rust/com-api/com-api-runtime-lola/runtime.rs b/score/mw/com/impl/rust/com-api/com-api-runtime-lola/runtime.rs index 7d87da8200..057cdf2b56 100644 --- a/score/mw/com/impl/rust/com-api/com-api-runtime-lola/runtime.rs +++ b/score/mw/com/impl/rust/com-api/com-api-runtime-lola/runtime.rs @@ -16,12 +16,10 @@ use core::marker::PhantomData; use std::path::{Path, PathBuf}; use crate::{ - LolaConsumerDiscovery, LolaConsumerInfo, LolaProducerBuilder, LolaProviderInfo, LolaPublisher, - LolaSubscribableImpl, + LolaConsumerDiscovery, LolaConsumerInfo, LolaProducerBuilder, LolaProviderInfo, LolaPublisher, LolaSubscribableImpl, }; use score_com_concept::{ - Builder, CommData, FindServiceSpecifier, InstanceSpecifier, Interface, Result, Runtime, - RuntimeBuilder, + Builder, CommData, FindServiceSpecifier, InstanceSpecifier, Interface, Result, Runtime, RuntimeBuilder, }; use bridge_ffi_lola::LolaFFIBridge; @@ -39,10 +37,7 @@ impl Runtime for LolaRuntimeImpl { type ProviderInfo = LolaProviderInfo; type ConsumerInfo = LolaConsumerInfo; - fn find_service( - &self, - instance_specifier: FindServiceSpecifier, - ) -> Self::ServiceDiscovery { + fn find_service(&self, instance_specifier: FindServiceSpecifier) -> Self::ServiceDiscovery { LolaConsumerDiscovery { instance_specifier: match instance_specifier { FindServiceSpecifier::Any => panic!( @@ -56,10 +51,7 @@ impl Runtime for LolaRuntimeImpl { } } - fn producer_builder( - &self, - instance_specifier: InstanceSpecifier, - ) -> Self::ProducerBuilder { + fn producer_builder(&self, instance_specifier: InstanceSpecifier) -> Self::ProducerBuilder { LolaProducerBuilder::new(self, instance_specifier) } } diff --git a/score/mw/com/impl/rust/com-api/com-api-runtime-mock/BUILD b/score/mw/com/impl/rust/com-api/com-api-runtime-mock/BUILD index 01522f2761..e2851f52d8 100644 --- a/score/mw/com/impl/rust/com-api/com-api-runtime-mock/BUILD +++ b/score/mw/com/impl/rust/com-api/com-api-runtime-mock/BUILD @@ -16,7 +16,7 @@ load("@rules_rust//rust:defs.bzl", "rust_library") rust_library( name = "com-api-runtime-mock", srcs = ["runtime.rs"], - edition = "2024", + edition = "2021", visibility = ["//score/mw/com:__subpackages__"], deps = [ "//score/mw/com/rust/score_com_concept", diff --git a/score/mw/com/impl/rust/com-api/com-api-runtime-mock/runtime.rs b/score/mw/com/impl/rust/com-api/com-api-runtime-mock/runtime.rs index fceb5b082c..639019ffa5 100644 --- a/score/mw/com/impl/rust/com-api/com-api-runtime-mock/runtime.rs +++ b/score/mw/com/impl/rust/com-api/com-api-runtime-mock/runtime.rs @@ -36,10 +36,9 @@ use std::collections::VecDeque; use std::path::Path; use score_com_concept::{ - Builder, CommData, Consumer, ConsumerBuilder, ConsumerDescriptor, FindServiceSpecifier, - InstanceSpecifier, Interface, Producer, ProducerBuilder, ProviderInfo, Publisher, Result, - Runtime, RuntimeBuilder, Sample, SampleContainer, SampleMaybeUninit, SampleMut, - ServiceDiscovery, Subscriber, Subscription, + Builder, CommData, Consumer, ConsumerBuilder, ConsumerDescriptor, FindServiceSpecifier, InstanceSpecifier, + Interface, Producer, ProducerBuilder, ProviderInfo, Publisher, Result, Runtime, RuntimeBuilder, Sample, + SampleContainer, SampleMaybeUninit, SampleMut, ServiceDiscovery, Subscriber, Subscription, }; pub struct MockRuntimeImpl {} @@ -81,10 +80,7 @@ impl Runtime for MockRuntimeImpl { } } - fn producer_builder( - &self, - instance_specifier: InstanceSpecifier, - ) -> Self::ProducerBuilder { + fn producer_builder(&self, instance_specifier: InstanceSpecifier) -> Self::ProducerBuilder { MockProducerBuilder::new(self, instance_specifier) } } @@ -412,9 +408,7 @@ where } #[allow(clippy::manual_async_fn)] - fn get_available_instances_async( - &self, - ) -> impl Future> + Send { + fn get_available_instances_async(&self) -> impl Future> + Send { async { Ok(Vec::new()) } } } @@ -520,12 +514,8 @@ mod test { match receive_result { Ok(0) => panic!("No sample received"), Ok(x) => { - println!( - "{} samples received: sample[0] = {}", - x, - *sample_buf.front().unwrap() - ) - } + println!("{} samples received: sample[0] = {}", x, *sample_buf.front().unwrap()) + }, Err(e) => panic!("{:?}", e), } } @@ -539,7 +529,7 @@ mod test { let sample_buf = SampleContainer::new(1); let (_returned_buf, result) = test_subscriber.receive(sample_buf, 1, 1).await; match result { - Ok(()) => {} + Ok(()) => {}, Err(e) => panic!("{:?}", e), } }) diff --git a/score/mw/com/rust/BUILD b/score/mw/com/rust/BUILD index 4b9d464ea5..5d3cc4686d 100644 --- a/score/mw/com/rust/BUILD +++ b/score/mw/com/rust/BUILD @@ -18,7 +18,7 @@ rust_library( name = "score_com", srcs = ["score_com.rs"], crate_name = "score_com", - edition = "2024", + edition = "2021", visibility = [ "//visibility:public", # platform_only ], @@ -36,7 +36,7 @@ rust_library( testonly = True, srcs = ["score_com_mock.rs"], crate_name = "score_com", - edition = "2024", + edition = "2021", visibility = [ "//visibility:public", ], diff --git a/score/mw/com/rust/score_com.rs b/score/mw/com/rust/score_com.rs index d16ae15b14..3ffe69fc46 100644 --- a/score/mw/com/rust/score_com.rs +++ b/score/mw/com/rust/score_com.rs @@ -135,11 +135,10 @@ pub use com_api_runtime_lola::LolaRuntimeImpl; pub use com_api_runtime_lola::RuntimeBuilderImpl as LolaRuntimeBuilderImpl; pub use score_com_concept::{ - interface, interface_common, interface_consumer, interface_producer, Builder, CommData, - Consumer, ConsumerBuilder, ConsumerDescriptor, Error, FindServiceSpecifier, InstanceSpecifier, - Interface, OfferedProducer, PlacementDefault, Producer, ProducerBuilder, ProviderInfo, - Publisher, Reloc, Result, Runtime, RuntimeBuilder, SampleContainer, SampleMaybeUninit, - SampleMut, ServiceDiscovery, Subscriber, Subscription, + interface, interface_common, interface_consumer, interface_producer, Builder, CommData, Consumer, ConsumerBuilder, + ConsumerDescriptor, Error, FindServiceSpecifier, InstanceSpecifier, Interface, OfferedProducer, PlacementDefault, + Producer, ProducerBuilder, ProviderInfo, Publisher, Reloc, Result, Runtime, RuntimeBuilder, SampleContainer, + SampleMaybeUninit, SampleMut, ServiceDiscovery, Subscriber, Subscription, }; #[doc(hidden)] diff --git a/score/mw/com/rust/score_com_concept/BUILD b/score/mw/com/rust/score_com_concept/BUILD index 2f557d48ec..59b4da3f61 100644 --- a/score/mw/com/rust/score_com_concept/BUILD +++ b/score/mw/com/rust/score_com_concept/BUILD @@ -17,7 +17,7 @@ load("//quality/unit_testing:unit_testing.bzl", "rust_unit_test") rust_library( name = "score_com_concept", srcs = glob(["**/*.rs"]), - edition = "2024", + edition = "2021", proc_macro_deps = [ "//score/mw/com/rust/score_com_macros:score-com-macros", "@score_communication_crate_index//:paste", @@ -36,7 +36,7 @@ rust_library( rust_test( name = "score_com_concept-test", crate = ":score_com_concept", - edition = "2024", + edition = "2021", tags = ["manual"], deps = [":score_com_concept"], ) diff --git a/score/mw/com/rust/score_com_concept/concept.rs b/score/mw/com/rust/score_com_concept/concept.rs index 8e5f7601ba..bfe3162923 100644 --- a/score/mw/com/rust/score_com_concept/concept.rs +++ b/score/mw/com/rust/score_com_concept/concept.rs @@ -50,12 +50,12 @@ use crate::error::*; use crate::Reloc; -pub use score_com_macros::CommData; use containers::fixed_capacity::FixedCapacityQueue; use core::fmt::Debug; use core::future::Future; use core::ops::{Deref, DerefMut}; use futures::stream::Stream; +pub use score_com_macros::CommData; use std::path::Path; /// Result type alias with `std::result::Result` using `score_com::Error` as error type @@ -118,10 +118,7 @@ pub trait Runtime { /// /// # Returns /// Service discovery handle for querying available instances - fn find_service( - &self, - instance_specifier: FindServiceSpecifier, - ) -> Self::ServiceDiscovery; + fn find_service(&self, instance_specifier: FindServiceSpecifier) -> Self::ServiceDiscovery; /// Create a producer builder for the given interface and producer type. /// Constructs a producer builder for offering services. @@ -133,10 +130,7 @@ pub trait Runtime { /// # Returns /// /// A configured builder ready for finalization via `build()` - fn producer_builder( - &self, - instance_specifier: InstanceSpecifier, - ) -> Self::ProducerBuilder; + fn producer_builder(&self, instance_specifier: InstanceSpecifier) -> Self::ProducerBuilder; } /// This trait contains the APIs required for producer service instance management. @@ -239,9 +233,8 @@ impl InstanceSpecifier { // Check each character // Allowed: digits, lowercase, uppercase, underscore - let is_legal_char = |c: char| { - c.is_ascii_digit() || c.is_ascii_lowercase() || c.is_ascii_uppercase() || c == '_' - }; + let is_legal_char = + |c: char| c.is_ascii_digit() || c.is_ascii_lowercase() || c.is_ascii_uppercase() || c == '_'; //validation of each path segment !service_name.is_empty() @@ -272,9 +265,7 @@ impl InstanceSpecifier { specifier: service_name.to_string(), }) } else { - Err(Error::ServiceError( - ServiceFailedReason::InstanceSpecifierInvalid, - )) + Err(Error::ServiceError(ServiceFailedReason::InstanceSpecifierInvalid)) } } } @@ -588,9 +579,7 @@ pub trait ServiceDiscovery { /// # Errors /// Returns 'Error' if the query operation fails. #[allow(clippy::manual_async_fn)] - fn get_available_instances_async( - &self, - ) -> impl Future> + Send; + fn get_available_instances_async(&self) -> impl Future> + Send; } /// Metadata and identification for a discovered service instance. @@ -613,10 +602,7 @@ pub trait ConsumerDescriptor { /// # Type Parameters /// * `I` - The service interface /// * `R` - The runtime managing the consumer -pub trait ConsumerBuilder: - ConsumerDescriptor + Builder> -{ -} +pub trait ConsumerBuilder: ConsumerDescriptor + Builder> {} /// Event subscription management interface. /// @@ -858,12 +844,7 @@ pub trait Subscription { new_samples: usize, max_samples: usize, ) -> impl Future>, Result)> + 'a { - self.cancellable_receive( - scratch, - new_samples, - max_samples, - core::future::pending::<()>(), - ) + self.cancellable_receive(scratch, new_samples, max_samples, core::future::pending::<()>()) } /// This method is an extension of `receive` with an additional `cancellation` parameter @@ -982,11 +963,7 @@ mod tests { ]; for spec in &valid_specifiers { - assert!( - InstanceSpecifier::check_str(spec), - "Expected '{}' to be valid", - spec - ); + assert!(InstanceSpecifier::check_str(spec), "Expected '{}' to be valid", spec); } // Invalid specifiers @@ -1004,11 +981,7 @@ mod tests { ]; for spec in &invalid_specifiers { - assert!( - !InstanceSpecifier::check_str(spec), - "Expected '{}' to be invalid", - spec - ); + assert!(!InstanceSpecifier::check_str(spec), "Expected '{}' to be invalid", spec); } } } diff --git a/score/mw/com/rust/score_com_concept/error.rs b/score/mw/com/rust/score_com_concept/error.rs index d9b6a7305c..79e49eb91c 100644 --- a/score/mw/com/rust/score_com_concept/error.rs +++ b/score/mw/com/rust/score_com_concept/error.rs @@ -23,7 +23,9 @@ use thiserror::Error; /// including specific issues with service interfaces, instance specifiers, and handle retrieval. #[derive(Debug, ScoreDebug, Error)] pub enum ServiceFailedReason { - #[error("Invalid instance specifier format or content, which may not be according to the expected format or contain invalid content")] + #[error( + "Invalid instance specifier format or content, which may not be according to the expected format or contain invalid content" + )] InstanceSpecifierInvalid, #[error("Service not found, which may not be available currently or accessible")] ServiceNotFound, @@ -36,7 +38,9 @@ pub enum ServiceFailedReason { /// Reason for producer failure #[derive(Debug, ScoreDebug, Error)] pub enum ProducerFailedReason { - #[error("Invalid instance specifier format or content, which may not be according to the expected format or contain invalid content")] + #[error( + "Invalid instance specifier format or content, which may not be according to the expected format or contain invalid content" + )] InstanceSpecifierInvalid, #[error("Skeleton creation failed")] SkeletonCreationFailed, @@ -47,7 +51,9 @@ pub enum ProducerFailedReason { /// Reason for consumer failure #[derive(Debug, ScoreDebug, Error)] pub enum ConsumerFailedReason { - #[error("Invalid instance specifier format or content, which may not be according to the expected format or contain invalid content")] + #[error( + "Invalid instance specifier format or content, which may not be according to the expected format or contain invalid content" + )] InstanceSpecifierInvalid, #[error("Service not found from service discovery handle")] ServiceHandleNotFound, @@ -58,9 +64,7 @@ pub enum ConsumerFailedReason { /// Memory allocation error details #[derive(Debug, ScoreDebug, Error)] pub enum AllocationFailureReason { - #[error( - "Requested size exceeds available memory which is configured during subscription setup" - )] + #[error("Requested size exceeds available memory which is configured during subscription setup")] OutOfMemory, #[error("Invalid allocation request")] InvalidRequest, @@ -98,7 +102,9 @@ pub enum EventFailedReason { SendingDataFailed, #[error("Event not available for subscription, possibly due to missing event type or incompatible service")] EventNotAvailable, - #[error("Failed to subscribe to event, due to the max_samples parameter being invalid (e.g., zero or exceeding allowed limits)")] + #[error( + "Failed to subscribe to event, due to the max_samples parameter being invalid (e.g., zero or exceeding allowed limits)" + )] InvalidMaxSamples, #[error("Sample count out of bounds, expected at most {max}, but got {requested}")] MaxSampleOutOfBounds { max: usize, requested: usize }, diff --git a/score/mw/com/rust/score_com_concept/interface_macros.rs b/score/mw/com/rust/score_com_concept/interface_macros.rs index 46cae701f7..5394e07810 100644 --- a/score/mw/com/rust/score_com_concept/interface_macros.rs +++ b/score/mw/com/rust/score_com_concept/interface_macros.rs @@ -760,10 +760,7 @@ mod validation_tests { // the compiler enforces the name at compile time. let interface_id = ::INTERFACE_ID; let expected_id = concat!(module_path!(), "::", "Vehicle"); - assert_eq!( - interface_id, expected_id, - "Interface ID mismatch for VehicleInterface" - ); + assert_eq!(interface_id, expected_id, "Interface ID mismatch for VehicleInterface"); } } test_module::validate(); @@ -773,8 +770,7 @@ mod validation_tests { fn test_consumer_type_generated() { mod test_module { use score_com::{ - CommData, Consumer, LolaRuntimeImpl as LolaRuntime, ProviderInfo, Publisher, Reloc, - Subscriber, + CommData, Consumer, LolaRuntimeImpl as LolaRuntime, ProviderInfo, Publisher, Reloc, Subscriber, }; #[derive(Debug, Reloc, Clone)] @@ -818,8 +814,7 @@ mod validation_tests { fn test_producer_type_generated() { mod test_module { use score_com::{ - CommData, LolaRuntimeImpl as LolaRuntime, Producer, ProviderInfo, Publisher, Reloc, - Subscriber, + CommData, LolaRuntimeImpl as LolaRuntime, Producer, ProviderInfo, Publisher, Reloc, Subscriber, }; #[derive(Debug, Reloc, Clone)] @@ -849,8 +844,7 @@ mod validation_tests { fn test_offered_producer_type_generated() { mod test_module { use score_com::{ - CommData, LolaRuntimeImpl as LolaRuntime, Producer, ProviderInfo, Publisher, Reloc, - Subscriber, + CommData, LolaRuntimeImpl as LolaRuntime, Producer, ProviderInfo, Publisher, Reloc, Subscriber, }; #[derive(Debug, Reloc, Clone)] @@ -919,8 +913,7 @@ mod validation_tests { fn test_interface_with_multiple_events_validation() { mod test_module { use score_com::{ - CommData, Interface, LolaRuntimeImpl as LolaRuntime, ProviderInfo, Publisher, - Reloc, Subscriber, + CommData, Interface, LolaRuntimeImpl as LolaRuntime, ProviderInfo, Publisher, Reloc, Subscriber, }; #[derive(Debug, Reloc, Clone)] @@ -981,8 +974,7 @@ mod validation_tests { fn test_interface_type_consistency_across_traits() { mod test_module { use score_com::{ - CommData, Interface, LolaRuntimeImpl as LolaRuntime, ProviderInfo, Publisher, - Reloc, Subscriber, + CommData, Interface, LolaRuntimeImpl as LolaRuntime, ProviderInfo, Publisher, Reloc, Subscriber, }; #[derive(Debug, Reloc, Clone)] @@ -1022,10 +1014,7 @@ mod validation_tests { #[test] fn test_interface_naming_convention_validation() { mod test_module { - use score_com::{ - CommData, LolaRuntimeImpl as LolaRuntime, ProviderInfo, Publisher, Reloc, - Subscriber, - }; + use score_com::{CommData, LolaRuntimeImpl as LolaRuntime, ProviderInfo, Publisher, Reloc, Subscriber}; #[derive(Debug, Reloc, Clone)] #[repr(C)] diff --git a/score/mw/com/rust/score_com_macros/lib.rs b/score/mw/com/rust/score_com_macros/lib.rs index e09f434026..c32ea2c6fe 100644 --- a/score/mw/com/rust/score_com_macros/lib.rs +++ b/score/mw/com/rust/score_com_macros/lib.rs @@ -80,15 +80,15 @@ pub fn derive_comm_data(input: TokenStream) -> TokenStream { Ok(Some(user_id)) => { // User-provided ID quote! { #user_id } - } + }, Ok(None) => { // Auto-generated: use fully qualified type name with module_path!() quote! { concat!(module_path!(), "::", stringify!(#ident_name)) } - } + }, Err(err) => { // Propagate the error to the compiler return err.to_compile_error().into(); - } + }, }; let comm_data_impl = quote! { @@ -107,46 +107,28 @@ fn extract_id_from_attribute(attrs: &[syn::Attribute]) -> Result, } let Meta::List(list) = &attr.meta else { - return Err(syn::Error::new_spanned( - attr, - "Expected #[comm_data(id = \"...\")]", - )); + return Err(syn::Error::new_spanned(attr, "Expected #[comm_data(id = \"...\")]")); }; let Ok(Meta::NameValue(nv)) = list.parse_args::() else { - return Err(syn::Error::new_spanned( - attr, - "Expected #[comm_data(id = \"...\")]", - )); + return Err(syn::Error::new_spanned(attr, "Expected #[comm_data(id = \"...\")]")); }; if !nv.path.is_ident("id") { - return Err(syn::Error::new_spanned( - nv.path, - "Expected #[comm_data(id = \"...\")]", - )); + return Err(syn::Error::new_spanned(nv.path, "Expected #[comm_data(id = \"...\")]")); } let syn::Expr::Lit(expr_lit) = &nv.value else { - return Err(syn::Error::new_spanned( - nv.value, - "Expected a string literal value", - )); + return Err(syn::Error::new_spanned(nv.value, "Expected a string literal value")); }; let syn::Lit::Str(lit_str) = &expr_lit.lit else { - return Err(syn::Error::new_spanned( - expr_lit, - "Expected a string literal value", - )); + return Err(syn::Error::new_spanned(expr_lit, "Expected a string literal value")); }; let id_value = lit_str.value(); if id_value.is_empty() { - return Err(syn::Error::new_spanned( - expr_lit, - "The id cannot be an empty string", - )); + return Err(syn::Error::new_spanned(expr_lit, "The id cannot be an empty string")); } return Ok(Some(id_value)); @@ -173,11 +155,7 @@ fn check_enum_variants( ) -> Result<(), syn::Error> { for variant in variants { // Find #[comm_data(...)] attribute on the variant - if let Some(attr) = variant - .attrs - .iter() - .find(|a| a.path().is_ident("comm_data")) - { + if let Some(attr) = variant.attrs.iter().find(|a| a.path().is_ident("comm_data")) { return Err(syn::Error::new_spanned( attr, "#[comm_data(id = \"...\")] must be placed on the type, not on an enum variant", @@ -200,7 +178,7 @@ fn check_attrs(fields: &Fields) -> Result<(), syn::Error> { } } Ok(()) - } + }, Fields::Unnamed(f) => { for field in &f.unnamed { if let Some(attr) = field.attrs.iter().find(|a| a.path().is_ident("comm_data")) { @@ -211,7 +189,7 @@ fn check_attrs(fields: &Fields) -> Result<(), syn::Error> { } } Ok(()) - } + }, Fields::Unit => Ok(()), // Unit variants have no fields, nothing to check } } @@ -235,12 +213,9 @@ pub fn derive_reloc(input: TokenStream) -> TokenStream { // Ensure #[repr(C)] on the struct itself if !has_repr_c(&input_args.attrs) { - return syn::Error::new_spanned( - ident_name, - "The #[derive(Reloc)] macro requires #[repr(C)] on the type", - ) - .to_compile_error() - .into(); + return syn::Error::new_spanned(ident_name, "The #[derive(Reloc)] macro requires #[repr(C)] on the type") + .to_compile_error() + .into(); } let mut generics = create_bounds_with_reloc(input_args.generics.clone()); @@ -264,8 +239,8 @@ pub fn derive_reloc(input: TokenStream) -> TokenStream { tuple structs", ) .to_compile_error() - .into() - } + .into(); + }, }; { @@ -319,7 +294,7 @@ fn collect_field_types(data: &Data) -> Result, ()> { Fields::Unnamed(fields) => fields.unnamed.iter().map(|f| &f.ty).collect(), Fields::Unit => Vec::new(), }; - } + }, Data::Enum(data_enum) => { if !data_enum .variants @@ -328,7 +303,7 @@ fn collect_field_types(data: &Data) -> Result, ()> { { return Err(()); } - } + }, Data::Union(_) => return Err(()), }; diff --git a/score/mw/com/rust/score_com_mock.rs b/score/mw/com/rust/score_com_mock.rs index 6649234f6b..3aab72d903 100644 --- a/score/mw/com/rust/score_com_mock.rs +++ b/score/mw/com/rust/score_com_mock.rs @@ -15,6 +15,6 @@ //! //! Depend on `//score/mw/com/rust:score_com_mock` (instead of `:score_com`). -pub use score_com::*; pub use com_api_runtime_mock::MockRuntimeImpl; pub use com_api_runtime_mock::RuntimeBuilderImpl as MockRuntimeBuilderImpl; +pub use score_com::*; diff --git a/score/mw/com/test/basic_rust_api/consumer_async_apis/consumer_app.rs b/score/mw/com/test/basic_rust_api/consumer_async_apis/consumer_app.rs index c1aa6c186c..d96effb9b1 100644 --- a/score/mw/com/test/basic_rust_api/consumer_async_apis/consumer_app.rs +++ b/score/mw/com/test/basic_rust_api/consumer_async_apis/consumer_app.rs @@ -26,14 +26,14 @@ use bigdata_com_api_gen::{BigDataInterface, MapApiLanesStamped}; use clap::Parser; -use score_com::{ - Builder, FindServiceSpecifier, InstanceSpecifier, LolaRuntimeBuilderImpl, Runtime, - RuntimeBuilder, SampleContainer, ServiceDiscovery, Subscriber, Subscription, -}; use core::time::Duration; use core::unreachable; use futures::channel::oneshot; use futures::{FutureExt, StreamExt}; +use score_com::{ + Builder, FindServiceSpecifier, InstanceSpecifier, LolaRuntimeBuilderImpl, Runtime, RuntimeBuilder, SampleContainer, + ServiceDiscovery, Subscriber, Subscription, +}; use std::path::Path; use std::sync::mpsc; use std::thread; @@ -82,11 +82,11 @@ async fn receive_without_cancellation( println!("[bigdata-consumer] Sample x: {}", sample.x); } buffer = buf; - } + }, Err(e) => { eprintln!("[bigdata-consumer] Failed to receive samples: {:?}", e); buffer = returned_buf; - } + }, } total_cycle += 1; if total_cycle >= num_cycles { @@ -120,9 +120,7 @@ async fn receive_with_cancellation( while total_cycle < num_cycles { // Request a timeout from the shared timer thread. let (tx, rx) = oneshot::channel(); - timer_tx - .send(tx) - .expect("Timer thread unexpectedly stopped"); + timer_tx.send(tx).expect("Timer thread unexpectedly stopped"); // Map the receiver to resolve to () instead of Result<(), Canceled> let timeout_future = rx.map(|_| ()); @@ -140,12 +138,12 @@ async fn receive_with_cancellation( println!("[bigdata-consumer] Sample x: {}", sample.x); } buffer = buf; - } + }, Err(e) => { // Just for demonstration, we are printing the error, but in a real application you would likely handle it differently. eprintln!("[bigdata-consumer] Receive error or timeout: {:?}", e); buffer = returned_buf; - } + }, } total_cycle += 1; if total_cycle >= num_cycles { @@ -158,10 +156,7 @@ async fn receive_with_cancellation( /// Receives samples one at a time as they are published by the producer, printing each sample's `x` field until the specified number of samples have been received. /// The stream will end if the subscription is cancelled or if the consumer is shut down, but will not end on receive errors instead, /// errors are returned as part of the stream and can be handled by the consumer while continuing to receive future samples. -async fn receive_stream( - mut subscription: impl Subscription, - num_cycles: usize, -) { +async fn receive_stream(mut subscription: impl Subscription, num_cycles: usize) { let mut stream = subscription.to_stream(); let mut total_cycle = 0; @@ -171,12 +166,12 @@ async fn receive_stream( match stream.next().await { Some(Ok(sample)) => { println!("[bigdata-consumer] Stream received sample x: {}", sample.x); - } + }, //when error received from stream, here we are just printing it, but in a real application you would likely handle it differently based on user needs and error type. //But library never ends the stream, it will keep retrying to receive samples until the subscription is cancelled or the consumer is shut down. Some(Err(e)) => { eprintln!("[bigdata-consumer] Stream error: {:?}", e); - } + }, None => unreachable!("Stream never sends None"), } total_cycle += 1; @@ -199,15 +194,12 @@ async fn async_main() { // Initialise the Lola runtime. let mut runtime_builder: LolaRuntimeBuilderImpl = LolaRuntimeBuilderImpl::new(); runtime_builder.load_config(Path::new(CONFIG_PATH)); - let runtime = runtime_builder - .build() - .expect("Failed to build Lola runtime"); + let runtime = runtime_builder.build().expect("Failed to build Lola runtime"); - let instance_specifier = InstanceSpecifier::new("/score/cp60/MapApiLanesStamped") - .expect("Invalid instance specifier"); + let instance_specifier = + InstanceSpecifier::new("/score/cp60/MapApiLanesStamped").expect("Invalid instance specifier"); - let discovery = runtime - .find_service::(FindServiceSpecifier::Specific(instance_specifier)); + let discovery = runtime.find_service::(FindServiceSpecifier::Specific(instance_specifier)); // Await the producer to become available. let instances = discovery @@ -215,10 +207,7 @@ async fn async_main() { .await .expect("Failed to get available instances"); - let builder = instances - .into_iter() - .next() - .expect("No service instances available"); + let builder = instances.into_iter().next().expect("No service instances available"); let consumer = builder.build().expect("Failed to build consumer"); // Subscribe with a slot buffer large enough for MAX_SAMPLES_PER_CALL. @@ -228,15 +217,10 @@ async fn async_main() { .expect("Failed to subscribe to map_api_lanes_stamped_"); match args.receive_mode { - ReceiveMode::WithoutCancellation => { - receive_without_cancellation(subscription, num_cycles).await - } + ReceiveMode::WithoutCancellation => receive_without_cancellation(subscription, num_cycles).await, ReceiveMode::WithCancellation => receive_with_cancellation(subscription, num_cycles).await, ReceiveMode::Stream => receive_stream(subscription, num_cycles).await, } - println!( - "[bigdata-consumer] Completed {} receive attempts, exiting", - num_cycles - ); + println!("[bigdata-consumer] Completed {} receive attempts, exiting", num_cycles); } diff --git a/score/mw/com/test/basic_rust_api/consumer_sync_apis/consumer_app.rs b/score/mw/com/test/basic_rust_api/consumer_sync_apis/consumer_app.rs index ba680639bd..358b76dffc 100644 --- a/score/mw/com/test/basic_rust_api/consumer_sync_apis/consumer_app.rs +++ b/score/mw/com/test/basic_rust_api/consumer_sync_apis/consumer_app.rs @@ -28,8 +28,8 @@ use bigdata_com_api_gen::{ }; use clap::Parser; use score_com::{ - Builder, FindServiceSpecifier, InstanceSpecifier, LolaRuntimeBuilderImpl, Result, Runtime, - RuntimeBuilder, SampleContainer, ServiceDiscovery, Subscriber, Subscription, + Builder, FindServiceSpecifier, InstanceSpecifier, LolaRuntimeBuilderImpl, Result, Runtime, RuntimeBuilder, + SampleContainer, ServiceDiscovery, Subscriber, Subscription, }; use std::path::Path; use std::thread; @@ -72,11 +72,11 @@ fn receive_loop( Ok(n) => { received_total += n; println!("{} Progress: {}/{}", log_tag, received_total, num_cycles); - } + }, Err(e) => { eprintln!("{} Receive error: {:?}", log_tag, e); std::process::exit(1); - } + }, } } println!("{} Received all {} samples, exiting", log_tag, num_cycles); @@ -118,15 +118,12 @@ fn run_bigdata_test(runtime: &R, num_cycles: usize) { "[bigdata-consumer] Starting bigdata test, will receive {} samples", num_cycles ); - let instance_specifier = InstanceSpecifier::new("/score/cp60/MapApiLanesStamped") - .expect("Invalid instance specifier"); - let discovery = runtime - .find_service::(FindServiceSpecifier::Specific(instance_specifier)); + let instance_specifier = + InstanceSpecifier::new("/score/cp60/MapApiLanesStamped").expect("Invalid instance specifier"); + let discovery = runtime.find_service::(FindServiceSpecifier::Specific(instance_specifier)); let consumer_builder = wait_for_consumer_builder(log_tag, || { - let instances = discovery - .get_available_instances() - .expect("Service discovery failed"); + let instances = discovery.get_available_instances().expect("Service discovery failed"); instances.into_iter().next() }); @@ -154,16 +151,13 @@ fn run_mixed_primitives_test(runtime: &R, num_cycles: usize) { "[mixed-primitives-consumer] Starting mixed_primitives test, will receive {} samples", num_cycles ); - let instance_specifier = InstanceSpecifier::new("/IntegrationTest/MixedPrimitives") - .expect("Invalid instance specifier"); - let discovery = runtime.find_service::( - FindServiceSpecifier::Specific(instance_specifier), - ); + let instance_specifier = + InstanceSpecifier::new("/IntegrationTest/MixedPrimitives").expect("Invalid instance specifier"); + let discovery = + runtime.find_service::(FindServiceSpecifier::Specific(instance_specifier)); let consumer_builder = wait_for_consumer_builder(log_tag, || { - let instances = discovery - .get_available_instances() - .expect("Service discovery failed"); + let instances = discovery.get_available_instances().expect("Service discovery failed"); instances.into_iter().next() }); @@ -205,9 +199,16 @@ fn run_mixed_primitives_test(runtime: &R, num_cycles: usize) { assert_eq!(sample.flag, expected.flag); println!( "[mixed-primitives-consumer] Received sample u64={} i64={} u32={} i32={} f32={} u16={} i16={} u8={} i8={} flag={}", - sample.u64_val, sample.i64_val, sample.u32_val, - sample.i32_val, sample.f32_val, sample.u16_val, - sample.i16_val, sample.u8_val, sample.i8_val, sample.flag + sample.u64_val, + sample.i64_val, + sample.u32_val, + sample.i32_val, + sample.f32_val, + sample.u16_val, + sample.i16_val, + sample.u8_val, + sample.i8_val, + sample.flag ); }, ); @@ -219,15 +220,12 @@ fn run_complex_struct_test(runtime: &R, num_cycles: usize) { "[complex-struct-consumer] Starting complex_struct test, will receive {} samples", num_cycles ); - let instance_specifier = InstanceSpecifier::new("/UserDefinedTest/ComplexStruct") - .expect("Invalid instance specifier"); - let discovery = runtime - .find_service::(FindServiceSpecifier::Specific(instance_specifier)); + let instance_specifier = + InstanceSpecifier::new("/UserDefinedTest/ComplexStruct").expect("Invalid instance specifier"); + let discovery = runtime.find_service::(FindServiceSpecifier::Specific(instance_specifier)); let consumer_builder = wait_for_consumer_builder(log_tag, || { - let instances = discovery - .get_available_instances() - .expect("Service discovery failed"); + let instances = discovery.get_available_instances().expect("Service discovery failed"); instances.into_iter().next() }); @@ -319,9 +317,7 @@ fn main() { // Initialise the Lola runtime. let mut runtime_builder: LolaRuntimeBuilderImpl = LolaRuntimeBuilderImpl::new(); runtime_builder.load_config(Path::new(CONFIG_PATH)); - let runtime = runtime_builder - .build() - .expect("Failed to build Lola runtime"); + let runtime = runtime_builder.build().expect("Failed to build Lola runtime"); match args.test_case { TestCase::Bigdata => run_bigdata_test(&runtime, num_cycles), diff --git a/score/mw/com/test/basic_rust_api/producer_app/producer_app.rs b/score/mw/com/test/basic_rust_api/producer_app/producer_app.rs index 06512ca49f..0a129327c3 100644 --- a/score/mw/com/test/basic_rust_api/producer_app/producer_app.rs +++ b/score/mw/com/test/basic_rust_api/producer_app/producer_app.rs @@ -30,14 +30,13 @@ use std::thread; use std::time::Duration; use bigdata_com_api_gen::{ - ArrayStruct, BigDataInterface, ComplexStruct, ComplexStructInterface, MapApiLanesStamped, - MixedPrimitivesInterface, MixedPrimitivesPayload, NestedStruct, Point, Point3D, SensorData, - SimpleStruct, VehicleState, + ArrayStruct, BigDataInterface, ComplexStruct, ComplexStructInterface, MapApiLanesStamped, MixedPrimitivesInterface, + MixedPrimitivesPayload, NestedStruct, Point, Point3D, SensorData, SimpleStruct, VehicleState, }; use clap::Parser; use score_com::{ - Builder, InstanceSpecifier, LolaRuntimeBuilderImpl, Producer, Publisher, Runtime, - RuntimeBuilder, SampleMaybeUninit, SampleMut, + Builder, InstanceSpecifier, LolaRuntimeBuilderImpl, Producer, Publisher, Runtime, RuntimeBuilder, + SampleMaybeUninit, SampleMut, }; const CONFIG_PATH: &str = "etc/config.json"; @@ -74,8 +73,8 @@ fn run_bigdata_test(runtime: &R, num_cycles: u32) { "[bigdata-producer] Starting bigdata test with num_cycles={}", num_cycles ); - let instance_specifier = InstanceSpecifier::new("/score/cp60/MapApiLanesStamped") - .expect("Invalid instance specifier"); + let instance_specifier = + InstanceSpecifier::new("/score/cp60/MapApiLanesStamped").expect("Invalid instance specifier"); // Sleep to allow the consumer to start first and demonstrate service discovery retries. thread::sleep(SERVICE_OFFER_DELAY_MS); @@ -102,8 +101,8 @@ fn run_mixed_primitives_test(runtime: &R, num_cycles: u32) { "[mixed-primitives-producer] Starting mixed_primitives test with num_cycles={}", num_cycles ); - let instance_specifier = InstanceSpecifier::new("/IntegrationTest/MixedPrimitives") - .expect("Invalid instance specifier"); + let instance_specifier = + InstanceSpecifier::new("/IntegrationTest/MixedPrimitives").expect("Invalid instance specifier"); // Sleep to allow the consumer to start first and demonstrate service discovery retries. thread::sleep(SERVICE_OFFER_DELAY_MS); @@ -113,10 +112,7 @@ fn run_mixed_primitives_test(runtime: &R, num_cycles: u32) { println!("[mixed-primitives-producer] Service offered, starting send loop"); run_send_loop(num_cycles, |x| { - let uninit = offered - .mixed_event - .allocate() - .expect("Failed to allocate sample"); + let uninit = offered.mixed_event.allocate().expect("Failed to allocate sample"); let sample = MixedPrimitivesPayload { u64_val: u64::from(x), i64_val: i64::from(x), @@ -140,8 +136,8 @@ fn run_complex_struct_test(runtime: &R, num_cycles: u32) { "[complex-struct-producer] Starting complex_struct test with num_cycles={}", num_cycles ); - let instance_specifier = InstanceSpecifier::new("/UserDefinedTest/ComplexStruct") - .expect("Invalid instance specifier"); + let instance_specifier = + InstanceSpecifier::new("/UserDefinedTest/ComplexStruct").expect("Invalid instance specifier"); // Sleep to allow the consumer to start first and demonstrate service discovery retries. thread::sleep(SERVICE_OFFER_DELAY_MS); @@ -151,10 +147,7 @@ fn run_complex_struct_test(runtime: &R, num_cycles: u32) { println!("[complex-struct-producer] Service offered, starting send loop"); run_send_loop(num_cycles, |x| { - let uninit = offered - .complex_event - .allocate() - .expect("Failed to allocate sample"); + let uninit = offered.complex_event.allocate().expect("Failed to allocate sample"); let x_f32 = x as f32; let sample = ComplexStruct { count: x, @@ -201,9 +194,7 @@ fn main() { // Initialise the Lola runtime. let mut runtime_builder: LolaRuntimeBuilderImpl = LolaRuntimeBuilderImpl::new(); runtime_builder.load_config(Path::new(CONFIG_PATH)); - let runtime = runtime_builder - .build() - .expect("Failed to build Lola runtime"); + let runtime = runtime_builder.build().expect("Failed to build Lola runtime"); match args.test_case { TestCase::Bigdata => run_bigdata_test(&runtime, num_cycles), diff --git a/tools/lint/BUILD b/tools/lint/BUILD index 6373ba59f5..c999c07ba1 100644 --- a/tools/lint/BUILD +++ b/tools/lint/BUILD @@ -11,8 +11,57 @@ # SPDX-License-Identifier: Apache-2.0 # ******************************************************************************* +load("@rules_shell//shell:sh_binary.bzl", "sh_binary") +load("//bazel/rules:expand_template.bzl", "expand_template") + # Makes tools/lint/ a Bazel package so linters.bzl can be referenced as a # label target (e.g. //tools/lint:linters.bzl%clang_tidy) in bazelrc. exports_files([ "linters.bzl", ]) + +# Wraps @score_rust_policies//rustfmt:rustfmt.toml (a plain exports_files +# source file, which //bazel/rules:expand_template.bzl's `deps` attribute +# rejects) in a filegroup so it can be depended on for location expansion. +filegroup( + name = "rustfmt_toml", + srcs = ["@score_rust_policies//rustfmt:rustfmt.toml"], +) + +# Generates the rustfmt_with_config wrapper script by substituting the +# runfiles ("rlocation") paths of the S-CORE rustfmt policy config and the +# rules_rust rustfmt binary into the template. See rustfmt_wrapper.sh.tpl for +# why this indirection exists. //bazel/rules:expand_template.bzl is used +# (rather than @bazel_skylib's) because it expands the `$(rlocationpath ...)` +# label expressions below via `ctx.expand_location`, which the skylib rule +# does not support. +expand_template( + name = "rustfmt_with_config_script", + out = "rustfmt_wrapper.sh", + expression_substitutions = { + "@@RUSTFMT_BIN@@": "$(rlocationpath @rules_rust//tools/upstream_wrapper:rustfmt)", + "@@RUSTFMT_TOML@@": "$(rlocationpath :rustfmt_toml)", + }, + is_executable = True, + template = "rustfmt_wrapper.sh.tpl", + deps = [ + ":rustfmt_toml", + "@rules_rust//tools/upstream_wrapper:rustfmt", + ], +) + +# A drop-in replacement for `@rules_rust//tools/upstream_wrapper:rustfmt` +# that always formats/checks using the shared S-CORE rustfmt policy pulled in +# via the `score_rust_policies` bazel_dep (see MODULE.bazel), rather than a +# rustfmt.toml checked into this repository. +sh_binary( + name = "rustfmt_with_config", + srcs = [":rustfmt_with_config_script"], + data = [ + ":rustfmt_toml", + "@rules_rust//tools/upstream_wrapper:rustfmt", + ], + target_compatible_with = ["@platforms//os:linux"], + visibility = ["//:__pkg__"], + deps = ["@bazel_tools//tools/bash/runfiles"], +) diff --git a/tools/lint/rustfmt_wrapper.sh.tpl b/tools/lint/rustfmt_wrapper.sh.tpl new file mode 100644 index 0000000000..576920c207 --- /dev/null +++ b/tools/lint/rustfmt_wrapper.sh.tpl @@ -0,0 +1,21 @@ +#!/usr/bin/env bash +# Wrapper around the rules_rust `rustfmt` binary that injects the config to use, so the policy is consumed as a Bazel +# dependency. +set -euo pipefail + +# --- begin runfiles.bash initialization v3 --- +# Copy-pasted from the Bazel Bash runfiles library v3. +# https://github.com/bazelbuild/bazel/blob/master/tools/bash/runfiles/runfiles.bash +f=bazel_tools/tools/bash/runfiles/runfiles.bash +source "${RUNFILES_DIR:-/dev/null}/$f" 2>/dev/null || \ + source "$(grep -sm1 "^$f " "${RUNFILES_MANIFEST_FILE:-/dev/null}" | cut -f2- -d' ')" 2>/dev/null || \ + source "$0.runfiles/$f" 2>/dev/null || \ + source "$(grep -sm1 "^$f " "$0.runfiles_manifest" | cut -f2- -d' ')" 2>/dev/null || \ + source "$(grep -sm1 "^$f " "$0.exe.runfiles_manifest" | cut -f2- -d' ')" 2>/dev/null || \ + { echo >&2 "ERROR: runfiles.bash initializer cannot find $f"; exit 1; } +# --- end runfiles.bash initialization v3 --- + +config="$(rlocation "@@RUSTFMT_TOML@@")" +rustfmt="$(rlocation "@@RUSTFMT_BIN@@")" + +exec "$rustfmt" --config-path "$config" "$@"