1mod asynchronous;
4mod cleanup;
5mod content_type;
6mod delivery;
7mod endpoint;
8mod header;
9mod raw;
10mod request_target;
11mod response;
12mod retained;
13mod streaming;
14mod workspace;
15
16pub use asynchronous::{
17 ASYNC_CANCELLATION_DELIVERY_PHASE, AsyncExecutionError, AsyncTransport, LocalAsyncTransport,
18 drive_async, drive_local,
19};
20pub use cleanup::ResponseStorageSanitizer;
21pub use content_type::{
22 ContentType, ContentTypeError, MAX_CONTENT_TYPE_BYTES, MediaType, ResponseContentType,
23};
24pub use delivery::{DeliveryPhase, TransportFailure};
25pub(crate) use endpoint::CanonicalHost;
26pub use endpoint::{
27 AcknowledgedCustomEndpoint, BoundTransport, CustomEndpointAcknowledgement, EndpointIdentity,
28 EndpointIdentityError, EndpointPolicy, EndpointPolicyError, EndpointPolicyKind, EndpointScheme,
29 MAX_ENDPOINT_BASE_PATH_BYTES, MAX_ENDPOINT_HOST_BYTES, MAX_ENDPOINT_REGION_BYTES,
30 MAX_OFFICIAL_ENDPOINTS, RegionEndpoint,
31};
32pub use header::{
33 HeaderError, HeaderName, HeaderSensitivity, HeaderValue, MAX_HEADER_NAME_BYTES,
34 MAX_HEADER_VALUE_BYTES, MAX_REQUEST_HEADER_BYTES, MAX_REQUEST_HEADERS,
35 MAX_RESPONSE_HEADER_BYTES, MAX_RESPONSE_HEADERS, RequestHeader, RequestHeaders, ResponseHeader,
36 ResponseHeaders,
37};
38pub use raw::{
39 AsyncRawHttpExecutor, BlockingRawHttpExecutor, InformationalResponseError,
40 InformationalResponseTracker, LocalAsyncRawHttpExecutor, MAX_INFORMATIONAL_RESPONSES,
41 MAX_RAW_RESPONSE_BODY_BYTES, MAX_RESPONSE_CHUNKS, RawResponsePolicy, RawResponsePolicyError,
42 ResponseMediaPolicy, TrailerPolicy, drive_async_raw, drive_local_raw,
43};
44pub use request_target::{
45 CanonicalQuery, FormQuery, MAX_REQUEST_TARGET_BYTES, ProviderLinkQuery, QueryPair, QueryPairs,
46 RequestPath, RequestPathError, RequestQuery, RequestTarget, RequestTargetError,
47 StructuredQueryError,
48};
49pub use response::{
50 AsyncResponseStaging, ResponseAttempt, ResponseBuffer, ResponseCompletion, ResponseMetadata,
51 ResponseWriter, ResponseWriterError, TransportResponse,
52};
53pub use retained::{MAX_REQUEST_ID_BYTES, RetainedMetadataError, RetainedResponseMetadata};
54pub use streaming::{
55 AsyncStreamSink, AsyncStreamSource, BlockingStreamSink, BlockingStreamSource,
56 LocalAsyncStreamSink, LocalAsyncStreamSource, MAX_CONSECUTIVE_ZERO_PROGRESS, MAX_STREAM_BYTES,
57 MAX_STREAM_CHUNK_BYTES, MAX_STREAM_CHUNKS, MAX_STREAM_OBSERVATIONS, MAX_STREAM_SOURCE_ID_BYTES,
58 StreamAttempt, StreamCompletion, StreamExecutionError, StreamFraming, StreamKind, StreamLimits,
59 StreamLimitsError, StreamOutcome, StreamPartialState, StreamPolicy, StreamPolicyError,
60 StreamProgress, StreamProgressError, StreamRead, StreamReplayError, StreamReplayability,
61 StreamSinkMode, StreamSourceId, StreamSourceIdError, StreamState, drive_async_stream,
62 drive_blocking_stream, drive_local_stream, validate_stream_replay,
63};
64pub use workspace::{
65 RESPONSE_CURSOR_SCRATCH_BYTES, RESPONSE_DECODER_SCRATCH_BYTES,
66 RESPONSE_PROVIDER_LINK_SCRATCH_BYTES, ResponseDecodeWorkspace,
67};
68
69use core::fmt;
70
71use crate::Method;
72
73#[derive(Clone, Copy)]
75pub struct TransportRequest<'a> {
76 method: Method,
77 target: RequestTarget<'a>,
78 body: &'a [u8],
79 headers: RequestHeaders<'a>,
80}
81
82impl<'a> TransportRequest<'a> {
83 #[must_use]
85 pub const fn new(method: Method, target: RequestTarget<'a>) -> Self {
86 Self {
87 method,
88 target,
89 body: &[],
90 headers: RequestHeaders::EMPTY,
91 }
92 }
93
94 #[must_use]
96 pub const fn with_body(mut self, body: &'a [u8]) -> Self {
97 self.body = body;
98 self
99 }
100
101 #[must_use]
103 pub const fn with_headers(mut self, headers: RequestHeaders<'a>) -> Self {
104 self.headers = headers;
105 self
106 }
107
108 #[must_use]
110 pub const fn method(self) -> Method {
111 self.method
112 }
113
114 #[must_use]
116 pub const fn target(self) -> RequestTarget<'a> {
117 self.target
118 }
119
120 #[must_use]
122 pub const fn body(self) -> &'a [u8] {
123 self.body
124 }
125
126 #[must_use]
128 pub const fn headers(self) -> RequestHeaders<'a> {
129 self.headers
130 }
131}
132
133impl fmt::Debug for TransportRequest<'_> {
134 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
135 formatter
136 .debug_struct("TransportRequest")
137 .field("method", &self.method)
138 .field("target", &self.target)
139 .field("body", &"[redacted]")
140 .field("headers", &self.headers)
141 .finish()
142 }
143}
144
145#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
147pub struct StatusCode(u16);
148
149impl StatusCode {
150 pub const OK: Self = Self(200);
152 pub const CREATED: Self = Self(201);
154 pub const ACCEPTED: Self = Self(202);
156 pub const NO_CONTENT: Self = Self(204);
158 pub const TOO_MANY_REQUESTS: Self = Self(429);
160
161 #[must_use]
163 pub const fn new(value: u16) -> Option<Self> {
164 if value < 100 || value > 599 {
165 return None;
166 }
167 Some(Self(value))
168 }
169
170 #[must_use]
172 pub const fn get(self) -> u16 {
173 self.0
174 }
175
176 #[must_use]
178 pub const fn is_success(self) -> bool {
179 self.0 >= 200 && self.0 <= 299
180 }
181
182 #[must_use]
184 pub const fn is_error(self) -> bool {
185 self.0 >= 400
186 }
187}
188
189pub trait BlockingTransport {
198 type Error;
200
201 fn send(
206 &self,
207 request: TransportRequest<'_>,
208 response: &mut ResponseWriter<'_>,
209 ) -> Result<(), Self::Error>;
210}
211
212#[cfg(test)]
213mod local_async_tests;
214#[cfg(test)]
215mod tests;