nyquest_interface/register.rs
1//! Backend registration functionality for nyquest.
2//!
3//! This module provides the mechanism for registering a backend implementation
4//! to be used by the nyquest facade.
5//!
6//! Backend implementations should create a single type that satisfies the appropriate
7//! traits based on the enabled features (`AsyncBackend` when the `async` feature is enabled
8//! and/or `BlockingBackend` when the `blocking` feature is enabled).
9
10mod __priv {
11 use cfg_if::cfg_if;
12
13 cfg_if! {
14 if #[cfg(feature = "async")] {
15 /// Trait for backends that may implement async functionality.
16 ///
17 /// Automatically implemented for any type that implements `AnyAsyncBackend`.
18 pub trait MaybeAsync: crate::r#async::AnyAsyncBackend {}
19 impl<B: crate::r#async::AnyAsyncBackend> MaybeAsync for B {}
20 } else {
21 /// Trait for backends when async functionality is not required.
22 pub trait MaybeAsync {}
23 impl<B> MaybeAsync for B {}
24 }
25 }
26
27 cfg_if! {
28 if #[cfg(feature = "blocking")] {
29 /// Trait for backends that may implement blocking functionality.
30 ///
31 /// Automatically implemented for any type that implements `AnyBlockingBackend`.
32 pub trait MaybeBlocking: crate::blocking::AnyBlockingBackend {}
33 impl<B: crate::blocking::AnyBlockingBackend> MaybeBlocking for B {}
34 } else {
35 /// Trait for backends when blocking functionality is not required.
36 pub trait MaybeBlocking {}
37 impl<B> MaybeBlocking for B {}
38 }
39 }
40
41 /// Trait for backends that can be registered with nyquest.
42 ///
43 /// Automatically implemented for types that satisfy the `MaybeAsync`
44 /// and `MaybeBlocking` constraints.
45 pub trait RegisterBackend: MaybeAsync + MaybeBlocking {}
46 impl<B: MaybeAsync + MaybeBlocking> RegisterBackend for B {}
47}
48
49use std::sync::OnceLock;
50
51use __priv::RegisterBackend;
52
53/// Global storage for the registered backend.
54///
55/// This is used internally by nyquest to access the registered backend implementation.
56pub static BACKEND: OnceLock<Box<dyn RegisterBackend + Send + Sync>> = OnceLock::new();
57
58/// Registers a backend implementation for use with nyquest.
59///
60/// This function should be called once at the beginning of a program to set up
61/// the backend that will be used by all nyquest client operations.
62///
63/// Backend developers should create a type that implements:
64/// - [`AsyncBackend`] trait if the `async` feature is enabled
65/// - [`BlockingBackend`] trait if the `blocking` feature is enabled
66///
67/// # Panics
68///
69/// Panics if a backend has already been registered.
70///
71/// [`AsyncBackend`]: crate::async::AsyncBackend
72/// [`BlockingBackend`]: crate::blocking::BlockingBackend
73pub fn register_backend(backend: impl RegisterBackend + Send + Sync + 'static) {
74 if BACKEND.set(Box::new(backend)).is_err() {
75 panic!("Backend already registered");
76 }
77}