diff --git a/rustecal-core/src/configuration.rs b/rustecal-core/src/configuration.rs index 6e0427a..40ebef4 100644 --- a/rustecal-core/src/configuration.rs +++ b/rustecal-core/src/configuration.rs @@ -7,88 +7,92 @@ //! default settings or loading from a YAML file, and automatically //! frees the underlying C object on drop. -use std::{ffi::{CStr, CString}, path::Path, ops::{Deref, DerefMut}}; -use thiserror::Error; use rustecal_sys as sys; +use std::{ + ffi::{CStr, CString}, + ops::{Deref, DerefMut}, + path::Path, +}; +use thiserror::Error; /// Errors that can occur when creating or loading a Configuration #[derive(Debug, Error)] pub enum ConfigError { - #[error("Received null pointer from eCAL_Configuration_New")] - NullPointer, - #[error("Invalid file path: {0}")] - InvalidPath(String), + #[error("Received null pointer from eCAL_Configuration_New")] + NullPointer, + #[error("Invalid file path: {0}")] + InvalidPath(String), } /// Safe Rust wrapper around eCAL_Configuration pub struct Configuration { - inner: *mut sys::eCAL_Configuration, + inner: *mut sys::eCAL_Configuration, } unsafe impl Send for Configuration {} unsafe impl Sync for Configuration {} impl Configuration { - /// Creates a new Configuration with default values loaded via eCAL_Configuration_InitFromConfig - pub fn new() -> Result { - let cfg = unsafe { sys::eCAL_Configuration_New() }; - if cfg.is_null() { - return Err(ConfigError::NullPointer); + /// Creates a new Configuration with default values loaded via eCAL_Configuration_InitFromConfig + pub fn new() -> Result { + let cfg = unsafe { sys::eCAL_Configuration_New() }; + if cfg.is_null() { + return Err(ConfigError::NullPointer); + } + unsafe { sys::eCAL_Configuration_InitFromConfig(cfg) }; + Ok(Configuration { inner: cfg }) } - unsafe { sys::eCAL_Configuration_InitFromConfig(cfg) }; - Ok(Configuration { inner: cfg }) - } - /// Loads a Configuration from a YAML file at the given path - pub fn from_file(path: &str) -> Result { - if !Path::new(path).exists() { - return Err(ConfigError::InvalidPath(path.to_string())); + /// Loads a Configuration from a YAML file at the given path + pub fn from_file(path: &str) -> Result { + if !Path::new(path).exists() { + return Err(ConfigError::InvalidPath(path.to_string())); + } + let c_path = CString::new(path).map_err(|_| ConfigError::InvalidPath(path.to_string()))?; + let cfg = unsafe { sys::eCAL_Configuration_New() }; + if cfg.is_null() { + return Err(ConfigError::NullPointer); + } + unsafe { sys::eCAL_Configuration_InitFromFile(cfg, c_path.as_ptr()) }; + Ok(Configuration { inner: cfg }) } - let c_path = CString::new(path).map_err(|_| ConfigError::InvalidPath(path.to_string()))?; - let cfg = unsafe { sys::eCAL_Configuration_New() }; - if cfg.is_null() { - return Err(ConfigError::NullPointer); - } - unsafe { sys::eCAL_Configuration_InitFromFile(cfg, c_path.as_ptr()) }; - Ok(Configuration { inner: cfg }) - } - /// Returns the path of the loaded configuration file, if any - pub fn file_path(&self) -> Option { - unsafe { - let p = sys::eCAL_Configuration_GetConfigurationFilePath(self.inner); - if p.is_null() { - None - } else { - Some(CStr::from_ptr(p).to_string_lossy().into_owned()) - } + /// Returns the path of the loaded configuration file, if any + pub fn file_path(&self) -> Option { + unsafe { + let p = sys::eCAL_Configuration_GetConfigurationFilePath(self.inner); + if p.is_null() { + None + } else { + Some(CStr::from_ptr(p).to_string_lossy().into_owned()) + } + } } - } - /// Returns a raw pointer to the underlying eCAL_Configuration for FFI calls - pub(crate) fn as_ptr(&self) -> *const sys::eCAL_Configuration { - self.inner as *const _ - } + /// Returns a raw pointer to the underlying eCAL_Configuration for FFI calls + pub(crate) fn as_ptr(&self) -> *const sys::eCAL_Configuration { + self.inner as *const _ + } } /// Allow transparent access to the underlying C struct impl Deref for Configuration { - type Target = sys::eCAL_Configuration; - fn deref(&self) -> &Self::Target { - unsafe { &*self.inner } - } + type Target = sys::eCAL_Configuration; + fn deref(&self) -> &Self::Target { + unsafe { &*self.inner } + } } /// Allow mutable access to the underlying C struct impl DerefMut for Configuration { - fn deref_mut(&mut self) -> &mut Self::Target { - unsafe { &mut *self.inner } - } + fn deref_mut(&mut self) -> &mut Self::Target { + unsafe { &mut *self.inner } + } } impl Drop for Configuration { - /// Deletes the underlying eCAL_Configuration on drop - fn drop(&mut self) { - unsafe { sys::eCAL_Configuration_Delete(self.inner) }; - } + /// Deletes the underlying eCAL_Configuration on drop + fn drop(&mut self) { + unsafe { sys::eCAL_Configuration_Delete(self.inner) }; + } } diff --git a/rustecal-core/src/core.rs b/rustecal-core/src/core.rs index 666d3d3..4942073 100644 --- a/rustecal-core/src/core.rs +++ b/rustecal-core/src/core.rs @@ -45,7 +45,7 @@ impl Ecal { // Convert the unit name (if any), mapping CString errors let (name_ptr, _): (*const i8, Option) = if let Some(name) = unit_name { let c = CString::new(name) - .map_err(|e| RustecalError::Internal(format!("invalid unit name: {}", e)))?; + .map_err(|e| RustecalError::Internal(format!("invalid unit name: {e}")))?; (c.as_ptr(), Some(c)) } else { (ptr::null(), None) @@ -57,9 +57,7 @@ impl Ecal { .unwrap_or(ptr::null_mut()); // Call the C API and map its return code - let ret = unsafe { - rustecal_sys::eCAL_Initialize(name_ptr, &components.bits(), cfg_ptr) - }; + let ret = unsafe { rustecal_sys::eCAL_Initialize(name_ptr, &components.bits(), cfg_ptr) }; check(ret) } diff --git a/rustecal-core/src/core_types/mod.rs b/rustecal-core/src/core_types/mod.rs index 00df7ec..c0fc113 100644 --- a/rustecal-core/src/core_types/mod.rs +++ b/rustecal-core/src/core_types/mod.rs @@ -1,4 +1,4 @@ //! Common eCAL types shared across pubsub and service layers. -pub mod monitoring; pub mod logging; +pub mod monitoring; diff --git a/rustecal-core/src/lib.rs b/rustecal-core/src/lib.rs index 21a8814..60fa1e4 100644 --- a/rustecal-core/src/lib.rs +++ b/rustecal-core/src/lib.rs @@ -9,21 +9,21 @@ //! //! This crate is typically re-exported by the `rustecal` crate. -pub mod core; pub mod components; pub mod configuration; +pub mod core; +pub mod core_types; pub mod error; -pub mod types; pub mod log; pub mod log_level; -pub mod core_types; pub mod monitoring; +pub mod types; // Re‑exports for ergonomic access: -pub use core::Ecal; pub use components::EcalComponents; pub use configuration::Configuration; +pub use core::Ecal; +pub use core_types::logging::LogMessage; pub use error::RustecalError; pub use log::Log; pub use log_level::LogLevel; -pub use core_types::logging::LogMessage; diff --git a/rustecal-core/src/log.rs b/rustecal-core/src/log.rs index 794f523..5f15536 100644 --- a/rustecal-core/src/log.rs +++ b/rustecal-core/src/log.rs @@ -4,8 +4,8 @@ //! logging at various severity levels, as well as retrieval of current log entries. use crate::core_types::logging::LogMessage; -use crate::log_level::LogLevel; use crate::error::RustecalError; +use crate::log_level::LogLevel; use std::{ffi::CString, ptr, slice}; /// Provides logging functions to emit and retrieve messages via the eCAL runtime. @@ -16,8 +16,8 @@ impl Log { /// /// Any interior NUL in `message` is replaced with `""`. pub fn log(level: LogLevel, message: &str) { - let cstr = CString::new(message) - .unwrap_or_else(|_| CString::new("").unwrap()); + let cstr = + CString::new(message).unwrap_or_else(|_| CString::new("").unwrap()); unsafe { rustecal_sys::eCAL_Logging_Log(level.into(), cstr.as_ptr()); diff --git a/rustecal-core/src/log_level.rs b/rustecal-core/src/log_level.rs index 1bcc204..5b06f17 100644 --- a/rustecal-core/src/log_level.rs +++ b/rustecal-core/src/log_level.rs @@ -22,40 +22,40 @@ #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum LogLevel { /// No logging. - None = 0, + None = 0, /// Informational messages. - Info = 1, + Info = 1, /// Warnings. Warning = 2, /// Errors. - Error = 4, + Error = 4, /// Fatal errors. - Fatal = 8, + Fatal = 8, /// Debug level 1. - Debug1 = 16, + Debug1 = 16, /// Debug level 2. - Debug2 = 32, + Debug2 = 32, /// Debug level 3. - Debug3 = 64, + Debug3 = 64, /// Debug level 4. - Debug4 = 128, + Debug4 = 128, /// All levels. - All = 255, + All = 255, } impl From for LogLevel { fn from(value: i32) -> Self { match value { - 1 => LogLevel::Info, - 2 => LogLevel::Warning, - 4 => LogLevel::Error, - 8 => LogLevel::Fatal, - 16 => LogLevel::Debug1, - 32 => LogLevel::Debug2, - 64 => LogLevel::Debug3, + 1 => LogLevel::Info, + 2 => LogLevel::Warning, + 4 => LogLevel::Error, + 8 => LogLevel::Fatal, + 16 => LogLevel::Debug1, + 32 => LogLevel::Debug2, + 64 => LogLevel::Debug3, 128 => LogLevel::Debug4, 255 => LogLevel::All, - _ => LogLevel::None, + _ => LogLevel::None, } } } diff --git a/rustecal-core/src/monitoring.rs b/rustecal-core/src/monitoring.rs index e722ca9..acd6c42 100644 --- a/rustecal-core/src/monitoring.rs +++ b/rustecal-core/src/monitoring.rs @@ -4,7 +4,7 @@ //! a safe Rust API to access a snapshot of the middleware's state. use crate::core_types::monitoring::{ - MonitoringSnapshot, ProcessInfo, TopicInfo, ServerInfo, ClientInfo, + ClientInfo, MonitoringSnapshot, ProcessInfo, ServerInfo, TopicInfo, }; use crate::error::RustecalError; use std::{ptr, slice}; @@ -25,13 +25,10 @@ impl Monitoring { /// when a snapshot *should* have been provided. pub fn get_snapshot() -> Result { // 1) Prepare a null pointer for the C function to fill in - let mut raw: *mut rustecal_sys::eCAL_Monitoring_SMonitoring = - ptr::null_mut(); + let mut raw: *mut rustecal_sys::eCAL_Monitoring_SMonitoring = ptr::null_mut(); // 2) Call the FFI: non‑zero means “no snapshot available” - let ret = unsafe { - rustecal_sys::eCAL_Monitoring_GetMonitoring(&mut raw, ptr::null()) - }; + let ret = unsafe { rustecal_sys::eCAL_Monitoring_GetMonitoring(&mut raw, ptr::null()) }; // 3) If nothing to monitor, return an empty snapshot if ret != 0 { diff --git a/rustecal-pubsub/src/lib.rs b/rustecal-pubsub/src/lib.rs index c996c44..7aecddd 100644 --- a/rustecal-pubsub/src/lib.rs +++ b/rustecal-pubsub/src/lib.rs @@ -12,23 +12,22 @@ //! - `TypedSubscriber` //! - Supported types: `StringMessage`, `BytesMessage`, `ProtobufMessage` - // Re-export core init & types pub use rustecal_core::{Ecal, EcalComponents}; // Sub‑modules -pub mod types; +pub mod payload_writer; pub mod publisher; pub mod subscriber; pub mod typed_publisher; pub mod typed_subscriber; -pub mod payload_writer; +pub mod types; // Public API +pub use payload_writer::PayloadWriter; pub use publisher::Publisher; pub use subscriber::Subscriber; -pub use typed_publisher::TypedPublisher; pub use typed_publisher::PublisherMessage; -pub use typed_subscriber::TypedSubscriber; +pub use typed_publisher::TypedPublisher; pub use typed_subscriber::SubscriberMessage; -pub use payload_writer::PayloadWriter; \ No newline at end of file +pub use typed_subscriber::TypedSubscriber; diff --git a/rustecal-pubsub/src/payload_writer.rs b/rustecal-pubsub/src/payload_writer.rs index 83883d0..cf80ef3 100644 --- a/rustecal-pubsub/src/payload_writer.rs +++ b/rustecal-pubsub/src/payload_writer.rs @@ -5,7 +5,7 @@ // with eCAL's `SendPayloadWriter` API, using mutable references rather than owning values. use std::cell::RefCell; -use std::os::raw::{c_void, c_int}; +use std::os::raw::{c_int, c_void}; /// A zero‐copy payload writer: you fill the shared‐memory buffer in place. pub trait PayloadWriter { @@ -35,7 +35,11 @@ pub(crate) unsafe extern "C" fn write_full_cb(buffer: *mut c_void, size: usize) if let Some(writer_ptr) = *cell.borrow() { let writer: &mut dyn PayloadWriter = &mut *writer_ptr; let buf = std::slice::from_raw_parts_mut(buffer as *mut u8, size); - if writer.write_full(buf) { 0 } else { -1 } + if writer.write_full(buf) { + 0 + } else { + -1 + } } else { -1 } @@ -48,7 +52,11 @@ pub(crate) unsafe extern "C" fn write_mod_cb(buffer: *mut c_void, size: usize) - if let Some(writer_ptr) = *cell.borrow() { let writer: &mut dyn PayloadWriter = &mut *writer_ptr; let buf = std::slice::from_raw_parts_mut(buffer as *mut u8, size); - if writer.write_modified(buf) { 0 } else { -1 } + if writer.write_modified(buf) { + 0 + } else { + -1 + } } else { -1 } diff --git a/rustecal-pubsub/src/publisher.rs b/rustecal-pubsub/src/publisher.rs index 1539f39..b24a488 100644 --- a/rustecal-pubsub/src/publisher.rs +++ b/rustecal-pubsub/src/publisher.rs @@ -1,7 +1,9 @@ -use rustecal_sys::*; -use rustecal_core::types::DataTypeInfo; +use crate::payload_writer::{ + get_size_cb, write_full_cb, write_mod_cb, PayloadWriter, CURRENT_WRITER, +}; use crate::types::TopicId; -use crate::payload_writer::{PayloadWriter, CURRENT_WRITER, write_full_cb, write_mod_cb, get_size_cb}; +use rustecal_core::types::DataTypeInfo; +use rustecal_sys::*; use std::ffi::{CStr, CString}; use std::ptr; @@ -54,9 +56,8 @@ impl Publisher { descriptor_length: data_type.descriptor.len(), }; - let handle = unsafe { - eCAL_Publisher_New(c_topic.as_ptr(), &data_type_info, None, ptr::null()) - }; + let handle = + unsafe { eCAL_Publisher_New(c_topic.as_ptr(), &data_type_info, None, ptr::null()) }; if handle.is_null() { Err("Failed to create eCAL_Publisher".into()) @@ -82,16 +83,11 @@ impl Publisher { /// `true` on success, `false` on failure. pub fn send(&self, data: &[u8], timestamp: Timestamp) -> bool { let ts_ptr = match timestamp { - Timestamp::Auto => ptr::null(), + Timestamp::Auto => ptr::null(), Timestamp::Custom(t) => &t as *const i64 as *const _, }; let ret = unsafe { - eCAL_Publisher_Send( - self.handle, - data.as_ptr() as *const _, - data.len(), - ts_ptr, - ) + eCAL_Publisher_Send(self.handle, data.as_ptr() as *const _, data.len(), ts_ptr) }; // eCAL returns 0 on success ret == 0 @@ -120,25 +116,20 @@ impl Publisher { // build the C payload writer struct let c_writer = eCAL_PayloadWriter { - WriteFull: Some(write_full_cb), + WriteFull: Some(write_full_cb), WriteModified: Some(write_mod_cb), - GetSize: Some(get_size_cb), + GetSize: Some(get_size_cb), }; // prepare timestamp pointer let ts_ptr = match timestamp { - Timestamp::Auto => ptr::null(), + Timestamp::Auto => ptr::null(), Timestamp::Custom(t) => &t as *const i64 as *const _, }; // call into the FFI - let result = unsafe { - eCAL_Publisher_SendPayloadWriter( - self.handle, - &c_writer as *const _, - ts_ptr, - ) - }; + let result = + unsafe { eCAL_Publisher_SendPayloadWriter(self.handle, &c_writer as *const _, ts_ptr) }; // clear the slot CURRENT_WRITER.with(|cell| { @@ -148,7 +139,7 @@ impl Publisher { // eCAL returns 0 on success result == 0 } - + /// Retrieves the number of currently connected subscribers. pub fn get_subscriber_count(&self) -> usize { unsafe { eCAL_Publisher_GetSubscriberCount(self.handle) } @@ -216,7 +207,8 @@ impl Publisher { let descriptor = if info.descriptor.is_null() || info.descriptor_length == 0 { vec![] } else { - std::slice::from_raw_parts(info.descriptor as *const u8, info.descriptor_length).to_vec() + std::slice::from_raw_parts(info.descriptor as *const u8, info.descriptor_length) + .to_vec() }; Some(DataTypeInfo { diff --git a/rustecal-pubsub/src/subscriber.rs b/rustecal-pubsub/src/subscriber.rs index 108afc4..fc38833 100644 --- a/rustecal-pubsub/src/subscriber.rs +++ b/rustecal-pubsub/src/subscriber.rs @@ -1,9 +1,9 @@ -use rustecal_sys::*; -use rustecal_core::types::DataTypeInfo; use crate::types::TopicId; +use rustecal_core::types::DataTypeInfo; +use rustecal_sys::*; +use std::ffi::c_void; use std::ffi::{CStr, CString}; use std::ptr; -use std::ffi::c_void; /// A safe and ergonomic wrapper around the eCAL C subscriber API. /// @@ -56,26 +56,14 @@ impl Subscriber { descriptor_length: data_type.descriptor.len(), }; - let handle = unsafe { - eCAL_Subscriber_New( - c_topic.as_ptr(), - &data_type_info, - None, - ptr::null(), - ) - }; + let handle = + unsafe { eCAL_Subscriber_New(c_topic.as_ptr(), &data_type_info, None, ptr::null()) }; if handle.is_null() { return Err("Failed to create eCAL_Subscriber".into()); } - unsafe { - eCAL_Subscriber_SetReceiveCallback( - handle, - Some(callback), - ptr::null_mut(), - ) - }; + unsafe { eCAL_Subscriber_SetReceiveCallback(handle, Some(callback), ptr::null_mut()) }; Ok(Self { handle, @@ -159,7 +147,8 @@ impl Subscriber { let descriptor = if info.descriptor.is_null() || info.descriptor_length == 0 { vec![] } else { - std::slice::from_raw_parts(info.descriptor as *const u8, info.descriptor_length).to_vec() + std::slice::from_raw_parts(info.descriptor as *const u8, info.descriptor_length) + .to_vec() }; Some(DataTypeInfo { diff --git a/rustecal-pubsub/src/typed_publisher.rs b/rustecal-pubsub/src/typed_publisher.rs index 0f1b823..5aeebd0 100644 --- a/rustecal-pubsub/src/typed_publisher.rs +++ b/rustecal-pubsub/src/typed_publisher.rs @@ -1,4 +1,8 @@ -use crate::{publisher::{Publisher, Timestamp}, payload_writer::PayloadWriter, types::TopicId}; +use crate::{ + payload_writer::PayloadWriter, + publisher::{Publisher, Timestamp}, + types::TopicId, +}; use rustecal_core::types::DataTypeInfo; use std::{marker::PhantomData, sync::Arc}; @@ -20,7 +24,7 @@ pub trait PublisherMessage { /// (implementing [`PublisherMessage`]) are published. pub struct TypedPublisher { publisher: Publisher, - _phantom: PhantomData, + _phantom: PhantomData, } impl TypedPublisher { @@ -34,10 +38,13 @@ impl TypedPublisher { /// /// Returns an `Err(String)` if the underlying eCAL publisher could not be created. pub fn new(topic_name: &str) -> Result { - let datatype = T::datatype(); + let datatype = T::datatype(); let publisher = Publisher::new(topic_name, datatype)?; - Ok(Self { publisher, _phantom: PhantomData }) + Ok(Self { + publisher, + _phantom: PhantomData, + }) } /// Sends a message of type `T` to all connected subscribers. diff --git a/rustecal-pubsub/src/typed_subscriber.rs b/rustecal-pubsub/src/typed_subscriber.rs index d8e19fe..f5bfef8 100644 --- a/rustecal-pubsub/src/typed_subscriber.rs +++ b/rustecal-pubsub/src/typed_subscriber.rs @@ -2,7 +2,11 @@ use crate::subscriber::Subscriber; use crate::types::TopicId; use rustecal_core::types::DataTypeInfo; use rustecal_sys::{eCAL_SDataTypeInformation, eCAL_SReceiveCallbackData, eCAL_STopicId}; -use std::{ffi::{c_void, CStr}, marker::PhantomData, slice}; +use std::{ + ffi::{c_void, CStr}, + marker::PhantomData, + slice, +}; /// A trait for message types that can be deserialized by [`TypedSubscriber`]. /// @@ -28,17 +32,17 @@ pub trait SubscriberMessage<'a>: Sized { /// A received message, with payload and metadata. pub struct Received { /// The deserialized payload of type `T`. - pub payload: T, + pub payload: T, /// The topic name this message was received on. pub topic_name: String, /// The declared encoding format (e.g. "proto", "raw"). - pub encoding: String, + pub encoding: String, /// The declared type name for the message. - pub type_name: String, + pub type_name: String, /// The publisher's send timestamp (microseconds since epoch). - pub timestamp: i64, + pub timestamp: i64, /// The publisher's logical clock at send time. - pub clock: i64, + pub clock: i64, } /// Wrapper to store a boxed callback for `Received` @@ -52,7 +56,10 @@ impl<'buf, T: SubscriberMessage<'buf>> CallbackWrapper<'buf, T> { where F: Fn(Received) + Send + Sync + 'static, { - Self { callback: Box::new(f), _phantom: PhantomData } + Self { + callback: Box::new(f), + _phantom: PhantomData, + } } fn call(&self, received: Received) { @@ -84,11 +91,15 @@ impl<'buf, T: SubscriberMessage<'buf>> TypedSubscriber<'buf, T> { let datatype = T::datatype(); // dummy callback for construction - let boxed = Box::new(CallbackWrapper::new(|_| {})); + let boxed = Box::new(CallbackWrapper::new(|_| {})); let user_data = Box::into_raw(boxed); - let subscriber = Subscriber::new(topic_name, datatype, trampoline::< 'buf, T>)?; - Ok(Self { subscriber, user_data, _phantom: PhantomData }) + let subscriber = Subscriber::new(topic_name, datatype, trampoline::<'buf, T>)?; + Ok(Self { + subscriber, + user_data, + _phantom: PhantomData, + }) } /// Registers a user callback that receives a deserialized message with metadata. @@ -100,12 +111,12 @@ impl<'buf, T: SubscriberMessage<'buf>> TypedSubscriber<'buf, T> { unsafe { let _ = Box::from_raw(self.user_data); } - let boxed = Box::new(CallbackWrapper::new(callback)); + let boxed = Box::new(CallbackWrapper::new(callback)); self.user_data = Box::into_raw(boxed); unsafe { rustecal_sys::eCAL_Subscriber_SetReceiveCallback( self.subscriber.raw_handle(), - Some(trampoline::< 'buf, T>), + Some(trampoline::<'buf, T>), self.user_data as *mut _, ); } @@ -151,10 +162,10 @@ impl<'buf, T: SubscriberMessage<'buf>> Drop for TypedSubscriber<'buf, T> { /// Internal trampoline for dispatching incoming messages to the registered user callback. extern "C" fn trampoline<'buf, T: SubscriberMessage<'buf> + 'buf>( - topic_id: *const eCAL_STopicId, + topic_id: *const eCAL_STopicId, data_type_info: *const eCAL_SDataTypeInformation, - data: *const eCAL_SReceiveCallbackData, - user_data: *mut c_void, + data: *const eCAL_SReceiveCallbackData, + user_data: *mut c_void, ) { unsafe { if data.is_null() || user_data.is_null() { @@ -162,19 +173,23 @@ extern "C" fn trampoline<'buf, T: SubscriberMessage<'buf> + 'buf>( } // zero-copy view of the shared-memory payload - let rd = &*data; - let payload = slice::from_raw_parts(rd.buffer as *const u8, rd.buffer_size as usize); + let rd = &*data; + let payload = slice::from_raw_parts(rd.buffer as *const u8, rd.buffer_size); // rebuild DataTypeInfo let info = &*data_type_info; - let encoding = CStr::from_ptr(info.encoding).to_string_lossy().into_owned(); - let type_name = CStr::from_ptr(info.name).to_string_lossy().into_owned(); + let encoding = CStr::from_ptr(info.encoding).to_string_lossy().into_owned(); + let type_name = CStr::from_ptr(info.name).to_string_lossy().into_owned(); let descriptor = if info.descriptor.is_null() || info.descriptor_length == 0 { Vec::new() } else { - slice::from_raw_parts(info.descriptor as *const u8, info.descriptor_length as usize).to_vec() + slice::from_raw_parts(info.descriptor as *const u8, info.descriptor_length).to_vec() + }; + let dt_info = DataTypeInfo { + encoding: encoding.clone(), + type_name: type_name.clone(), + descriptor, }; - let dt_info = DataTypeInfo { encoding: encoding.clone(), type_name: type_name.clone(), descriptor }; // direct-borrow deserialization if let Some(decoded) = T::from_bytes(payload, &dt_info) { @@ -183,12 +198,12 @@ extern "C" fn trampoline<'buf, T: SubscriberMessage<'buf> + 'buf>( .to_string_lossy() .into_owned(); let received = Received { - payload: decoded, + payload: decoded, topic_name, - encoding: encoding.clone(), - type_name: type_name.clone(), - timestamp: rd.send_timestamp, - clock: rd.send_clock, + encoding: encoding.clone(), + type_name: type_name.clone(), + timestamp: rd.send_timestamp, + clock: rd.send_clock, }; cb_wrapper.call(received); } diff --git a/rustecal-pubsub/src/types.rs b/rustecal-pubsub/src/types.rs index 7be89e7..b6c07e2 100644 --- a/rustecal-pubsub/src/types.rs +++ b/rustecal-pubsub/src/types.rs @@ -1,7 +1,7 @@ //! Types used by the pub/sub layer of eCAL. -use rustecal_sys::*; use rustecal_core::types::EntityId; +use rustecal_sys::*; use std::ffi::CStr; /// Internal eCAL topic identifier, used by publishers and subscribers. diff --git a/rustecal-samples/benchmarks/performance_receive/src/main.rs b/rustecal-samples/benchmarks/performance_receive/src/main.rs index 47d67ba..53da5fe 100644 --- a/rustecal-samples/benchmarks/performance_receive/src/main.rs +++ b/rustecal-samples/benchmarks/performance_receive/src/main.rs @@ -1,28 +1,37 @@ //! A performance benchmark subscriber in Rust, using the typed `BytesMessage` subscriber //! to demonstrate zero-copy payload support. -use std::{sync::{Arc, Mutex, atomic::Ordering}, thread, time::{Duration, Instant}}; -use std::thread::sleep; -use rustecal::{Ecal, EcalComponents, TypedSubscriber}; use rustecal::pubsub::typed_subscriber::Received; +use rustecal::{Ecal, EcalComponents, TypedSubscriber}; use rustecal_types_bytes::BytesMessage; +use std::thread::sleep; +use std::{ + sync::{atomic::Ordering, Arc, Mutex}, + thread, + time::{Duration, Instant}, +}; fn main() -> Result<(), Box> { // initialize eCAL - Ecal::initialize(Some("performance receive rust"), EcalComponents::DEFAULT, None) - .expect("eCAL initialization failed"); + Ecal::initialize( + Some("performance receive rust"), + EcalComponents::DEFAULT, + None, + ) + .expect("eCAL initialization failed"); // create a typed subscriber for raw bytes - let mut subscriber: TypedSubscriber<'_, BytesMessage<'_>> = TypedSubscriber::new("Performance")?; + let mut subscriber: TypedSubscriber<'_, BytesMessage<'_>> = + TypedSubscriber::new("Performance")?; // shared counters & timer - let msgs = Arc::new(std::sync::atomic::AtomicU64::new(0)); + let msgs = Arc::new(std::sync::atomic::AtomicU64::new(0)); let bytes = Arc::new(std::sync::atomic::AtomicU64::new(0)); let start = Arc::new(Mutex::new(Instant::now())); // register the receive-callback { - let msgs = Arc::clone(&msgs); + let msgs = Arc::clone(&msgs); let bytes = Arc::clone(&bytes); let start = Arc::clone(&start); @@ -45,10 +54,10 @@ fn main() -> Result<(), Box> { let b = bytes.swap(0, Ordering::Relaxed); let secs = elapsed.as_secs_f64(); - let kbyte_s = (b as f64 / 1024.0) / secs; - let mbyte_s = kbyte_s / 1024.0; - let gbyte_s = mbyte_s / 1024.0; - let msg_s = (m as f64) / secs; + let kbyte_s = (b as f64 / 1024.0) / secs; + let mbyte_s = kbyte_s / 1024.0; + let gbyte_s = mbyte_s / 1024.0; + let msg_s = (m as f64) / secs; let latency_us = (secs * 1e6) / (m as f64); println!("Topic name : {}", msg.topic_name); @@ -58,13 +67,13 @@ fn main() -> Result<(), Box> { .map(|&b| (b as char).to_string()) .collect::>() .join(" "); - println!("Message [0 - 15] : {:?}", spaced); + println!("Message [0 - 15] : {spaced:?}"); println!("Payload size (kB) : {:.0}", buffer.len() / 1024); - println!("Throughput (kB/s) : {:.0}", kbyte_s); - println!("Throughput (MB/s) : {:.2}", mbyte_s); - println!("Throughput (GB/s) : {:.2}", gbyte_s); - println!("Messages (1/s) : {:.0}", msg_s); - println!("Latency (µs) : {:.2}", latency_us); + println!("Throughput (kB/s) : {kbyte_s:.0}"); + println!("Throughput (MB/s) : {mbyte_s:.2}"); + println!("Throughput (GB/s) : {gbyte_s:.2}"); + println!("Messages (1/s) : {msg_s:.0}"); + println!("Latency (µs) : {latency_us:.2}"); println!(); // reset the timer diff --git a/rustecal-samples/benchmarks/performance_send/src/main.rs b/rustecal-samples/benchmarks/performance_send/src/main.rs index 5545782..df81d45 100644 --- a/rustecal-samples/benchmarks/performance_send/src/main.rs +++ b/rustecal-samples/benchmarks/performance_send/src/main.rs @@ -3,20 +3,23 @@ //! //! Sends messages of the given size in a tight loop, logging throughput every second. -use std::{env, time::{Duration, Instant}}; -use std::thread::sleep; -use rustecal::{Ecal, EcalComponents, Configuration, TypedPublisher}; +use rustecal::{Configuration, Ecal, EcalComponents, TypedPublisher}; use rustecal_types_bytes::BytesMessage; +use std::thread::sleep; +use std::{ + env, + time::{Duration, Instant}, +}; mod binary_payload_writer; use binary_payload_writer::BinaryPayload; use rustecal_pubsub::publisher::Timestamp; // performance settings -const ZERO_COPY: bool = true; -const BUFFER_COUNT: u32 = 1; -const ACKNOWLEDGE_TIMEOUT_MS: i32 = 50; -const PAYLOAD_SIZE_DEFAULT: usize = 8 * 1024 * 1024; +const ZERO_COPY: bool = true; +const BUFFER_COUNT: u32 = 1; +const ACKNOWLEDGE_TIMEOUT_MS: i32 = 50; +const PAYLOAD_SIZE_DEFAULT: usize = 8 * 1024 * 1024; fn main() -> Result<(), Box> { // parse payload size from CLI (or use default) @@ -27,16 +30,16 @@ fn main() -> Result<(), Box> { .unwrap_or(PAYLOAD_SIZE_DEFAULT); // log performance settings - println!("Zero copy mode : {}", ZERO_COPY); - println!("Number of write buffers : {}", BUFFER_COUNT); - println!("Acknowledge timeout : {} ms", ACKNOWLEDGE_TIMEOUT_MS); - println!("Payload size : {} bytes", payload_size); + println!("Zero copy mode : {ZERO_COPY}"); + println!("Number of write buffers : {BUFFER_COUNT}"); + println!("Acknowledge timeout : {ACKNOWLEDGE_TIMEOUT_MS} ms"); + println!("Payload size : {payload_size} bytes"); println!(); // configure eCAL let mut cfg = Configuration::new()?; - cfg.publisher.layer.shm.zero_copy_mode = ZERO_COPY as i32; - cfg.publisher.layer.shm.memfile_buffer_count = BUFFER_COUNT; + cfg.publisher.layer.shm.zero_copy_mode = ZERO_COPY as i32; + cfg.publisher.layer.shm.memfile_buffer_count = BUFFER_COUNT; cfg.publisher.layer.shm.acknowledge_timeout_ms = ACKNOWLEDGE_TIMEOUT_MS as u32; // initialize eCAL @@ -47,17 +50,16 @@ fn main() -> Result<(), Box> { )?; // create a typed publisher for raw bytes - let publisher: TypedPublisher = - TypedPublisher::new("Performance")?; + let publisher: TypedPublisher = TypedPublisher::new("Performance")?; // prepare our zero-copy payload writer let mut payload = BinaryPayload::new(payload_size); // counters and timer - let mut msgs_sent = 0u64; + let mut msgs_sent = 0u64; let mut bytes_sent = 0u64; let mut iterations = 0u64; - let mut last_log = Instant::now(); + let mut last_log = Instant::now(); // wait for subscriber while publisher.get_subscriber_count() == 0 { @@ -71,31 +73,31 @@ fn main() -> Result<(), Box> { // zero-copy send via PayloadWriter publisher.send_payload_writer(&mut payload, Timestamp::Auto); - msgs_sent += 1; + msgs_sent += 1; bytes_sent += payload_size as u64; iterations += 1; // every ~2000 msgs, log if 1s has passed if iterations % 2000 == 0 && last_log.elapsed() >= Duration::from_secs(1) { - let secs = last_log.elapsed().as_secs_f64(); - let kbyte_s = (bytes_sent as f64 / 1024.0) / secs; - let mbyte_s = kbyte_s / 1024.0; - let gbyte_s = mbyte_s / 1024.0; - let msg_s = (msgs_sent as f64) / secs; + let secs = last_log.elapsed().as_secs_f64(); + let kbyte_s = (bytes_sent as f64 / 1024.0) / secs; + let mbyte_s = kbyte_s / 1024.0; + let gbyte_s = mbyte_s / 1024.0; + let msg_s = (msgs_sent as f64) / secs; let latency_us = (secs * 1e6) / (msgs_sent as f64); println!("Payload size (kB) : {}", payload_size / 1024); - println!("Throughput (kB/s) : {:.0}", kbyte_s); - println!("Throughput (MB/s) : {:.2}", mbyte_s); - println!("Throughput (GB/s) : {:.2}", gbyte_s); - println!("Messages (1/s) : {:.0}", msg_s); - println!("Latency (µs) : {:.2}", latency_us); + println!("Throughput (kB/s) : {kbyte_s:.0}"); + println!("Throughput (MB/s) : {mbyte_s:.2}"); + println!("Throughput (GB/s) : {gbyte_s:.2}"); + println!("Messages (1/s) : {msg_s:.0}"); + println!("Latency (µs) : {latency_us:.2}"); println!(); // reset counters and timer - msgs_sent = 0; + msgs_sent = 0; bytes_sent = 0; - last_log = Instant::now(); + last_log = Instant::now(); } } diff --git a/rustecal-samples/monitoring/logging_receive/src/main.rs b/rustecal-samples/monitoring/logging_receive/src/main.rs index e76e3b5..cb93d03 100644 --- a/rustecal-samples/monitoring/logging_receive/src/main.rs +++ b/rustecal-samples/monitoring/logging_receive/src/main.rs @@ -4,7 +4,11 @@ use std::{thread, time::Duration}; fn main() -> Result<(), Box> { // initialize eCAL (only the logging component) - Ecal::initialize(Some("logging receive sample"), EcalComponents::LOGGING, None)?; + Ecal::initialize( + Some("logging receive sample"), + EcalComponents::LOGGING, + None, + )?; println!("eCAL initialized. Entering logging loop…"); while Ecal::ok() { @@ -12,7 +16,7 @@ fn main() -> Result<(), Box> { let entries = Log::get_logging()?; println!("=== Logging Snapshot ===\n"); - println!("Entries:\n{:#?}", entries); + println!("Entries:\n{entries:#?}"); // sleep before next poll thread::sleep(Duration::from_secs(1)); diff --git a/rustecal-samples/monitoring/monitoring_receive/src/main.rs b/rustecal-samples/monitoring/monitoring_receive/src/main.rs index e424eae..8f66ed5 100644 --- a/rustecal-samples/monitoring/monitoring_receive/src/main.rs +++ b/rustecal-samples/monitoring/monitoring_receive/src/main.rs @@ -4,7 +4,11 @@ use std::{thread, time::Duration}; fn main() -> Result<(), Box> { // initialize eCAL (only the monitoring component) - Ecal::initialize(Some("monitoring receive sample"), EcalComponents::MONITORING, None)?; + Ecal::initialize( + Some("monitoring receive sample"), + EcalComponents::MONITORING, + None, + )?; println!("eCAL initialized. Entering monitoring loop…"); while Ecal::ok() { diff --git a/rustecal-samples/pubsub/blob_receive/src/main.rs b/rustecal-samples/pubsub/blob_receive/src/main.rs index 68ecc4e..f2e8775 100644 --- a/rustecal-samples/pubsub/blob_receive/src/main.rs +++ b/rustecal-samples/pubsub/blob_receive/src/main.rs @@ -1,5 +1,5 @@ -use rustecal::{Ecal, EcalComponents, TypedSubscriber}; use rustecal::pubsub::typed_subscriber::Received; +use rustecal::{Ecal, EcalComponents, TypedSubscriber}; use rustecal_types_bytes::BytesMessage; fn main() -> Result<(), Box> { diff --git a/rustecal-samples/pubsub/blob_send/src/main.rs b/rustecal-samples/pubsub/blob_send/src/main.rs index 156fc2c..b7f44c9 100644 --- a/rustecal-samples/pubsub/blob_send/src/main.rs +++ b/rustecal-samples/pubsub/blob_send/src/main.rs @@ -1,5 +1,5 @@ -use rustecal::{Ecal, EcalComponents, TypedPublisher}; use rustecal::pubsub::publisher::Timestamp; +use rustecal::{Ecal, EcalComponents, TypedPublisher}; use rustecal_types_bytes::BytesMessage; fn main() -> Result<(), Box> { @@ -15,10 +15,12 @@ fn main() -> Result<(), Box> { let buffer = vec![counter; 1024]; counter = counter.wrapping_add(1); - let wrapped = BytesMessage { data: buffer.into() }; + let wrapped = BytesMessage { + data: buffer.into(), + }; publisher.send(&wrapped, Timestamp::Auto); - println!("Sent buffer filled with {}", counter); + println!("Sent buffer filled with {counter}"); std::thread::sleep(std::time::Duration::from_millis(500)); } diff --git a/rustecal-samples/pubsub/hello_receive/src/main.rs b/rustecal-samples/pubsub/hello_receive/src/main.rs index 9c4eb91..704485e 100644 --- a/rustecal-samples/pubsub/hello_receive/src/main.rs +++ b/rustecal-samples/pubsub/hello_receive/src/main.rs @@ -1,5 +1,5 @@ -use rustecal::{Ecal, EcalComponents, TypedSubscriber}; use rustecal::pubsub::typed_subscriber::Received; +use rustecal::{Ecal, EcalComponents, TypedSubscriber}; use rustecal_types_string::StringMessage; fn main() -> Result<(), Box> { diff --git a/rustecal-samples/pubsub/hello_send/src/main.rs b/rustecal-samples/pubsub/hello_send/src/main.rs index 1762546..49d4c25 100644 --- a/rustecal-samples/pubsub/hello_send/src/main.rs +++ b/rustecal-samples/pubsub/hello_send/src/main.rs @@ -1,5 +1,5 @@ -use rustecal::{Ecal, EcalComponents, TypedPublisher}; use rustecal::pubsub::publisher::Timestamp; +use rustecal::{Ecal, EcalComponents, TypedPublisher}; use rustecal_types_string::StringMessage; fn main() -> Result<(), Box> { @@ -12,9 +12,9 @@ fn main() -> Result<(), Box> { let mut count = 0; while Ecal::ok() { count += 1; - let msg = format!("HELLO WORLD FROM RUST ({})", count); + let msg = format!("HELLO WORLD FROM RUST ({count})"); - let wrapped = StringMessage{ data: msg.into()}; + let wrapped = StringMessage { data: msg.into() }; publisher.send(&wrapped, Timestamp::Auto); println!("Sent: {}", wrapped.data); diff --git a/rustecal-samples/pubsub/person_receive/build.rs b/rustecal-samples/pubsub/person_receive/build.rs index 492f769..60870d5 100644 --- a/rustecal-samples/pubsub/person_receive/build.rs +++ b/rustecal-samples/pubsub/person_receive/build.rs @@ -6,5 +6,6 @@ fn main() { "proto/house.proto", ], &["proto"], - ).unwrap(); -} \ No newline at end of file + ) + .unwrap(); +} diff --git a/rustecal-samples/pubsub/person_receive/src/main.rs b/rustecal-samples/pubsub/person_receive/src/main.rs index 1bdc113..6b73a75 100644 --- a/rustecal-samples/pubsub/person_receive/src/main.rs +++ b/rustecal-samples/pubsub/person_receive/src/main.rs @@ -1,10 +1,16 @@ -use rustecal::{Ecal, EcalComponents, TypedSubscriber}; use rustecal::pubsub::typed_subscriber::Received; -use rustecal_types_protobuf::{ProtobufMessage, IsProtobufType}; +use rustecal::{Ecal, EcalComponents, TypedSubscriber}; +use rustecal_types_protobuf::{IsProtobufType, ProtobufMessage}; -mod people { include!(concat!(env!("OUT_DIR"), "/pb.people.rs")); } -mod animal { include!(concat!(env!("OUT_DIR"), "/pb.animal.rs")); } -mod environment { include!(concat!(env!("OUT_DIR"), "/pb.environment.rs")); } +mod people { + include!(concat!(env!("OUT_DIR"), "/pb.people.rs")); +} +mod animal { + include!(concat!(env!("OUT_DIR"), "/pb.animal.rs")); +} +mod environment { + include!(concat!(env!("OUT_DIR"), "/pb.environment.rs")); +} use people::Person; impl IsProtobufType for Person {} @@ -34,8 +40,14 @@ fn main() -> Result<(), Box> { println!("person name : {}", person.name); println!("person stype : {}", person.stype); println!("person email : {}", person.email); - println!("dog.name : {}", person.dog.as_ref().map_or("", |d| &d.name)); - println!("house.rooms : {}", person.house.as_ref().map_or(0, |h| h.rooms)); + println!( + "dog.name : {}", + person.dog.as_ref().map_or("", |d| &d.name) + ); + println!( + "house.rooms : {}", + person.house.as_ref().map_or(0, |h| h.rooms) + ); println!("------------------------------------------\n"); }); diff --git a/rustecal-samples/pubsub/person_send/build.rs b/rustecal-samples/pubsub/person_send/build.rs index 492f769..60870d5 100644 --- a/rustecal-samples/pubsub/person_send/build.rs +++ b/rustecal-samples/pubsub/person_send/build.rs @@ -6,5 +6,6 @@ fn main() { "proto/house.proto", ], &["proto"], - ).unwrap(); -} \ No newline at end of file + ) + .unwrap(); +} diff --git a/rustecal-samples/pubsub/person_send/src/main.rs b/rustecal-samples/pubsub/person_send/src/main.rs index f643ad3..5803850 100644 --- a/rustecal-samples/pubsub/person_send/src/main.rs +++ b/rustecal-samples/pubsub/person_send/src/main.rs @@ -1,9 +1,15 @@ use rustecal::{Ecal, EcalComponents, TypedPublisher}; -use rustecal_types_protobuf::{ProtobufMessage, IsProtobufType}; +use rustecal_types_protobuf::{IsProtobufType, ProtobufMessage}; -mod people { include!(concat!(env!("OUT_DIR"), "/pb.people.rs")); } -mod animal { include!(concat!(env!("OUT_DIR"), "/pb.animal.rs")); } -mod environment { include!(concat!(env!("OUT_DIR"), "/pb.environment.rs")); } +mod people { + include!(concat!(env!("OUT_DIR"), "/pb.people.rs")); +} +mod animal { + include!(concat!(env!("OUT_DIR"), "/pb.animal.rs")); +} +mod environment { + include!(concat!(env!("OUT_DIR"), "/pb.environment.rs")); +} use people::Person; use rustecal::pubsub::publisher::Timestamp; @@ -30,21 +36,27 @@ fn main() -> Result<(), Box> { name: "Brandy".to_string(), colour: "Brown".to_string(), }), - house: Some(environment::House { - rooms: 4, - }), + house: Some(environment::House { rooms: 4 }), }; println!("person id : {}", person.id); println!("person name : {}", person.name); println!("person stype : {}", person.stype); println!("person email : {}", person.email); - println!("dog.name : {}", person.dog.as_ref().map_or("", |d| &d.name)); - println!("house.rooms : {}", person.house.as_ref().map_or(0, |h| h.rooms)); + println!( + "dog.name : {}", + person.dog.as_ref().map_or("", |d| &d.name) + ); + println!( + "house.rooms : {}", + person.house.as_ref().map_or(0, |h| h.rooms) + ); println!(); // wrap the person struct in ProtobufMessage - let wrapped = ProtobufMessage { data: person.into() }; + let wrapped = ProtobufMessage { + data: person.into(), + }; publisher.send(&wrapped, Timestamp::Auto); std::thread::sleep(std::time::Duration::from_millis(500)); diff --git a/rustecal-samples/pubsub/serde_receive/src/main.rs b/rustecal-samples/pubsub/serde_receive/src/main.rs index b159968..e052048 100644 --- a/rustecal-samples/pubsub/serde_receive/src/main.rs +++ b/rustecal-samples/pubsub/serde_receive/src/main.rs @@ -1,6 +1,6 @@ +use rustecal::pubsub::typed_subscriber::Received; use rustecal::{Ecal, EcalComponents, TypedSubscriber}; use rustecal_types_serde::JsonMessage; -use rustecal::pubsub::typed_subscriber::Received; #[derive(serde::Serialize, serde::Deserialize, Clone, Debug)] struct SimpleMessage { diff --git a/rustecal-samples/pubsub/serde_send/src/main.rs b/rustecal-samples/pubsub/serde_send/src/main.rs index 9bcce40..86b66dc 100644 --- a/rustecal-samples/pubsub/serde_send/src/main.rs +++ b/rustecal-samples/pubsub/serde_send/src/main.rs @@ -1,5 +1,5 @@ -use rustecal::{Ecal, EcalComponents, TypedPublisher}; use rustecal::pubsub::publisher::Timestamp; +use rustecal::{Ecal, EcalComponents, TypedPublisher}; use rustecal_types_serde::JsonMessage; #[derive(serde::Serialize, serde::Deserialize, Clone, Debug)] diff --git a/rustecal-samples/service/mirror_client/src/main.rs b/rustecal-samples/service/mirror_client/src/main.rs index eb51b56..b38d6c8 100644 --- a/rustecal-samples/service/mirror_client/src/main.rs +++ b/rustecal-samples/service/mirror_client/src/main.rs @@ -1,5 +1,5 @@ +use rustecal::{CallState, ServiceClient, ServiceRequest}; use rustecal::{Ecal, EcalComponents}; -use rustecal::{ServiceClient, ServiceRequest, CallState}; use std::thread; use std::time::Duration; @@ -31,28 +31,26 @@ fn main() -> Result<(), Box> { let response = instance.call(method_name, request.clone(), Some(1000)); println!(); - println!("Method '{}' called with message: stressed", method_name); + println!("Method '{method_name}' called with message: stressed"); match response { - Some(res) => { - match CallState::from(res.success as i32) { - CallState::Executed => { - let text = String::from_utf8_lossy(&res.payload); - println!( - "Received response: {} from service id {:?}", - text, res.server_id.service_id.entity_id - ); - } - CallState::Failed => { - println!( - "Received error: {} from service id {:?}", - res.error_msg.unwrap_or_else(|| "Unknown".into()), - res.server_id.service_id.entity_id - ); - } - _ => {} + Some(res) => match CallState::from(res.success as i32) { + CallState::Executed => { + let text = String::from_utf8_lossy(&res.payload); + println!( + "Received response: {} from service id {:?}", + text, res.server_id.service_id.entity_id + ); } - } + CallState::Failed => { + println!( + "Received error: {} from service id {:?}", + res.error_msg.unwrap_or_else(|| "Unknown".into()), + res.server_id.service_id.entity_id + ); + } + _ => {} + }, None => { println!("Method blocking call failed .."); } diff --git a/rustecal-samples/service/mirror_client_instances/src/main.rs b/rustecal-samples/service/mirror_client_instances/src/main.rs index 9c78e79..db41907 100644 --- a/rustecal-samples/service/mirror_client_instances/src/main.rs +++ b/rustecal-samples/service/mirror_client_instances/src/main.rs @@ -5,8 +5,12 @@ use std::time::Duration; fn main() -> Result<(), Box> { // initialize eCAL - Ecal::initialize(Some("mirror client instances rust"), EcalComponents::DEFAULT, None) - .expect("eCAL initialization failed"); + Ecal::initialize( + Some("mirror client instances rust"), + EcalComponents::DEFAULT, + None, + ) + .expect("eCAL initialization failed"); let client = ServiceClient::new("mirror")?; let methods = ["echo", "reverse"]; @@ -29,10 +33,7 @@ fn main() -> Result<(), Box> { let response = instance.call(method, request.clone(), Some(1000)); println!(); - println!( - "Method '{}' called with message: stressed", - method - ); + println!("Method '{method}' called with message: stressed"); match response { Some(res) => { diff --git a/rustecal-samples/service/mirror_server/src/main.rs b/rustecal-samples/service/mirror_server/src/main.rs index 5189109..2fd23ea 100644 --- a/rustecal-samples/service/mirror_server/src/main.rs +++ b/rustecal-samples/service/mirror_server/src/main.rs @@ -1,5 +1,5 @@ use rustecal::{Ecal, EcalComponents}; -use rustecal::{ServiceServer, MethodInfo}; +use rustecal::{MethodInfo, ServiceServer}; fn main() -> Result<(), Box> { // initialize eCAL @@ -10,22 +10,28 @@ fn main() -> Result<(), Box> { let mut server = ServiceServer::new("mirror")?; // register "echo" method: respond with request unchanged - server.add_method("echo", Box::new(|info: MethodInfo, req: &[u8]| { - println!("Method : '{}' called", info.method_name); - println!("Request : {}", String::from_utf8_lossy(req)); - println!("Response : {}\n", String::from_utf8_lossy(req)); - req.to_vec() - }))?; + server.add_method( + "echo", + Box::new(|info: MethodInfo, req: &[u8]| { + println!("Method : '{}' called", info.method_name); + println!("Request : {}", String::from_utf8_lossy(req)); + println!("Response : {}\n", String::from_utf8_lossy(req)); + req.to_vec() + }), + )?; // register "reverse" method: respond with request reversed - server.add_method("reverse", Box::new(|info: MethodInfo, req: &[u8]| { - let mut reversed = req.to_vec(); - reversed.reverse(); - println!("Method : '{}' called", info.method_name); - println!("Request : {}", String::from_utf8_lossy(req)); - println!("Response : {}\n", String::from_utf8_lossy(&reversed)); - reversed - }))?; + server.add_method( + "reverse", + Box::new(|info: MethodInfo, req: &[u8]| { + let mut reversed = req.to_vec(); + reversed.reverse(); + println!("Method : '{}' called", info.method_name); + println!("Request : {}", String::from_utf8_lossy(req)); + println!("Response : {}\n", String::from_utf8_lossy(&reversed)); + reversed + }), + )?; println!("Rust mirror service running. Press Ctrl+C to exit."); diff --git a/rustecal-service/src/client.rs b/rustecal-service/src/client.rs index be8c080..55d4bad 100644 --- a/rustecal-service/src/client.rs +++ b/rustecal-service/src/client.rs @@ -1,7 +1,7 @@ -use rustecal_sys::*; use crate::client_instance::ClientInstance; -use crate::types::ServiceRequest; use crate::response::ServiceResponse; +use crate::types::ServiceRequest; +use rustecal_sys::*; use std::ffi::CString; use std::os::raw::c_void; use std::ptr; @@ -22,7 +22,12 @@ impl ServiceClient { } } - pub fn call(&self, method: &str, request: ServiceRequest, timeout_ms: Option) -> Option { + pub fn call( + &self, + method: &str, + request: ServiceRequest, + timeout_ms: Option, + ) -> Option { self.call_all(method, request, timeout_ms)?.pop() } diff --git a/rustecal-service/src/client_instance.rs b/rustecal-service/src/client_instance.rs index 66ac160..4f9455c 100644 --- a/rustecal-service/src/client_instance.rs +++ b/rustecal-service/src/client_instance.rs @@ -1,5 +1,5 @@ -use crate::types::{ServiceId, ServiceRequest}; use crate::response::ServiceResponse; +use crate::types::{ServiceId, ServiceRequest}; use rustecal_sys::*; use std::ffi::CString; use std::os::raw::c_void; diff --git a/rustecal-service/src/lib.rs b/rustecal-service/src/lib.rs index eb247ab..b042554 100644 --- a/rustecal-service/src/lib.rs +++ b/rustecal-service/src/lib.rs @@ -13,11 +13,11 @@ //! let response = client.call("Hello!".as_bytes(), std::time::Duration::from_millis(500)); //! ``` -pub mod types; pub mod client; pub mod client_instance; -pub mod server; pub mod response; +pub mod server; +pub mod types; // Public API pub use client::ServiceClient; @@ -25,4 +25,3 @@ pub use client_instance::ClientInstance; pub use server::ServiceServer; pub use types::ServiceRequest; pub use types::ServiceResponse; - diff --git a/rustecal-service/src/response.rs b/rustecal-service/src/response.rs index 5a260aa..841a519 100644 --- a/rustecal-service/src/response.rs +++ b/rustecal-service/src/response.rs @@ -1,5 +1,5 @@ -use rustecal_sys::*; use crate::types::{CallState, ServiceId}; +use rustecal_sys::*; use std::ffi::CStr; /// Represents a structured response to a service request, @@ -23,7 +23,9 @@ impl ServiceResponse { None } else { Some(unsafe { - CStr::from_ptr(response.error_msg).to_string_lossy().into_owned() + CStr::from_ptr(response.error_msg) + .to_string_lossy() + .into_owned() }) }; @@ -31,10 +33,7 @@ impl ServiceResponse { vec![] } else { unsafe { - std::slice::from_raw_parts( - response.response as *const u8, - response.response_length, - ) + std::slice::from_raw_parts(response.response as *const u8, response.response_length) .to_vec() } }; diff --git a/rustecal-service/src/server.rs b/rustecal-service/src/server.rs index ff2956a..c2d5b93 100644 --- a/rustecal-service/src/server.rs +++ b/rustecal-service/src/server.rs @@ -1,5 +1,5 @@ -use rustecal_sys::*; use crate::types::{MethodInfo, ServiceCallback}; +use rustecal_sys::*; use std::collections::HashMap; use std::ffi::{CStr, CString}; use std::os::raw::{c_int, c_void}; @@ -24,10 +24,7 @@ impl ServiceServer { return Err("Failed to create eCAL_ServiceServer".into()); } - Ok(Self { - handle, - callbacks, - }) + Ok(Self { handle, callbacks }) } pub fn add_method(&mut self, method: &str, callback: ServiceCallback) -> Result<(), String> { diff --git a/rustecal-service/src/types.rs b/rustecal-service/src/types.rs index ff32496..a2adb4a 100644 --- a/rustecal-service/src/types.rs +++ b/rustecal-service/src/types.rs @@ -19,9 +19,15 @@ impl From for CallState { fn from(value: i32) -> Self { match value { x if x == rustecal_sys::eCAL_eCallState_eCAL_eCallState_none as i32 => CallState::None, - x if x == rustecal_sys::eCAL_eCallState_eCAL_eCallState_executed as i32 => CallState::Executed, - x if x == rustecal_sys::eCAL_eCallState_eCAL_eCallState_timeouted as i32 => CallState::Timeout, - x if x == rustecal_sys::eCAL_eCallState_eCAL_eCallState_failed as i32 => CallState::Failed, + x if x == rustecal_sys::eCAL_eCallState_eCAL_eCallState_executed as i32 => { + CallState::Executed + } + x if x == rustecal_sys::eCAL_eCallState_eCAL_eCallState_timeouted as i32 => { + CallState::Timeout + } + x if x == rustecal_sys::eCAL_eCallState_eCAL_eCallState_failed as i32 => { + CallState::Failed + } other => CallState::Unknown(other), } } diff --git a/rustecal-sys/build.rs b/rustecal-sys/build.rs index ddd4b3d..ca619fa 100644 --- a/rustecal-sys/build.rs +++ b/rustecal-sys/build.rs @@ -18,19 +18,19 @@ fn main() { if cfg!(target_os = "windows") { // --- Windows: Use ECAL_HOME --- - let ecal_home = env::var("ECAL_HOME") - .expect("ECAL_HOME environment variable must be set on Windows"); - let include_path = format!("{}/include", ecal_home); - let lib_path = format!("{}/lib", ecal_home); + let ecal_home = + env::var("ECAL_HOME").expect("ECAL_HOME environment variable must be set on Windows"); + let include_path = format!("{ecal_home}/include"); + let lib_path = format!("{ecal_home}/lib"); - println!("cargo:rustc-link-search=native={}", lib_path); + println!("cargo:rustc-link-search=native={lib_path}"); println!("cargo:rustc-link-lib=static=ecal_core_c"); - builder = builder.clang_arg(format!("-I{}", include_path)); + builder = builder.clang_arg(format!("-I{include_path}")); // Debug info println!("cargo:warning=Building on Windows"); - println!("cargo:warning=Using ECAL_HOME = {}", ecal_home); + println!("cargo:warning=Using ECAL_HOME = {ecal_home}"); } else if cfg!(target_os = "linux") { // --- Linux: Assume system-wide install --- println!("cargo:rustc-link-lib=dylib=ecal_core_c"); @@ -47,9 +47,7 @@ fn main() { } // Final bindgen output - let bindings = builder - .generate() - .expect("Unable to generate bindings"); + let bindings = builder.generate().expect("Unable to generate bindings"); let out_path = PathBuf::from(env::var("OUT_DIR").unwrap()); bindings diff --git a/rustecal-types-bytes/src/lib.rs b/rustecal-types-bytes/src/lib.rs index 999630e..81f7bd2 100644 --- a/rustecal-types-bytes/src/lib.rs +++ b/rustecal-types-bytes/src/lib.rs @@ -2,13 +2,10 @@ //! //! Provides support for sending and receiving raw binary messages (`Vec`) with rustecal. -use std::{ - borrow::Cow, - sync::Arc, -}; use rustecal_core::types::DataTypeInfo; use rustecal_pubsub::typed_publisher::PublisherMessage; use rustecal_pubsub::typed_subscriber::SubscriberMessage; +use std::{borrow::Cow, sync::Arc}; /// A wrapper for raw‐binary messages used with typed eCAL pub/sub. /// @@ -21,7 +18,9 @@ pub struct BytesMessage<'a> { impl<'a> BytesMessage<'a> { /// Construct for sending: takes ownership of an `Arc<[u8]>`. pub fn owned(data: Arc<[u8]>) -> BytesMessage<'static> { - BytesMessage { data: Cow::Owned(data.as_ref().to_vec()) } + BytesMessage { + data: Cow::Owned(data.as_ref().to_vec()), + } } } @@ -32,8 +31,8 @@ impl<'a> SubscriberMessage<'a> for BytesMessage<'a> { /// raw/bytes, no descriptor fn datatype() -> DataTypeInfo { DataTypeInfo { - encoding: "raw".into(), - type_name: "bytes".into(), + encoding: "raw".into(), + type_name: "bytes".into(), descriptor: Vec::new(), } } @@ -41,7 +40,9 @@ impl<'a> SubscriberMessage<'a> for BytesMessage<'a> { /// On receive, we get a `&[u8]` slice straight from shared memory. fn from_bytes(bytes: &'a [u8], _info: &DataTypeInfo) -> Option { // zero‐copy: borrow the slice - Some(BytesMessage { data: Cow::Borrowed(bytes) }) + Some(BytesMessage { + data: Cow::Borrowed(bytes), + }) } } diff --git a/rustecal-types-protobuf/src/lib.rs b/rustecal-types-protobuf/src/lib.rs index 77c37ca..d2e7a5b 100644 --- a/rustecal-types-protobuf/src/lib.rs +++ b/rustecal-types-protobuf/src/lib.rs @@ -2,11 +2,11 @@ //! //! Provides support for Protobuf message serialization with rustecal. -use std::sync::Arc; use prost::Message; use rustecal_core::types::DataTypeInfo; use rustecal_pubsub::typed_publisher::PublisherMessage; use rustecal_pubsub::typed_subscriber::SubscriberMessage; +use std::sync::Arc; /// Marker trait to opt-in a Protobuf type for use with eCAL. /// @@ -48,7 +48,7 @@ where /// - `Some(ProtobufMessage)` on success /// - `None` if decoding fails fn from_bytes(bytes: &[u8], _data_type_info: &DataTypeInfo) -> Option { - T::decode(bytes.as_ref()).ok().map(|msg| ProtobufMessage { + T::decode(bytes).ok().map(|msg| ProtobufMessage { data: Arc::new(msg), }) } diff --git a/rustecal-types-serde/src/cbor_message.rs b/rustecal-types-serde/src/cbor_message.rs index decb1b1..db3e477 100644 --- a/rustecal-types-serde/src/cbor_message.rs +++ b/rustecal-types-serde/src/cbor_message.rs @@ -1,10 +1,10 @@ -use std::sync::Arc; -use serde::{Deserialize, Serialize}; +use crate::format_support::{short_type_name, FormatSupport}; +use crate::make_format; use rustecal_core::types::DataTypeInfo; use rustecal_pubsub::typed_publisher::PublisherMessage; use rustecal_pubsub::typed_subscriber::SubscriberMessage; -use crate::format_support::{FormatSupport, short_type_name}; -use crate::make_format; +use serde::{Deserialize, Serialize}; +use std::sync::Arc; /// CBOR support using `serde_cbor`. #[derive(Debug, Clone)] @@ -22,20 +22,28 @@ impl FormatSupport for CborSupport { make_format!(CborMessage, CborSupport); impl PublisherMessage for CborMessage -where T: Serialize + for<'de> Deserialize<'de> + Clone +where + T: Serialize + for<'de> Deserialize<'de> + Clone, { fn datatype() -> DataTypeInfo { - DataTypeInfo { encoding: CborSupport::ENCODING.into(), type_name: short_type_name::(), descriptor: vec![] } + DataTypeInfo { + encoding: CborSupport::ENCODING.into(), + type_name: short_type_name::(), + descriptor: vec![], + } } fn to_bytes(&self) -> Arc<[u8]> { Arc::from(CborSupport::encode(&*self.data)) } } impl SubscriberMessage<'_> for CborMessage -where T: Serialize + for<'de> Deserialize<'de> + Clone +where + T: Serialize + for<'de> Deserialize<'de> + Clone, { - fn datatype() -> DataTypeInfo { as PublisherMessage>::datatype() } + fn datatype() -> DataTypeInfo { + as PublisherMessage>::datatype() + } fn from_bytes(bytes: &[u8], _dt: &DataTypeInfo) -> Option { - CborSupport::decode(bytes.as_ref()).map(|p| CborMessage { data: Arc::new(p) }) + CborSupport::decode(bytes).map(|p| CborMessage { data: Arc::new(p) }) } } diff --git a/rustecal-types-serde/src/format_support.rs b/rustecal-types-serde/src/format_support.rs index 2a13166..d9bc580 100644 --- a/rustecal-types-serde/src/format_support.rs +++ b/rustecal-types-serde/src/format_support.rs @@ -20,17 +20,21 @@ macro_rules! make_format { ($msg_type:ident, $support:ty) => { #[derive(Debug, Clone)] pub struct $msg_type - where T: serde::Serialize + for<'de> serde::Deserialize<'de> + Clone + where + T: serde::Serialize + for<'de> serde::Deserialize<'de> + Clone, { /// The inner payload. pub data: std::sync::Arc, } impl $msg_type - where T: serde::Serialize + for<'de> serde::Deserialize<'de> + Clone + where + T: serde::Serialize + for<'de> serde::Deserialize<'de> + Clone, { /// Create a new message with given payload. pub fn new(payload: T) -> Self { - $msg_type { data: std::sync::Arc::new(payload) } + $msg_type { + data: std::sync::Arc::new(payload), + } } } }; diff --git a/rustecal-types-serde/src/json_message.rs b/rustecal-types-serde/src/json_message.rs index 215f3a8..347c060 100644 --- a/rustecal-types-serde/src/json_message.rs +++ b/rustecal-types-serde/src/json_message.rs @@ -1,10 +1,10 @@ -use std::sync::Arc; -use serde::{Deserialize, Serialize}; +use crate::format_support::{short_type_name, FormatSupport}; +use crate::make_format; use rustecal_core::types::DataTypeInfo; use rustecal_pubsub::typed_publisher::PublisherMessage; use rustecal_pubsub::typed_subscriber::SubscriberMessage; -use crate::format_support::{FormatSupport, short_type_name}; -use crate::make_format; +use serde::{Deserialize, Serialize}; +use std::sync::Arc; /// JSON support using `serde_json`. #[derive(Debug, Clone)] @@ -22,20 +22,28 @@ impl FormatSupport for JsonSupport { make_format!(JsonMessage, JsonSupport); impl PublisherMessage for JsonMessage -where T: Serialize + for<'de> Deserialize<'de> + Clone +where + T: Serialize + for<'de> Deserialize<'de> + Clone, { fn datatype() -> DataTypeInfo { - DataTypeInfo { encoding: JsonSupport::ENCODING.into(), type_name: short_type_name::(), descriptor: vec![] } + DataTypeInfo { + encoding: JsonSupport::ENCODING.into(), + type_name: short_type_name::(), + descriptor: vec![], + } } fn to_bytes(&self) -> Arc<[u8]> { Arc::from(JsonSupport::encode(&*self.data)) } } impl SubscriberMessage<'_> for JsonMessage -where T: Serialize + for<'de> Deserialize<'de> + Clone +where + T: Serialize + for<'de> Deserialize<'de> + Clone, { - fn datatype() -> DataTypeInfo { as PublisherMessage>::datatype() } + fn datatype() -> DataTypeInfo { + as PublisherMessage>::datatype() + } fn from_bytes(bytes: &[u8], _dt: &DataTypeInfo) -> Option { - JsonSupport::decode(bytes.as_ref()).map(|p| JsonMessage { data: Arc::new(p) }) + JsonSupport::decode(bytes).map(|p| JsonMessage { data: Arc::new(p) }) } } diff --git a/rustecal-types-serde/src/lib.rs b/rustecal-types-serde/src/lib.rs index 52793d7..76f602b 100644 --- a/rustecal-types-serde/src/lib.rs +++ b/rustecal-types-serde/src/lib.rs @@ -2,11 +2,11 @@ //! //! eCAL Pub/Sub support for Serde-enabled messages. +pub mod cbor_message; pub mod format_support; pub mod json_message; -pub mod cbor_message; pub mod msgpack_message; -pub use json_message::JsonMessage; pub use cbor_message::CborMessage; +pub use json_message::JsonMessage; pub use msgpack_message::MsgpackMessage; diff --git a/rustecal-types-serde/src/msgpack_message.rs b/rustecal-types-serde/src/msgpack_message.rs index 57eb127..a4ef614 100644 --- a/rustecal-types-serde/src/msgpack_message.rs +++ b/rustecal-types-serde/src/msgpack_message.rs @@ -1,10 +1,10 @@ -use std::sync::Arc; -use serde::{Deserialize, Serialize}; +use crate::format_support::{short_type_name, FormatSupport}; +use crate::make_format; use rustecal_core::types::DataTypeInfo; use rustecal_pubsub::typed_publisher::PublisherMessage; use rustecal_pubsub::typed_subscriber::SubscriberMessage; -use crate::format_support::{FormatSupport, short_type_name}; -use crate::make_format; +use serde::{Deserialize, Serialize}; +use std::sync::Arc; /// MessagePack support using `rmp-serde`. #[derive(Debug, Clone)] @@ -22,20 +22,28 @@ impl FormatSupport for MsgpackSupport { make_format!(MsgpackMessage, MsgpackSupport); impl PublisherMessage for MsgpackMessage -where T: Serialize + for<'de> Deserialize<'de> + Clone +where + T: Serialize + for<'de> Deserialize<'de> + Clone, { fn datatype() -> DataTypeInfo { - DataTypeInfo { encoding: MsgpackSupport::ENCODING.into(), type_name: short_type_name::(), descriptor: vec![] } + DataTypeInfo { + encoding: MsgpackSupport::ENCODING.into(), + type_name: short_type_name::(), + descriptor: vec![], + } } fn to_bytes(&self) -> Arc<[u8]> { Arc::from(MsgpackSupport::encode(&*self.data)) } } impl SubscriberMessage<'_> for MsgpackMessage -where T: Serialize + for<'de> Deserialize<'de> + Clone +where + T: Serialize + for<'de> Deserialize<'de> + Clone, { - fn datatype() -> DataTypeInfo { as PublisherMessage>::datatype() } + fn datatype() -> DataTypeInfo { + as PublisherMessage>::datatype() + } fn from_bytes(bytes: &[u8], _dt: &DataTypeInfo) -> Option { - MsgpackSupport::decode(bytes.as_ref()).map(|p| MsgpackMessage { data: Arc::new(p) }) + MsgpackSupport::decode(bytes).map(|p| MsgpackMessage { data: Arc::new(p) }) } } diff --git a/rustecal-types-serde/tests/format_support.rs b/rustecal-types-serde/tests/format_support.rs index 3043d87..62c89ee 100644 --- a/rustecal-types-serde/tests/format_support.rs +++ b/rustecal-types-serde/tests/format_support.rs @@ -3,7 +3,10 @@ use rustecal_types_serde::json_message::JsonSupport; #[test] fn short_type_name_for_implementor() { - assert_eq!(format_support::short_type_name::(), "JsonSupport"); + assert_eq!( + format_support::short_type_name::(), + "JsonSupport" + ); } #[test] @@ -13,5 +16,8 @@ fn short_type_name_for_nested_type() { pub struct TestType; } } - assert_eq!(format_support::short_type_name::(), "TestType"); + assert_eq!( + format_support::short_type_name::(), + "TestType" + ); } diff --git a/rustecal-types-string/src/lib.rs b/rustecal-types-string/src/lib.rs index fa42cf8..05be28b 100644 --- a/rustecal-types-string/src/lib.rs +++ b/rustecal-types-string/src/lib.rs @@ -2,11 +2,11 @@ //! //! Provides support for sending and receiving `String` messages with rustecal. -use std::str; -use std::sync::Arc; use rustecal_core::types::DataTypeInfo; use rustecal_pubsub::typed_publisher::PublisherMessage; use rustecal_pubsub::typed_subscriber::SubscriberMessage; +use std::str; +use std::sync::Arc; /// A wrapper for UTF-8 string messages used with typed eCAL pub/sub. /// @@ -28,9 +28,9 @@ impl SubscriberMessage<'_> for StringMessage { /// Attempts to decode a UTF-8 string from a byte buffer. fn from_bytes(bytes: &[u8], _data_type_info: &DataTypeInfo) -> Option { - str::from_utf8(bytes.as_ref()) - .ok() - .map(|s| StringMessage{ data: Arc::::from(s) }) + str::from_utf8(bytes).ok().map(|s| StringMessage { + data: Arc::::from(s), + }) } } diff --git a/rustecal/src/lib.rs b/rustecal/src/lib.rs index bb57daf..5edf1b5 100644 --- a/rustecal/src/lib.rs +++ b/rustecal/src/lib.rs @@ -21,10 +21,9 @@ //! ``` //! - // ————————————————————————————————————————————————————————————————————————————— // Core initialization & types (always available) -pub use rustecal_core::{Ecal, EcalComponents, Configuration}; +pub use rustecal_core::{Configuration, Ecal, EcalComponents}; // ————————————————————————————————————————————————————————————————————————————— // Pub/Sub API (requires the `pubsub` feature) @@ -37,10 +36,13 @@ pub mod pubsub { #[cfg(feature = "pubsub")] pub use rustecal_pubsub::{ // low‑level handles - Publisher, Subscriber, + Publisher, + PublisherMessage, + Subscriber, + SubscriberMessage, // typed wrappers - TypedPublisher, PublisherMessage, - TypedSubscriber, SubscriberMessage, + TypedPublisher, + TypedSubscriber, }; // ————————————————————————————————————————————————————————————————————————————— @@ -53,14 +55,19 @@ pub mod service { #[cfg(feature = "service")] pub use rustecal_service::{ - // server & client entrypoints - ServiceServer, ServiceClient, ClientInstance, + ClientInstance, + ServiceClient, // request/response types - ServiceRequest, ServiceResponse, + ServiceRequest, + ServiceResponse, + // server & client entrypoints + ServiceServer, }; #[cfg(feature = "service")] pub use rustecal_service::types::{ + CallState, // metadata & callback signature - MethodInfo, ServiceCallback, CallState, + MethodInfo, + ServiceCallback, };