1use super::*;
15
16mod zero_copy_transport_sealed {
17 pub trait Sealed {}
18}
19
20#[cfg(feature = "zero-copy-transport")]
21mod zero_copy_uninit_transport_sealed {
22 pub trait Sealed {}
23}
24
25#[cfg(feature = "perf-diagnostics")]
27#[doc(hidden)]
28#[derive(Clone, Copy, Debug, Eq, PartialEq)]
29pub struct UninitStableSendPhases {
30 pub prepare: std::time::Duration,
31 pub loan: std::time::Duration,
32 pub verify: std::time::Duration,
33 pub initialize: std::time::Duration,
34 pub witness: std::time::Duration,
35 pub commit: std::time::Duration,
36 pub total: std::time::Duration,
37 pub residual: std::time::Duration,
38}
39
40#[cfg(feature = "perf-diagnostics")]
41impl UninitStableSendPhases {
42 #[must_use]
43 pub fn accounted(self) -> std::time::Duration {
44 self.prepare + self.loan + self.verify + self.initialize + self.witness + self.commit
45 }
46
47 #[must_use]
49 pub fn calibrate_clock_overhead(iterations: usize) -> std::time::Duration {
50 let mut samples = Vec::with_capacity(iterations.max(1));
51 for _ in 0..iterations.max(1) {
52 let start = std::time::Instant::now();
53 samples.push(start.elapsed());
54 }
55 samples.sort_unstable();
56 *samples
57 .get(samples.len() / 2)
58 .expect("clock calibration always records at least one sample")
59 }
60}
61
62#[cfg(feature = "zero-copy-transport")]
63fn initialize_stable_tx_payload<B, T>(
64 buffer: &mut B,
65 init: impl for<'payload> FnOnce(
66 StablePayloadInitContext<'payload, T>,
67 ) -> Result<InitializedStablePayload<'payload, T>, UWireError>,
68) -> Result<(), UStatus>
69where
70 B: UUninitTxBuffer,
71 T: StablePayloadInit,
72{
73 let payload = buffer.payload_uninit_mut();
74 let loaned = unsafe {
77 LoanedPayloadUninitMut::new_unchecked(payload, PayloadLoanProvenance::OpaqueTransportLoan)
78 };
79 let initializer = T::init_from_uninit_payload(loaned).map_err(UStatus::from)?;
80 let context = StablePayloadInitContext::new(initializer);
81 let _ = init(context).map_err(UStatus::from)?;
82 Ok(())
83}
84
85#[async_trait]
108pub trait UZeroCopyTransportImpl: Send + Sync {
109 type Tx: UTxBuffer + Send;
111
112 type Rx: UZeroCopyRxLease + Send + 'static;
114
115 async fn loan_validated_tx(&self, spec: UTxLoanSpec) -> Result<Self::Tx, UStatus>;
117
118 async fn send_validated_zero_copy(&self, buffer: Self::Tx) -> Result<(), UStatus>;
120
121 async fn receive_validated_zero_copy(
123 &self,
124 _source_filter: &UUri,
125 _sink_filter: Option<&UUri>,
126 ) -> Result<Self::Rx, UStatus> {
127 Err(UStatus::fail_with_code(
128 UCode::Unimplemented,
129 "not implemented",
130 ))
131 }
132
133 async fn register_validated_zero_copy_listener(
135 &self,
136 _source_filter: &UUri,
137 _sink_filter: Option<&UUri>,
138 _listener: Arc<dyn UZeroCopyListener<Self::Rx>>,
139 ) -> Result<(), UStatus> {
140 Err(UStatus::fail_with_code(
141 UCode::Unimplemented,
142 "not implemented",
143 ))
144 }
145
146 async fn unregister_validated_zero_copy_listener(
148 &self,
149 _source_filter: &UUri,
150 _sink_filter: Option<&UUri>,
151 _listener: Arc<dyn UZeroCopyListener<Self::Rx>>,
152 ) -> Result<(), UStatus> {
153 Err(UStatus::fail_with_code(
154 UCode::Unimplemented,
155 "not implemented",
156 ))
157 }
158}
159
160impl<T> zero_copy_transport_sealed::Sealed for T where T: UZeroCopyTransportImpl + ?Sized {}
161
162#[async_trait]
166pub trait UZeroCopyTransport: zero_copy_transport_sealed::Sealed + Send + Sync {
167 type Tx: UTxBuffer + Send;
169
170 type Rx: UZeroCopyRxLease + Send + 'static;
172
173 async fn loan_tx(&self, spec: UTxLoanSpec) -> Result<Self::Tx, UStatus>;
175
176 async fn send_zero_copy(&self, buffer: Self::Tx) -> Result<(), UStatus>;
178
179 async fn receive_zero_copy(
181 &self,
182 source_filter: &UUri,
183 sink_filter: Option<&UUri>,
184 ) -> Result<Self::Rx, UStatus>;
185
186 async fn register_zero_copy_listener(
188 &self,
189 source_filter: &UUri,
190 sink_filter: Option<&UUri>,
191 listener: Arc<dyn UZeroCopyListener<Self::Rx>>,
192 ) -> Result<(), UStatus>;
193
194 async fn unregister_zero_copy_listener(
196 &self,
197 source_filter: &UUri,
198 sink_filter: Option<&UUri>,
199 listener: Arc<dyn UZeroCopyListener<Self::Rx>>,
200 ) -> Result<(), UStatus>;
201}
202
203#[async_trait]
204impl<T> UZeroCopyTransport for T
205where
206 T: UZeroCopyTransportImpl + ?Sized,
207{
208 type Tx = T::Tx;
209 type Rx = T::Rx;
210
211 async fn loan_tx(&self, spec: UTxLoanSpec) -> Result<Self::Tx, UStatus> {
212 UZeroCopyTransportImpl::loan_validated_tx(self, spec).await
213 }
214
215 async fn send_zero_copy(&self, mut buffer: Self::Tx) -> Result<(), UStatus> {
216 validate_tx_buffer_for_transport(&mut buffer)?;
217 UZeroCopyTransportImpl::send_validated_zero_copy(self, buffer).await
218 }
219
220 async fn receive_zero_copy(
221 &self,
222 source_filter: &UUri,
223 sink_filter: Option<&UUri>,
224 ) -> Result<Self::Rx, UStatus> {
225 verify_zero_copy_filter_criteria(source_filter, sink_filter)?;
226 let frame =
227 UZeroCopyTransportImpl::receive_validated_zero_copy(self, source_filter, sink_filter)
228 .await?;
229 validate_frame_view_for_transport(&frame)?;
230 Ok(frame)
231 }
232
233 async fn register_zero_copy_listener(
234 &self,
235 source_filter: &UUri,
236 sink_filter: Option<&UUri>,
237 listener: Arc<dyn UZeroCopyListener<Self::Rx>>,
238 ) -> Result<(), UStatus> {
239 verify_zero_copy_filter_criteria(source_filter, sink_filter)?;
240 let key = zero_copy_listener_registration_key(
241 self,
242 source_filter,
243 sink_filter,
244 zero_copy_listener_pointer(&listener),
245 );
246 let (listener, inserted) = registered_zero_copy_listener(&key, listener);
247 let result = UZeroCopyTransportImpl::register_validated_zero_copy_listener(
248 self,
249 source_filter,
250 sink_filter,
251 listener,
252 )
253 .await;
254 if result.is_err() && inserted {
255 ZERO_COPY_LISTENER_REGISTRY
256 .lock()
257 .expect("zero-copy listener registry lock poisoned")
258 .remove(&key);
259 }
260 result
261 }
262
263 async fn unregister_zero_copy_listener(
264 &self,
265 source_filter: &UUri,
266 sink_filter: Option<&UUri>,
267 listener: Arc<dyn UZeroCopyListener<Self::Rx>>,
268 ) -> Result<(), UStatus> {
269 verify_zero_copy_filter_criteria(source_filter, sink_filter)?;
270 let key = zero_copy_listener_registration_key(
271 self,
272 source_filter,
273 sink_filter,
274 zero_copy_listener_pointer(&listener),
275 );
276 let listener = zero_copy_listener_for_unregister(&key, listener);
277 let result = UZeroCopyTransportImpl::unregister_validated_zero_copy_listener(
278 self,
279 source_filter,
280 sink_filter,
281 listener,
282 )
283 .await;
284 if result.is_ok() {
285 ZERO_COPY_LISTENER_REGISTRY
286 .lock()
287 .expect("zero-copy listener registry lock poisoned")
288 .remove(&key);
289 }
290 result
291 }
292}
293
294#[async_trait]
298pub trait UZeroCopyTransportExt: UZeroCopyTransport {
299 #[cfg(feature = "selected-wire-transport-adapter")]
309 async fn send_loaned_payload<T>(
310 &self,
311 metadata: UFrameMetadata,
312 init: impl for<'payload> FnOnce(&'payload mut T) + Send,
313 ) -> Result<(), UStatus>
314 where
315 Self: UHasWire,
316 Self::Wire: UWirePayload<T>,
317 <Self::Wire as UWirePayload<T>>::Codec: LoanPayload<T> + Send + Sync,
318 {
319 self.send_loaned_payload_as::<<Self::Wire as UWirePayload<T>>::Codec, T>(metadata, init)
320 .await
321 }
322
323 async fn send_loaned_payload_as<C, T>(
336 &self,
337 metadata: UFrameMetadata,
338 init: impl for<'payload> FnOnce(&'payload mut T) + Send,
339 ) -> Result<(), UStatus>
340 where
341 C: PayloadCodec + LoanPayload<T> + Send + Sync,
342 {
343 let metadata = metadata
344 .with_payload_encoding(C::payload_encoding())
345 .map_err(frame_metadata_error)?;
346 let layout = C::loan_layout().map_err(UStatus::from)?;
347 let mut buffer = self
348 .loan_tx(UTxLoanSpec::payload(
349 metadata,
350 layout.len(),
351 layout.align(),
352 )?)
353 .await?;
354 verify_tx_buffer_payload_layout(&mut buffer, layout.len(), layout.align())?;
355 {
356 let payload = C::loan_payload(buffer.payload_mut()).map_err(UStatus::from)?;
357 init(payload);
358 }
359 self.send_zero_copy(buffer).await
360 }
361}
362
363impl<T> UZeroCopyTransportExt for T where T: UZeroCopyTransport + ?Sized {}
364
365#[cfg(feature = "zero-copy-transport")]
369#[async_trait]
370pub trait UZeroCopyUninitTransportExt: UZeroCopyUninitTransport {
371 #[cfg(feature = "selected-wire-transport-adapter")]
382 async fn send_uninit_loaned_payload<T>(
383 &self,
384 metadata: UFrameMetadata,
385 init: impl for<'payload> FnOnce(
386 LoanedUninitPayload<'payload, T>,
387 ) -> Result<LoanedInitPayload<'payload, T>, UWireError>
388 + Send,
389 ) -> Result<(), UStatus>
390 where
391 Self: UHasWire,
392 Self::Wire: UWirePayload<T>,
393 <Self::Wire as UWirePayload<T>>::Codec: LoanUninitPayload<T> + Send + Sync,
394 T: Send,
395 {
396 self.send_uninit_loaned_payload_as::<<Self::Wire as UWirePayload<T>>::Codec, T>(
397 metadata, init,
398 )
399 .await
400 }
401
402 async fn send_uninit_loaned_payload_as<C, T>(
415 &self,
416 metadata: UFrameMetadata,
417 init: impl for<'payload> FnOnce(
418 LoanedUninitPayload<'payload, T>,
419 ) -> Result<LoanedInitPayload<'payload, T>, UWireError>
420 + Send,
421 ) -> Result<(), UStatus>
422 where
423 C: PayloadCodec + LoanUninitPayload<T> + Send + Sync,
424 T: Send,
425 {
426 let metadata = metadata
427 .with_payload_encoding(C::payload_encoding())
428 .map_err(frame_metadata_error)?;
429 let layout = C::loan_uninit_layout().map_err(UStatus::from)?;
430 let mut buffer = self
431 .loan_uninit_tx(UTxLoanSpec::payload(
432 metadata,
433 layout.len(),
434 layout.align(),
435 )?)
436 .await?;
437 verify_uninit_tx_buffer_payload_layout(&mut buffer, layout.len(), layout.align())?;
438 {
439 let payload = buffer.payload_uninit_mut();
440 let loaned = unsafe {
444 LoanedPayloadUninitMut::new_unchecked(
445 payload,
446 PayloadLoanProvenance::OpaqueTransportLoan,
447 )
448 };
449 let loaned = C::loan_uninit_payload(loaned).map_err(UStatus::from)?;
450 let expected = loaned.uninit_ptr();
451 let initialized = init(loaned).map_err(UStatus::from)?;
452 if initialized.initialized_ptr().cast::<MaybeUninit<T>>() != expected {
453 return Err(invalid_argument(
454 "initialized payload proof does not match the TX loan",
455 ));
456 }
457 }
458 let buffer = unsafe { buffer.assume_payload_init() };
461 self.send_zero_copy(buffer).await
462 }
463
464 #[cfg(feature = "selected-wire-transport-adapter")]
476 async fn send_uninit_stable_payload<T>(
477 &self,
478 metadata: UFrameMetadata,
479 init: impl for<'payload> FnOnce(
480 StablePayloadInitContext<'payload, T>,
481 )
482 -> Result<InitializedStablePayload<'payload, T>, UWireError>
483 + Send,
484 ) -> Result<(), UStatus>
485 where
486 Self: UHasWire,
487 Self::Wire: UWirePayload<T, Codec = StableContainerPayload<T>>,
488 T: StablePayloadInit + Send,
489 {
490 self.send_uninit_stable_payload_as::<T>(metadata, init)
491 .await
492 }
493
494 async fn send_uninit_stable_payload_as<T>(
511 &self,
512 metadata: UFrameMetadata,
513 init: impl for<'payload> FnOnce(
514 StablePayloadInitContext<'payload, T>,
515 )
516 -> Result<InitializedStablePayload<'payload, T>, UWireError>
517 + Send,
518 ) -> Result<(), UStatus>
519 where
520 T: StablePayloadInit + Send,
521 {
522 let metadata = metadata
523 .with_payload_encoding(StableContainerPayload::<T>::encoding())
524 .map_err(frame_metadata_error)?;
525 let layout_len = std::mem::size_of::<T>();
526 let layout_align = std::mem::align_of::<T>();
527 let mut buffer = self
528 .loan_uninit_tx(UTxLoanSpec::payload(metadata, layout_len, layout_align)?)
529 .await?;
530 verify_uninit_tx_buffer_payload_layout(&mut buffer, layout_len, layout_align)?;
531 initialize_stable_tx_payload(&mut buffer, init)?;
532 let buffer = unsafe { buffer.assume_payload_init() };
535 self.send_zero_copy(buffer).await
536 }
537
538 #[cfg(feature = "perf-diagnostics")]
540 #[doc(hidden)]
541 async fn send_uninit_stable_payload_as_phased<T>(
542 &self,
543 metadata: UFrameMetadata,
544 init: impl for<'payload> FnOnce(
545 StablePayloadInitContext<'payload, T>,
546 )
547 -> Result<InitializedStablePayload<'payload, T>, UWireError>
548 + Send,
549 ) -> Result<UninitStableSendPhases, UStatus>
550 where
551 T: StablePayloadInit + Send,
552 {
553 let total_start = std::time::Instant::now();
554
555 let phase_start = std::time::Instant::now();
556 let metadata = metadata
557 .with_payload_encoding(StableContainerPayload::<T>::encoding())
558 .map_err(frame_metadata_error)?;
559 let layout_len = std::mem::size_of::<T>();
560 let layout_align = std::mem::align_of::<T>();
561 let spec = UTxLoanSpec::payload(metadata, layout_len, layout_align)?;
562 let prepare = phase_start.elapsed();
563
564 let phase_start = std::time::Instant::now();
565 let mut buffer = self.loan_uninit_tx(spec).await?;
566 let loan = phase_start.elapsed();
567
568 let phase_start = std::time::Instant::now();
569 verify_uninit_tx_buffer_payload_layout(&mut buffer, layout_len, layout_align)?;
570 let verify = phase_start.elapsed();
571
572 let phase_start = std::time::Instant::now();
573 initialize_stable_tx_payload(&mut buffer, init)?;
574 let initialize = phase_start.elapsed();
575
576 let phase_start = std::time::Instant::now();
577 let buffer = unsafe { buffer.assume_payload_init() };
580 let witness = phase_start.elapsed();
581
582 let phase_start = std::time::Instant::now();
583 self.send_zero_copy(buffer).await?;
584 let commit = phase_start.elapsed();
585 let total = total_start.elapsed();
586 let accounted = prepare + loan + verify + initialize + witness + commit;
587
588 Ok(UninitStableSendPhases {
589 prepare,
590 loan,
591 verify,
592 initialize,
593 witness,
594 commit,
595 total,
596 residual: total.saturating_sub(accounted),
597 })
598 }
599
600 #[cfg(all(
602 feature = "perf-diagnostics",
603 feature = "selected-wire-transport-adapter"
604 ))]
605 #[doc(hidden)]
606 async fn send_uninit_stable_payload_phased<T>(
607 &self,
608 metadata: UFrameMetadata,
609 init: impl for<'payload> FnOnce(
610 StablePayloadInitContext<'payload, T>,
611 )
612 -> Result<InitializedStablePayload<'payload, T>, UWireError>
613 + Send,
614 ) -> Result<UninitStableSendPhases, UStatus>
615 where
616 Self: UHasWire,
617 Self::Wire: UWirePayload<T, Codec = StableContainerPayload<T>>,
618 T: StablePayloadInit + Send,
619 {
620 self.send_uninit_stable_payload_as_phased::<T>(metadata, init)
621 .await
622 }
623}
624
625#[cfg(feature = "zero-copy-transport")]
626impl<T> UZeroCopyUninitTransportExt for T where T: UZeroCopyUninitTransport + ?Sized {}
627
628#[async_trait]
632pub trait UZeroCopyUninitTransportImpl: UZeroCopyTransportImpl {
633 type UninitTx: UUninitTxBuffer<Initialized = Self::Tx> + Send;
635
636 async fn loan_validated_uninit_tx(&self, spec: UTxLoanSpec) -> Result<Self::UninitTx, UStatus>;
638}
639
640#[cfg(feature = "zero-copy-transport")]
641impl<T> zero_copy_uninit_transport_sealed::Sealed for T where
642 T: UZeroCopyUninitTransportImpl + ?Sized
643{
644}
645
646#[cfg(feature = "zero-copy-transport")]
650#[async_trait]
651pub trait UZeroCopyUninitTransport:
652 UZeroCopyTransport + zero_copy_uninit_transport_sealed::Sealed
653{
654 type UninitTx: UUninitTxBuffer<Initialized = Self::Tx> + Send;
656
657 async fn loan_uninit_tx(&self, spec: UTxLoanSpec) -> Result<Self::UninitTx, UStatus>;
659}
660
661#[cfg(feature = "zero-copy-transport")]
662#[async_trait]
663impl<T> UZeroCopyUninitTransport for T
664where
665 T: UZeroCopyUninitTransportImpl + ?Sized,
666{
667 type UninitTx = T::UninitTx;
668
669 async fn loan_uninit_tx(&self, spec: UTxLoanSpec) -> Result<Self::UninitTx, UStatus> {
670 UZeroCopyUninitTransportImpl::loan_validated_uninit_tx(self, spec).await
671 }
672}
673
674#[derive(Clone, Debug, Eq, Hash, PartialEq)]
675struct ZeroCopyListenerRegistrationKey {
676 transport: usize,
677 source_filter: UUri,
678 sink_filter: Option<UUri>,
679 listener: usize,
680}
681
682static ZERO_COPY_LISTENER_REGISTRY: LazyLock<
683 Mutex<HashMap<ZeroCopyListenerRegistrationKey, Arc<dyn Any + Send + Sync>>>,
684> = LazyLock::new(|| Mutex::new(HashMap::new()));
685
686struct ValidatingZeroCopyListener<Rx>
687where
688 Rx: UZeroCopyRxLease + Send + 'static,
689{
690 listener: Arc<dyn UZeroCopyListener<Rx>>,
691}
692
693#[async_trait]
694impl<Rx> UZeroCopyListener<Rx> for ValidatingZeroCopyListener<Rx>
695where
696 Rx: UZeroCopyRxLease + Send + 'static,
697{
698 async fn on_receive_zero_copy(&self, frame: Rx) {
699 match validate_frame_view_for_transport(&frame) {
700 Ok(()) => self.listener.on_receive_zero_copy(frame).await,
701 Err(error) => {
702 warn!(%error, "dropping invalid zero-copy frame before listener delivery")
703 }
704 }
705 }
706}
707
708fn registered_zero_copy_listener<Rx>(
709 key: &ZeroCopyListenerRegistrationKey,
710 listener: Arc<dyn UZeroCopyListener<Rx>>,
711) -> (Arc<dyn UZeroCopyListener<Rx>>, bool)
712where
713 Rx: UZeroCopyRxLease + Send + 'static,
714{
715 let mut registry = ZERO_COPY_LISTENER_REGISTRY
716 .lock()
717 .expect("zero-copy listener registry lock poisoned");
718 if let Some(existing) = registry.get(key) {
719 if let Ok(existing) = existing
720 .clone()
721 .downcast::<ValidatingZeroCopyListener<Rx>>()
722 {
723 let existing: Arc<dyn UZeroCopyListener<Rx>> = existing;
724 return (existing, false);
725 }
726 }
727
728 let validating_listener = Arc::new(ValidatingZeroCopyListener { listener });
729 registry.insert(key.clone(), validating_listener.clone());
730 let validating_listener: Arc<dyn UZeroCopyListener<Rx>> = validating_listener;
731 (validating_listener, true)
732}
733
734fn zero_copy_listener_for_unregister<Rx>(
735 key: &ZeroCopyListenerRegistrationKey,
736 fallback: Arc<dyn UZeroCopyListener<Rx>>,
737) -> Arc<dyn UZeroCopyListener<Rx>>
738where
739 Rx: UZeroCopyRxLease + Send + 'static,
740{
741 ZERO_COPY_LISTENER_REGISTRY
742 .lock()
743 .expect("zero-copy listener registry lock poisoned")
744 .get(key)
745 .and_then(|listener| {
746 listener
747 .clone()
748 .downcast::<ValidatingZeroCopyListener<Rx>>()
749 .ok()
750 })
751 .map_or(fallback, |listener| {
752 listener as Arc<dyn UZeroCopyListener<Rx>>
753 })
754}
755
756fn zero_copy_transport_pointer<T: ?Sized>(transport: &T) -> usize {
757 let ptr = transport as *const T;
758 let thin_ptr = ptr as *const ();
759 thin_ptr as usize
760}
761
762fn zero_copy_listener_pointer<Rx>(listener: &Arc<dyn UZeroCopyListener<Rx>>) -> usize
763where
764 Rx: UZeroCopyRxLease + Send + 'static,
765{
766 let ptr = Arc::as_ptr(listener);
767 let thin_ptr = ptr as *const ();
768 thin_ptr as usize
769}
770
771fn zero_copy_listener_registration_key<T: ?Sized>(
772 transport: &T,
773 source_filter: &UUri,
774 sink_filter: Option<&UUri>,
775 listener: usize,
776) -> ZeroCopyListenerRegistrationKey {
777 ZeroCopyListenerRegistrationKey {
778 transport: zero_copy_transport_pointer(transport),
779 source_filter: source_filter.clone(),
780 sink_filter: sink_filter.cloned(),
781 listener,
782 }
783}
784
785fn verify_zero_copy_filter_criteria(
786 source_filter: &UUri,
787 sink_filter: Option<&UUri>,
788) -> Result<(), UStatus> {
789 verify_filter_criteria(source_filter, sink_filter).map_err(|status| *status)
790}