pub trait ServiceClientTrait {
type Error;
// Required methods
fn send_request_raw(&mut self, request: &[u8]) -> Result<(), Self::Error>;
fn try_recv_reply_raw(
&mut self,
reply_buf: &mut [u8],
) -> Result<Option<usize>, Self::Error>;
// Provided methods
fn call_raw(
&mut self,
request: &[u8],
_reply_buf: &mut [u8],
) -> Result<usize, Self::Error>
where Self::Error: From<TransportError> { ... }
fn send_request<S: RosService>(
&mut self,
request: &S::Request,
req_buf: &mut [u8],
) -> Result<(), Self::Error>
where Self::Error: From<TransportError> { ... }
fn try_recv_reply<S: RosService>(
&mut self,
reply_buf: &mut [u8],
) -> Result<Option<S::Reply>, Self::Error>
where Self::Error: From<TransportError> { ... }
fn register_waker(&self, _waker: &Waker) { ... }
fn start_server_discovery(
&mut self,
_timeout_ms: u32,
) -> Result<(), Self::Error> { ... }
fn poll_server_discovery(&mut self) -> Result<Option<bool>, Self::Error> { ... }
fn is_server_ready(&self) -> bool { ... }
fn server_available(&self) -> Result<bool, Self::Error>
where Self::Error: From<TransportError> { ... }
fn call<S: RosService>(
&mut self,
request: &S::Request,
req_buf: &mut [u8],
_reply_buf: &mut [u8],
) -> Result<S::Reply, Self::Error>
where Self::Error: From<TransportError> { ... }
}Expand description
Service client trait for sending requests.
§Threading
&mut self on every method — the client is single-owner. For
fan-out request patterns, create one client per worker thread.
§Calling pattern
All in-tree backends route blocking waits through the executor:
send_request_raw(buf)— non-blocking; returns once the request is queued for transmission.- The executor’s
drive_ioruns. try_recv_reply_raw(buf)— non-blocking; returnsOk(Some(len))when the reply is back.
The deprecated call_raw blocking path is
kept for backwards compatibility but should not be called.
Required Associated Types§
Required Methods§
Sourcefn send_request_raw(&mut self, request: &[u8]) -> Result<(), Self::Error>
fn send_request_raw(&mut self, request: &[u8]) -> Result<(), Self::Error>
Send a service request without waiting for a reply (non-blocking).
The caller must subsequently poll try_recv_reply_raw
to retrieve the reply.
Provided Methods§
Sourcefn call_raw(
&mut self,
request: &[u8],
_reply_buf: &mut [u8],
) -> Result<usize, Self::Error>
👎Deprecated: use Client::call → Promise::wait with an executor instead
fn call_raw( &mut self, request: &[u8], _reply_buf: &mut [u8], ) -> Result<usize, Self::Error>
use Client::call → Promise::wait with an executor instead
Send a service request and wait for reply (blocking).
Deprecated — do not call. The default body returns Timeout
immediately without polling. Use Client::call →
Promise::wait(executor, timeout_ms) which lets the executor
drive I/O while waiting instead of busy-looping on
try_recv_reply_raw with no sleep (which starves the transport
on FreeRTOS / Zephyr single-threaded schedulers).
Backends that still need an internal blocking path should override this with a real sleep-between-polls implementation, but all in-tree backends (zenoh, XRCE) route blocking waits through the executor.
Sourcefn send_request<S: RosService>(
&mut self,
request: &S::Request,
req_buf: &mut [u8],
) -> Result<(), Self::Error>
fn send_request<S: RosService>( &mut self, request: &S::Request, req_buf: &mut [u8], ) -> Result<(), Self::Error>
Send a typed service request without waiting for a reply (non-blocking).
Serializes the request into req_buf and calls send_request_raw.
Sourcefn try_recv_reply<S: RosService>(
&mut self,
reply_buf: &mut [u8],
) -> Result<Option<S::Reply>, Self::Error>
fn try_recv_reply<S: RosService>( &mut self, reply_buf: &mut [u8], ) -> Result<Option<S::Reply>, Self::Error>
Poll for a typed reply to the most recently sent request (non-blocking).
Calls try_recv_reply_raw and deserializes if available.
Sourcefn register_waker(&self, _waker: &Waker)
fn register_waker(&self, _waker: &Waker)
Register an async waker to be notified when a reply arrives.
Called from Future::poll() implementations to store the waker.
The transport backend calls waker.wake() from its reply callback
when a response is available, enabling event-driven async without
busy-polling.
Default: no-op (backends that don’t support waking simply ignore this).
Sourcefn start_server_discovery(
&mut self,
_timeout_ms: u32,
) -> Result<(), Self::Error>
fn start_server_discovery( &mut self, _timeout_ms: u32, ) -> Result<(), Self::Error>
Begin a server-discovery query on this client (non-blocking).
Models rclcpp::ClientBase::wait_for_service machinery: the backend
fires off a discovery probe (typically a Zenoh liveliness query
against the matching server’s wildcarded liveliness keyexpr) and
the caller polls poll_server_discovery
to collect the result.
Default impl: no-op success. Backends without a discovery channel
(or those that always assume the server is reachable) can leave
this default and have poll_server_discovery return
Ok(Some(true)) immediately.
Sourcefn poll_server_discovery(&mut self) -> Result<Option<bool>, Self::Error>
fn poll_server_discovery(&mut self) -> Result<Option<bool>, Self::Error>
Poll an in-flight server-discovery query.
Ok(Some(true))— at least one matching server has reported back; safe to send the first request.Ok(Some(false))— discovery query finished without finding any matching server (timeout / no-replies).Ok(None)— query still in flight.Err(_)— transport-level failure unrelated to server presence.
Default impl: returns Ok(Some(true)) (i.e., “server is always
assumed reachable”). The Zenoh backend overrides this with a
liveliness-token check.
Sourcefn is_server_ready(&self) -> bool
fn is_server_ready(&self) -> bool
Synchronous, non-blocking check of whether a matching server is currently visible.
Mirrors rclcpp::ClientBase::service_is_ready. Backends that lack
discovery should keep the default true so existing call sites
don’t regress.
Default impl: always true.
Sourcefn server_available(&self) -> Result<bool, Self::Error>
fn server_available(&self) -> Result<bool, Self::Error>
Phase 124.C.1 — graph-aware server-availability probe.
Returns Ok(true) if at least one matching server has been
discovered, Ok(false) if none yet, or Err(_) if the
backend cannot answer (e.g. XRCE — micro-XRCE-DDS-Client has
no participant enumeration). Distinct from
is_server_ready, which collapses
“don’t know” and “no server” into the same false answer.
User-facing surface: Client<S>::server_available() in Rust,
nros_client_server_available() in C/C++. Clients use this
to gate the first call_raw so a startup-ordering race
(client opens before server’s discovery announcement lands)
doesn’t surface as a request-side timeout.
Default impl: Err(TransportError::Unsupported) — backends
that support graph introspection (zenoh queryable interest,
DDS built-in topic readers) opt in by overriding.
Sourcefn call<S: RosService>(
&mut self,
request: &S::Request,
req_buf: &mut [u8],
_reply_buf: &mut [u8],
) -> Result<S::Reply, Self::Error>
👎Deprecated: use Client::call → Promise::wait with an executor instead
fn call<S: RosService>( &mut self, request: &S::Request, req_buf: &mut [u8], _reply_buf: &mut [u8], ) -> Result<S::Reply, Self::Error>
use Client::call → Promise::wait with an executor instead
Call a service with typed messages (blocking).
Deprecated — do not call. The default body returns Timeout
immediately without polling. Use Client::call on the executor
instead, which drives I/O while waiting. See
call_raw for the same reasoning.
Dyn Compatibility§
This trait is not dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.