argan_core/response/
impls.rs

1use std::{borrow::Cow, convert::Infallible};
2
3use bytes::Bytes;
4use http::{header, HeaderMap, StatusCode};
5use http_body_util::{Empty, Full};
6
7use super::*;
8
9// --------------------------------------------------------------------------------
10// --------------------------------------------------------------------------------
11
12// --------------------------------------------------
13// StatusCode
14
15impl IntoResponse for StatusCode {
16	#[inline]
17	fn into_response(self) -> Response {
18		let mut response = Response::default();
19		*response.status_mut() = self;
20
21		response
22	}
23}
24
25// --------------------------------------------------
26// Infallible Error
27
28impl IntoResponse for Infallible {
29	#[inline]
30	fn into_response(self) -> Response {
31		Response::default()
32	}
33}
34
35// --------------------------------------------------
36// Unit ()
37
38impl IntoResponse for () {
39	#[inline]
40	fn into_response(self) -> Response {
41		Response::default()
42	}
43}
44
45// --------------------------------------------------
46// Option<T>
47
48impl<T: IntoResponse> IntoResponse for Option<T> {
49	#[inline]
50	fn into_response(self) -> Response {
51		match self {
52			Some(value) => value.into_response(),
53			None => {
54				let mut response = Response::default();
55				*response.status_mut() = StatusCode::NO_CONTENT;
56
57				response
58			}
59		}
60	}
61}
62
63// --------------------------------------------------
64// HeaderMap
65
66impl IntoResponseHeadParts for HeaderMap {
67	#[inline]
68	fn into_response_head(
69		self,
70		mut head: ResponseHeadParts,
71	) -> Result<ResponseHeadParts, BoxedErrorResponse> {
72		head.headers.extend(self);
73
74		Ok(head)
75	}
76}
77
78impl IntoResponse for HeaderMap {
79	fn into_response(self) -> Response {
80		let mut response = ().into_response();
81		*response.headers_mut() = self;
82
83		response
84	}
85}
86
87// --------------------------------------------------
88// Bytes
89
90impl IntoResponse for Bytes {
91	#[inline]
92	fn into_response(self) -> Response {
93		let mut response = Full::from(self).into_response();
94		response.headers_mut().insert(
95			header::CONTENT_TYPE,
96			HeaderValue::from_static(mime::APPLICATION_OCTET_STREAM.as_ref()),
97		);
98
99		response
100	}
101}
102
103// --------------------------------------------------
104// Empty<Bytes>
105
106impl IntoResponse for Empty<Bytes> {
107	#[inline]
108	fn into_response(self) -> Response {
109		Response::new(Body::new(self))
110	}
111}
112
113// --------------------------------------------------
114// Full<Bytes>
115
116impl IntoResponse for Full<Bytes> {
117	#[inline]
118	fn into_response(self) -> Response {
119		Response::new(Body::new(self))
120	}
121}
122
123// --------------------------------------------------
124// &'static str
125
126impl IntoResponse for &'static str {
127	#[inline]
128	fn into_response(self) -> Response {
129		Cow::<'_, str>::Borrowed(self).into_response()
130	}
131}
132
133// --------------------------------------------------
134// String
135
136impl IntoResponse for String {
137	#[inline]
138	fn into_response(self) -> Response {
139		Cow::<'_, str>::Owned(self).into_response()
140	}
141}
142
143// --------------------------------------------------
144// Cow<'static, str>
145
146impl IntoResponse for Cow<'static, str> {
147	#[inline]
148	fn into_response(self) -> Response {
149		let mut response = Full::from(self).into_response();
150		response.headers_mut().insert(
151			header::CONTENT_TYPE,
152			HeaderValue::from_static(mime::TEXT_PLAIN_UTF_8.as_ref()),
153		);
154
155		response
156	}
157}
158
159// --------------------------------------------------
160// &'static [u8]
161
162impl IntoResponse for &'static [u8] {
163	#[inline]
164	fn into_response(self) -> Response {
165		Cow::<'_, [u8]>::Borrowed(self).into_response()
166	}
167}
168
169// --------------------------------------------------
170// Vec<u8>
171
172impl IntoResponse for Vec<u8> {
173	#[inline]
174	fn into_response(self) -> Response {
175		Cow::<'_, [u8]>::Owned(self).into_response()
176	}
177}
178
179// --------------------------------------------------
180// Cow<'static, [u8]>
181
182impl IntoResponse for Cow<'static, [u8]> {
183	#[inline]
184	fn into_response(self) -> Response {
185		let mut response = Full::from(self).into_response();
186		response.headers_mut().insert(
187			header::CONTENT_TYPE,
188			HeaderValue::from_static(mime::APPLICATION_OCTET_STREAM.as_ref()),
189		);
190
191		response
192	}
193}
194
195// --------------------------------------------------
196// Body
197
198impl IntoResponse for Body {
199	#[inline]
200	fn into_response(self) -> Response {
201		Response::new(self)
202	}
203}
204
205// --------------------------------------------------
206// Array of header (name, value) tuples
207
208impl<N, V, const C: usize> IntoResponseHeadParts for [(N, V); C]
209where
210	N: TryInto<HeaderName>,
211	N::Error: crate::StdError + Send + Sync + 'static,
212	V: TryInto<HeaderValue>,
213	V::Error: crate::StdError + Send + Sync + 'static,
214{
215	fn into_response_head(
216		self,
217		mut head: ResponseHeadParts,
218	) -> Result<ResponseHeadParts, BoxedErrorResponse> {
219		for (key, value) in self {
220			let header_name = TryInto::<HeaderName>::try_into(key)
221				.map_err(HeaderError::<N::Error, V::Error>::from_name_error)?;
222
223			let header_value = TryInto::<HeaderValue>::try_into(value)
224				.map_err(HeaderError::<N::Error, V::Error>::from_value_error)?;
225
226			head.headers.insert(header_name, header_value);
227		}
228
229		Ok(head)
230	}
231}
232
233impl<N, V, const C: usize> IntoResponseResult for [(N, V); C]
234where
235	N: TryInto<HeaderName>,
236	N::Error: crate::StdError + Send + Sync + 'static,
237	V: TryInto<HeaderValue>,
238	V::Error: crate::StdError + Send + Sync + 'static,
239{
240	fn into_response_result(self) -> Result<Response, BoxedErrorResponse> {
241		let (head, body) = Response::default().into_parts();
242
243		self
244			.into_response_head(head)
245			.map(|head| Response::from_parts(head, body))
246	}
247}
248
249#[derive(Debug, crate::ImplError)]
250enum HeaderError<NE, VE> {
251	#[error(transparent)]
252	InvalidName(NE),
253	#[error(transparent)]
254	InvalidValue(VE),
255}
256
257impl<NE, VE> HeaderError<NE, VE> {
258	pub(crate) fn from_name_error(name_error: NE) -> Self {
259		Self::InvalidName(name_error)
260	}
261
262	pub(crate) fn from_value_error(value_error: VE) -> Self {
263		Self::InvalidValue(value_error)
264	}
265}
266
267impl<NE, VE> IntoResponse for HeaderError<NE, VE> {
268	fn into_response(self) -> Response {
269		StatusCode::INTERNAL_SERVER_ERROR.into_response()
270	}
271}
272
273// --------------------------------------------------
274// Tuples
275
276macro_rules! impl_into_response_for_tuples {
277	($t1:ident, $(($($t:ident),*),)? $tl:ident) => {
278		#[allow(non_snake_case)]
279		impl<$t1, $($($t,)*)? $tl> IntoResponseHeadParts for ($t1, $($($t,)*)? $tl)
280		where
281			$t1: IntoResponseHeadParts,
282			$($($t: IntoResponseHeadParts,)*)?
283			$tl: IntoResponseHeadParts,
284		{
285			fn into_response_head(
286				self,
287				mut head: ResponseHeadParts,
288			) -> Result<ResponseHeadParts, BoxedErrorResponse> {
289				let ($t1, $($($t,)*)? $tl) = self;
290
291				head = $t1.into_response_head(head)?;
292
293				$($(head = $t.into_response_head(head)?;)*)?
294
295				head = $tl.into_response_head(head)?;
296
297				Ok(head)
298			}
299		}
300
301		#[allow(non_snake_case)]
302		impl<$($($t,)*)? $tl> IntoResponseResult for (StatusCode, $($($t,)*)? $tl)
303		where
304			$($($t: IntoResponseHeadParts,)*)?
305			$tl: IntoResponseResult,
306		{
307			fn into_response_result(self) -> Result<Response, BoxedErrorResponse> {
308				let (status_code, $($($t,)*)? $tl) = self;
309
310				let (head, body) = $tl.into_response_result()?.into_parts();
311
312				$($(
313					let head = $t.into_response_head(head)?;
314				)*)?
315
316				let mut response = Response::from_parts(head, body);
317				*response.status_mut() = status_code;
318
319				Ok(response)
320			}
321		}
322
323		#[allow(non_snake_case)]
324		impl<$t1, $($($t,)*)? $tl> IntoResponseResult for ($t1, $($($t,)*)? $tl)
325		where
326			$t1: IntoResponseHeadParts,
327			$($($t: IntoResponseHeadParts,)*)?
328			$tl: IntoResponseResult,
329		{
330			fn into_response_result(self) -> Result<Response, BoxedErrorResponse> {
331				let ($t1, $($($t,)*)? $tl) = self;
332
333				let (head, body) = $tl.into_response_result()?.into_parts();
334
335				let head = $t1.into_response_head(head)?;
336
337				$($(
338					let head = $t.into_response_head(head)?;
339				)*)?
340
341				Ok(Response::from_parts(head, body))
342			}
343		}
344	};
345}
346
347call_for_tuples!(impl_into_response_for_tuples!);
348
349// --------------------------------------------------------------------------------