1#[zenoh_macros::unstable]
16use std::future::{IntoFuture, Ready};
17
18#[zenoh_macros::unstable]
19use tracing::error;
20#[zenoh_macros::unstable]
21use zenoh_core::{Resolvable, Wait};
22#[zenoh_macros::unstable]
23use zenoh_result::ZResult;
24
25#[zenoh_macros::unstable]
26use crate::api::handlers::locked;
27#[zenoh_macros::unstable]
28use crate::api::info::Transport;
29#[zenoh_macros::unstable]
30use crate::api::info::{Link, LinkEvent};
31#[zenoh_macros::unstable]
32use crate::api::Id;
33#[zenoh_macros::unstable]
34use crate::{
35 api::cancellation::SyncGroup,
36 api::session::{UndeclarableSealed, WeakSession},
37 handlers::{Callback, DefaultHandler, IntoHandler},
38};
39
40#[must_use = "Resolvables do nothing unless you resolve them using `.await` or `zenoh::Wait::wait`"]
61#[zenoh_macros::unstable]
62pub struct LinksBuilder<'a> {
63 session: &'a WeakSession,
64 transport: Option<Transport>,
65}
66
67#[zenoh_macros::unstable]
68impl<'a> LinksBuilder<'a> {
69 pub(crate) fn new(session: &'a WeakSession) -> Self {
70 Self {
71 session,
72 transport: None,
73 }
74 }
75
76 pub fn transport(mut self, transport: Transport) -> Self {
93 self.transport = Some(transport);
94 self
95 }
96}
97
98#[zenoh_macros::unstable]
99impl Resolvable for LinksBuilder<'_> {
100 type To = Box<dyn Iterator<Item = Link> + Send + Sync>;
101}
102
103#[zenoh_macros::unstable]
104impl Wait for LinksBuilder<'_> {
105 fn wait(self) -> Self::To {
106 self.session.runtime().get_links(self.transport.as_ref())
107 }
108}
109
110#[zenoh_macros::unstable]
111impl IntoFuture for LinksBuilder<'_> {
112 type Output = <Self as Resolvable>::To;
113 type IntoFuture = Ready<<Self as Resolvable>::To>;
114
115 fn into_future(self) -> Self::IntoFuture {
116 std::future::ready(self.wait())
117 }
118}
119
120#[zenoh_macros::unstable]
121pub(crate) struct LinkEventsListenerInner {
122 pub(crate) session: WeakSession,
123 pub(crate) id: Id,
124 pub(crate) undeclare_on_drop: bool,
125}
126
127#[zenoh_macros::unstable]
128impl std::fmt::Debug for LinkEventsListenerInner {
129 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
130 f.debug_struct("LinkEventsListenerInner")
131 .field("id", &self.id)
132 .field("undeclare_on_drop", &self.undeclare_on_drop)
133 .finish()
134 }
135}
136
137#[zenoh_macros::unstable]
168#[derive(Debug)]
169pub struct LinkEventsListener<Handler> {
170 pub(crate) inner: LinkEventsListenerInner,
171 pub(crate) handler: Handler,
172 pub(crate) callback_sync_group: SyncGroup,
173}
174
175#[zenoh_macros::unstable]
176impl<Handler> LinkEventsListener<Handler> {
177 #[inline]
193 pub fn undeclare(self) -> LinkEventsListenerUndeclaration<Handler>
194 where
195 Handler: Send,
196 {
197 self.undeclare_inner(())
198 }
199
200 fn undeclare_impl(&mut self) -> ZResult<()> {
201 self.inner.undeclare_on_drop = false;
203 self.inner
205 .session
206 .undeclare_transport_links_listener_inner(self.inner.id)
207 }
208
209 pub fn handler(&self) -> &Handler {
213 &self.handler
214 }
215
216 pub fn handler_mut(&mut self) -> &mut Handler {
220 &mut self.handler
221 }
222
223 #[zenoh_macros::internal]
224 pub fn set_background(&mut self, background: bool) {
225 self.inner.undeclare_on_drop = !background;
226 }
227}
228
229#[zenoh_macros::unstable]
230impl<Handler> Drop for LinkEventsListener<Handler> {
231 fn drop(&mut self) {
232 if self.inner.undeclare_on_drop {
233 if let Err(error) = self.undeclare_impl() {
234 error!(error);
235 }
236 }
237 }
238}
239
240#[zenoh_macros::unstable]
241impl<Handler: Send> UndeclarableSealed<()> for LinkEventsListener<Handler> {
242 type Undeclaration = LinkEventsListenerUndeclaration<Handler>;
243
244 fn undeclare_inner(self, _: ()) -> Self::Undeclaration {
245 LinkEventsListenerUndeclaration {
246 listener: self,
247 wait_callbacks: false,
248 }
249 }
250}
251
252#[zenoh_macros::unstable]
253impl<Handler> std::ops::Deref for LinkEventsListener<Handler> {
254 type Target = Handler;
255
256 fn deref(&self) -> &Self::Target {
257 &self.handler
258 }
259}
260
261#[zenoh_macros::unstable]
262impl<Handler> std::ops::DerefMut for LinkEventsListener<Handler> {
263 fn deref_mut(&mut self) -> &mut Self::Target {
264 &mut self.handler
265 }
266}
267
268#[zenoh_macros::unstable]
270pub struct LinkEventsListenerUndeclaration<Handler> {
271 listener: LinkEventsListener<Handler>,
272 wait_callbacks: bool,
273}
274
275#[zenoh_macros::unstable]
276impl<Handler> Resolvable for LinkEventsListenerUndeclaration<Handler> {
277 type To = ZResult<()>;
278}
279
280#[zenoh_macros::unstable]
281impl<Handler> LinkEventsListenerUndeclaration<Handler> {
282 #[zenoh_macros::internal_or_unstable]
283 pub fn wait_callbacks(mut self) -> Self {
285 self.wait_callbacks = true;
286 self
287 }
288}
289
290#[zenoh_macros::unstable]
291impl<Handler> Wait for LinkEventsListenerUndeclaration<Handler> {
292 fn wait(mut self) -> <Self as Resolvable>::To {
293 self.listener.undeclare_impl()?;
294 if self.wait_callbacks {
295 self.listener.callback_sync_group.wait();
296 }
297 Ok(())
298 }
299}
300
301#[zenoh_macros::unstable]
302impl<Handler> IntoFuture for LinkEventsListenerUndeclaration<Handler> {
303 type Output = <Self as Resolvable>::To;
304 type IntoFuture = Ready<<Self as Resolvable>::To>;
305
306 fn into_future(self) -> Self::IntoFuture {
307 std::future::ready(self.wait())
308 }
309}
310
311#[must_use = "Resolvables do nothing unless you resolve them using `.await` or `zenoh::Wait::wait`"]
340#[zenoh_macros::unstable]
341pub struct LinkEventsListenerBuilder<'a, Handler, const BACKGROUND: bool = false> {
342 session: &'a WeakSession,
343 handler: Handler,
344 history: bool,
345 transport: Option<Transport>,
346}
347
348#[zenoh_macros::unstable]
349impl<'a> LinkEventsListenerBuilder<'a, DefaultHandler> {
350 pub(crate) fn new(session: &'a WeakSession) -> Self {
351 Self {
352 session,
353 handler: DefaultHandler::default(),
354 history: false,
355 transport: None,
356 }
357 }
358}
359
360#[zenoh_macros::unstable]
361impl<'a, Handler> LinkEventsListenerBuilder<'a, Handler> {
362 pub fn history(mut self, enabled: bool) -> Self {
366 self.history = enabled;
367 self
368 }
369
370 pub fn with<H>(self, handler: H) -> LinkEventsListenerBuilder<'a, H>
372 where
373 H: IntoHandler<LinkEvent>,
374 {
375 LinkEventsListenerBuilder {
376 session: self.session,
377 handler,
378 history: self.history,
379 transport: self.transport,
380 }
381 }
382
383 pub fn transport(mut self, transport: Transport) -> Self {
401 self.transport = Some(transport);
402 self
403 }
404
405 pub fn callback<F>(self, callback: F) -> LinkEventsListenerBuilder<'a, Callback<LinkEvent>>
407 where
408 F: Fn(LinkEvent) + Send + Sync + 'static,
409 {
410 self.with(Callback::from(callback))
411 }
412
413 pub fn callback_mut<F>(self, callback: F) -> LinkEventsListenerBuilder<'a, Callback<LinkEvent>>
416 where
417 F: FnMut(LinkEvent) + Send + Sync + 'static,
418 {
419 self.callback(locked(callback))
420 }
421}
422
423#[zenoh_macros::unstable]
424impl<'a> LinkEventsListenerBuilder<'a, Callback<LinkEvent>> {
425 pub fn background(self) -> LinkEventsListenerBuilder<'a, Callback<LinkEvent>, true> {
450 LinkEventsListenerBuilder {
451 session: self.session,
452 handler: self.handler,
453 history: self.history,
454 transport: self.transport,
455 }
456 }
457}
458
459#[zenoh_macros::unstable]
460impl<Handler> Resolvable for LinkEventsListenerBuilder<'_, Handler>
461where
462 Handler: IntoHandler<LinkEvent> + Send,
463 Handler::Handler: Send,
464{
465 type To = ZResult<LinkEventsListener<Handler::Handler>>;
466}
467
468#[zenoh_macros::unstable]
469impl<Handler> Wait for LinkEventsListenerBuilder<'_, Handler>
470where
471 Handler: IntoHandler<LinkEvent> + Send,
472 Handler::Handler: Send,
473{
474 fn wait(self) -> Self::To {
475 let callback_sync_group = SyncGroup::default();
476 let (callback, handler) = self.handler.into_handler();
477 let state = self.session.declare_transport_links_listener_inner(
478 callback,
479 self.history,
480 self.transport,
481 callback_sync_group.notifier(),
482 )?;
483
484 Ok(LinkEventsListener {
485 inner: LinkEventsListenerInner {
486 session: self.session.clone(),
487 id: state.id,
488 undeclare_on_drop: true,
489 },
490 handler,
491 callback_sync_group,
492 })
493 }
494}
495
496#[zenoh_macros::unstable]
497impl<Handler> IntoFuture for LinkEventsListenerBuilder<'_, Handler>
498where
499 Handler: IntoHandler<LinkEvent> + Send,
500 Handler::Handler: Send,
501{
502 type Output = <Self as Resolvable>::To;
503 type IntoFuture = Ready<<Self as Resolvable>::To>;
504
505 fn into_future(self) -> Self::IntoFuture {
506 std::future::ready(self.wait())
507 }
508}
509
510#[zenoh_macros::unstable]
511impl Resolvable for LinkEventsListenerBuilder<'_, Callback<LinkEvent>, true> {
512 type To = ZResult<()>;
513}
514
515#[zenoh_macros::unstable]
516impl Wait for LinkEventsListenerBuilder<'_, Callback<LinkEvent>, true> {
517 fn wait(self) -> <Self as Resolvable>::To {
518 let state = self.session.declare_transport_links_listener_inner(
519 self.handler,
520 self.history,
521 self.transport,
522 None,
523 )?;
524 drop(state);
528 Ok(())
529 }
530}
531
532#[zenoh_macros::unstable]
533impl IntoFuture for LinkEventsListenerBuilder<'_, Callback<LinkEvent>, true> {
534 type Output = <Self as Resolvable>::To;
535 type IntoFuture = Ready<<Self as Resolvable>::To>;
536
537 fn into_future(self) -> Self::IntoFuture {
538 std::future::ready(self.wait())
539 }
540}