1mod asynchronous;
4mod content_type;
5mod endpoint;
6mod header;
7mod request_target;
8
9pub use asynchronous::AsyncTransport;
10pub use content_type::{
11 ContentType, ContentTypeError, MAX_CONTENT_TYPE_BYTES, MediaType, ResponseContentType,
12};
13pub use endpoint::{
14 AcknowledgedCustomEndpoint, BoundTransport, CustomEndpointAcknowledgement, EndpointIdentity,
15 EndpointIdentityError, EndpointPolicy, EndpointPolicyError, EndpointPolicyKind, EndpointScheme,
16 MAX_ENDPOINT_BASE_PATH_BYTES, MAX_ENDPOINT_HOST_BYTES, MAX_ENDPOINT_REGION_BYTES,
17 MAX_OFFICIAL_ENDPOINTS, RegionEndpoint,
18};
19pub use header::{
20 HeaderError, HeaderName, HeaderSensitivity, HeaderValue, MAX_HEADER_NAME_BYTES,
21 MAX_HEADER_VALUE_BYTES, MAX_REQUEST_HEADER_BYTES, MAX_REQUEST_HEADERS,
22 MAX_RESPONSE_HEADER_BYTES, MAX_RESPONSE_HEADERS, RequestHeader, RequestHeaders, ResponseHeader,
23 ResponseHeaders,
24};
25pub use request_target::{
26 CanonicalQuery, FormQuery, MAX_REQUEST_TARGET_BYTES, QueryPair, QueryPairs, RequestPath,
27 RequestPathError, RequestQuery, RequestTarget, RequestTargetError, StructuredQueryError,
28};
29
30use core::fmt;
31
32use crate::Method;
33use crate::rate_limit::RateLimit;
34
35pub trait ResponseStorageSanitizer {
44 fn sanitize_response_storage(&self, response_storage: &mut [u8]);
46}
47
48#[derive(Clone, Copy)]
50pub struct TransportRequest<'a> {
51 method: Method,
52 target: RequestTarget<'a>,
53 body: &'a [u8],
54 headers: RequestHeaders<'a>,
55}
56
57impl<'a> TransportRequest<'a> {
58 #[must_use]
60 pub const fn new(method: Method, target: RequestTarget<'a>) -> Self {
61 Self {
62 method,
63 target,
64 body: &[],
65 headers: RequestHeaders::EMPTY,
66 }
67 }
68
69 #[must_use]
71 pub const fn with_body(mut self, body: &'a [u8]) -> Self {
72 self.body = body;
73 self
74 }
75
76 #[must_use]
78 pub const fn with_headers(mut self, headers: RequestHeaders<'a>) -> Self {
79 self.headers = headers;
80 self
81 }
82
83 #[must_use]
85 pub const fn method(self) -> Method {
86 self.method
87 }
88
89 #[must_use]
91 pub const fn target(self) -> RequestTarget<'a> {
92 self.target
93 }
94
95 #[must_use]
97 pub const fn body(self) -> &'a [u8] {
98 self.body
99 }
100
101 #[must_use]
103 pub const fn headers(self) -> RequestHeaders<'a> {
104 self.headers
105 }
106}
107
108impl fmt::Debug for TransportRequest<'_> {
109 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
110 formatter
111 .debug_struct("TransportRequest")
112 .field("method", &self.method)
113 .field("target", &self.target)
114 .field("body", &"[redacted]")
115 .field("headers", &self.headers)
116 .finish()
117 }
118}
119
120#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
122pub struct StatusCode(u16);
123
124impl StatusCode {
125 pub const OK: Self = Self(200);
127 pub const CREATED: Self = Self(201);
129 pub const ACCEPTED: Self = Self(202);
131 pub const NO_CONTENT: Self = Self(204);
133 pub const TOO_MANY_REQUESTS: Self = Self(429);
135
136 #[must_use]
138 pub const fn new(value: u16) -> Option<Self> {
139 if value < 100 || value > 599 {
140 return None;
141 }
142 Some(Self(value))
143 }
144
145 #[must_use]
147 pub const fn get(self) -> u16 {
148 self.0
149 }
150
151 #[must_use]
153 pub const fn is_success(self) -> bool {
154 self.0 >= 200 && self.0 <= 299
155 }
156
157 #[must_use]
159 pub const fn is_error(self) -> bool {
160 self.0 >= 400
161 }
162}
163
164#[derive(Clone, Copy)]
176pub struct TransportResponse<'buffer> {
177 status: StatusCode,
178 body: &'buffer [u8],
179 content_type: Option<ResponseContentType>,
180 rate_limit: Option<RateLimit>,
181 headers: ResponseHeaders,
182}
183
184impl<'buffer> TransportResponse<'buffer> {
185 #[must_use]
187 pub const fn new(status: StatusCode, body: &'buffer [u8]) -> Self {
188 Self {
189 status,
190 body,
191 content_type: None,
192 rate_limit: None,
193 headers: ResponseHeaders::new(),
194 }
195 }
196
197 #[must_use]
199 pub const fn with_content_type(mut self, content_type: ResponseContentType) -> Self {
200 self.content_type = Some(content_type);
201 self
202 }
203
204 #[must_use]
206 pub const fn with_rate_limit(mut self, rate_limit: RateLimit) -> Self {
207 self.rate_limit = Some(rate_limit);
208 self
209 }
210
211 #[must_use]
213 pub const fn with_headers(mut self, headers: ResponseHeaders) -> Self {
214 self.headers = headers;
215 self
216 }
217
218 #[must_use]
220 pub const fn status(&self) -> StatusCode {
221 self.status
222 }
223
224 #[must_use]
226 pub const fn body(&self) -> &'buffer [u8] {
227 self.body
228 }
229
230 #[must_use]
232 pub const fn content_type(&self) -> Option<ResponseContentType> {
233 self.content_type
234 }
235
236 #[must_use]
238 pub const fn rate_limit(&self) -> Option<RateLimit> {
239 self.rate_limit
240 }
241
242 #[must_use]
244 pub const fn headers(&self) -> &ResponseHeaders {
245 &self.headers
246 }
247}
248
249impl fmt::Debug for TransportResponse<'_> {
250 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
251 formatter
252 .debug_struct("TransportResponse")
253 .field("status", &self.status)
254 .field("body_len", &self.body.len())
255 .field("body", &"[redacted]")
256 .field("content_type", &self.content_type)
257 .field("rate_limit", &self.rate_limit)
258 .field("headers", &self.headers)
259 .finish()
260 }
261}
262
263pub trait BlockingTransport {
272 type Error;
274
275 fn send<'buffer>(
277 &self,
278 request: TransportRequest<'_>,
279 response_body: &'buffer mut [u8],
280 ) -> Result<TransportResponse<'buffer>, Self::Error>;
281}
282
283#[cfg(test)]
284mod tests;