1use std::{
17 any::Any,
18 collections::HashMap,
19 io::Cursor,
20 mem::MaybeUninit,
21 ops::Deref,
22 sync::{Arc, LazyLock, Mutex},
23};
24
25use async_trait::async_trait;
26#[cfg(any(test, feature = "test-util"))]
27use std::collections::VecDeque;
28use tracing::warn;
29
30#[cfg(feature = "zero-copy-transport")]
31use crate::payload::{
32 loan::{LoanUninitPayload, LoanedInitPayload, LoanedUninitPayload},
33 stable::{InitializedStablePayload, StablePayloadInit, StablePayloadInitContext},
34};
35#[cfg(feature = "selected-wire-transport-adapter")]
36use crate::wire::UWirePayload;
37#[cfg(feature = "selected-wire-transport-adapter")]
38use crate::wire_transport::UHasWire;
39use crate::{
40 payload::{
41 codec::PayloadCodec,
42 loan::{BorrowPayload, LoanPayload},
43 stable::{StableContainerPayload, StablePayload},
44 UWireError,
45 },
46 utransport::verify_filter_criteria,
47 UCode, UFrameMetadata, UStatus, UUri,
48};
49
50mod rx;
51mod tests;
52mod transport;
53mod tx;
54
55pub use rx::*;
56#[cfg(feature = "test-util")]
57pub use tests::InMemoryZeroCopyTransport;
58pub use tests::{UVecRxLease, UVecTxBuffer, UVecUninitTxBuffer};
59pub use transport::UZeroCopyUninitTransportImpl;
60#[cfg(feature = "perf-diagnostics")]
61#[doc(hidden)]
62pub use transport::UninitStableSendPhases;
63pub use transport::{UZeroCopyTransport, UZeroCopyTransportExt, UZeroCopyTransportImpl};
64#[cfg(feature = "zero-copy-transport")]
65pub use transport::{UZeroCopyUninitTransport, UZeroCopyUninitTransportExt};
66pub use tx::*;
67
68#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
70pub enum PayloadLoanProvenance {
71 OpaqueTransportLoan,
73}
74
75#[derive(Clone, Copy, Debug, Eq, PartialEq)]
77pub struct LoanedPayload<'a> {
78 bytes: &'a [u8],
79 provenance: PayloadLoanProvenance,
80}
81
82impl<'a> LoanedPayload<'a> {
83 #[must_use]
91 pub unsafe fn new_unchecked(bytes: &'a [u8], provenance: PayloadLoanProvenance) -> Self {
92 Self { bytes, provenance }
93 }
94
95 #[must_use]
96 pub fn provenance(self) -> PayloadLoanProvenance {
98 self.provenance
99 }
100
101 #[must_use]
102 pub fn as_bytes(self) -> &'a [u8] {
104 self.bytes
105 }
106
107 #[must_use]
108 pub fn len(self) -> usize {
110 self.bytes.len()
111 }
112
113 #[must_use]
114 pub fn is_empty(self) -> bool {
116 self.bytes.is_empty()
117 }
118}
119
120impl AsRef<[u8]> for LoanedPayload<'_> {
121 fn as_ref(&self) -> &[u8] {
122 self.bytes
123 }
124}
125
126impl Deref for LoanedPayload<'_> {
127 type Target = [u8];
128
129 fn deref(&self) -> &Self::Target {
130 self.bytes
131 }
132}
133
134fn validate_tx_loan_spec(spec: &UTxLoanSpec) -> Result<(), UStatus> {
135 validate_metadata(spec.metadata())?;
136 validate_payload_presence(
137 spec.has_payload(),
138 spec.metadata().payload_encoding().is_some(),
139 "TX loan spec",
140 )?;
141 validate_payload_layout(spec.payload_len(), spec.payload_alignment())
142}
143
144pub(crate) use crate::frame::view::{
145 frame_metadata_error, validate_metadata, validate_payload_presence,
146};
147
148fn validate_payload_layout(payload_len: usize, alignment: usize) -> Result<(), UStatus> {
149 PayloadAlignment::new(alignment)?;
150 let _ = payload_len;
151 Ok(())
152}
153
154fn verify_payload_slice_layout(
155 payload: &[u8],
156 payload_len: usize,
157 alignment: usize,
158) -> Result<(), UStatus> {
159 if payload.len() != payload_len {
160 return Err(internal_zero_copy_error(format!(
161 "transport returned TX payload length {} but {payload_len} was requested",
162 payload.len()
163 )));
164 }
165 if !payload.is_empty() && !(payload.as_ptr() as usize).is_multiple_of(alignment) {
166 return Err(internal_zero_copy_error(format!(
167 "transport returned TX payload alignment {} but {alignment} was requested",
168 payload.as_ptr() as usize
169 )));
170 }
171 Ok(())
172}
173
174fn aligned_offset(address: usize, alignment: usize) -> usize {
175 if alignment == 1 {
176 0
177 } else {
178 (alignment - (address % alignment)) % alignment
179 }
180}
181
182fn invalid_argument(message: impl Into<String>) -> UStatus {
183 UStatus::fail_with_code(UCode::InvalidArgument, message.into())
184}
185
186fn internal_zero_copy_error(message: impl Into<String>) -> UStatus {
187 UStatus::fail_with_code(UCode::Internal, message.into())
188}