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}