connectrpc_tauri/
deferred.rs1use std::{
4 fmt,
5 sync::{Arc, OnceLock},
6};
7
8use bytes::Bytes;
9use connectrpc::{
10 CodecFormat, Dispatcher, MethodDescriptor, Payload, RequestContext,
11 dispatcher::{
12 RequestStream, StreamingResult, UnaryResult, unimplemented_streaming, unimplemented_unary,
13 },
14};
15
16pub struct DeferredDispatcher<D> {
39 inner: Arc<OnceLock<D>>,
41}
42
43impl<D> DeferredDispatcher<D> {
44 #[must_use = "retain and initialize the dispatcher before requests arrive"]
46 pub fn new() -> Self {
47 Self {
48 inner: Arc::new(OnceLock::new()),
49 }
50 }
51
52 pub fn set(&self, dispatcher: D) -> Result<(), D> {
58 self.inner.set(dispatcher)
59 }
60
61 #[inline]
63 #[must_use = "the identity comparison is returned without modifying either dispatcher"]
64 pub fn same_dispatcher(&self, other: &Self) -> bool {
65 Arc::ptr_eq(&self.inner, &other.inner)
66 }
67}
68
69impl<D> Clone for DeferredDispatcher<D> {
70 #[inline]
71 fn clone(&self) -> Self {
72 Self {
73 inner: Arc::clone(&self.inner),
74 }
75 }
76}
77
78impl<D> Default for DeferredDispatcher<D> {
79 fn default() -> Self {
80 Self::new()
81 }
82}
83
84impl<D> fmt::Debug for DeferredDispatcher<D> {
85 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
86 formatter
87 .debug_struct("DeferredDispatcher")
88 .field("is_initialized", &self.inner.get().is_some())
89 .finish()
90 }
91}
92
93impl<D: Dispatcher> Dispatcher for DeferredDispatcher<D> {
94 #[inline]
95 fn lookup(&self, path: &str) -> Option<MethodDescriptor> {
96 self.inner.get()?.lookup(path)
97 }
98
99 #[inline]
100 fn call_unary(
101 &self,
102 path: &str,
103 context: RequestContext,
104 request: Payload,
105 format: CodecFormat,
106 ) -> UnaryResult {
107 match self.inner.get() {
108 Some(dispatcher) => dispatcher.call_unary(path, context, request, format),
109 None => unimplemented_unary(path),
110 }
111 }
112
113 #[inline]
114 fn call_server_streaming(
115 &self,
116 path: &str,
117 context: RequestContext,
118 request: Bytes,
119 format: CodecFormat,
120 ) -> StreamingResult {
121 match self.inner.get() {
122 Some(dispatcher) => dispatcher.call_server_streaming(path, context, request, format),
123 None => unimplemented_streaming(path),
124 }
125 }
126
127 #[inline]
128 fn call_client_streaming(
129 &self,
130 path: &str,
131 context: RequestContext,
132 requests: RequestStream,
133 format: CodecFormat,
134 ) -> UnaryResult {
135 match self.inner.get() {
136 Some(dispatcher) => dispatcher.call_client_streaming(path, context, requests, format),
137 None => unimplemented_unary(path),
138 }
139 }
140
141 #[inline]
142 fn call_bidi_streaming(
143 &self,
144 path: &str,
145 context: RequestContext,
146 requests: RequestStream,
147 format: CodecFormat,
148 ) -> StreamingResult {
149 match self.inner.get() {
150 Some(dispatcher) => dispatcher.call_bidi_streaming(path, context, requests, format),
151 None => unimplemented_streaming(path),
152 }
153 }
154}