1use std::convert::Infallible;
4
5use axum_core::response::{IntoResponseParts, ResponseParts};
6use http::HeaderValue;
7
8use crate::{HxError, headers};
9
10mod location;
11pub use location::*;
12mod trigger;
13pub use trigger::*;
14mod vary;
15pub use vary::*;
16
17const HX_SWAP_INNER_HTML: &str = "innerHTML";
18const HX_SWAP_OUTER_HTML: &str = "outerHTML";
19const HX_SWAP_BEFORE_BEGIN: &str = "beforebegin";
20const HX_SWAP_AFTER_BEGIN: &str = "afterbegin";
21const HX_SWAP_BEFORE_END: &str = "beforeend";
22const HX_SWAP_AFTER_END: &str = "afterend";
23const HX_SWAP_DELETE: &str = "delete";
24const HX_SWAP_NONE: &str = "none";
25
26#[derive(Debug, Clone)]
35pub struct HxPushUrl(pub String);
36
37impl IntoResponseParts for HxPushUrl {
38 type Error = HxError;
39
40 fn into_response_parts(self, mut res: ResponseParts) -> Result<ResponseParts, Self::Error> {
41 res.headers_mut().insert(
42 headers::HX_PUSH_URL,
43 HeaderValue::from_maybe_shared(self.0)?,
44 );
45
46 Ok(res)
47 }
48}
49
50impl<'a> From<&'a str> for HxPushUrl {
51 fn from(value: &'a str) -> Self {
52 Self(value.to_string())
53 }
54}
55
56#[derive(Debug, Clone)]
63pub struct HxRedirect(pub String);
64
65impl IntoResponseParts for HxRedirect {
66 type Error = HxError;
67
68 fn into_response_parts(self, mut res: ResponseParts) -> Result<ResponseParts, Self::Error> {
69 res.headers_mut().insert(
70 headers::HX_REDIRECT,
71 HeaderValue::from_maybe_shared(self.0)?,
72 );
73
74 Ok(res)
75 }
76}
77
78impl<'a> From<&'a str> for HxRedirect {
79 fn from(value: &'a str) -> Self {
80 Self(value.to_string())
81 }
82}
83
84#[derive(Debug, Copy, Clone)]
90pub struct HxRefresh(pub bool);
91
92impl From<bool> for HxRefresh {
93 fn from(value: bool) -> Self {
94 Self(value)
95 }
96}
97
98impl IntoResponseParts for HxRefresh {
99 type Error = Infallible;
100
101 fn into_response_parts(self, mut res: ResponseParts) -> Result<ResponseParts, Self::Error> {
102 res.headers_mut().insert(
103 headers::HX_REFRESH,
104 if self.0 {
105 HeaderValue::from_static("true")
106 } else {
107 HeaderValue::from_static("false")
108 },
109 );
110
111 Ok(res)
112 }
113}
114
115#[derive(Debug, Clone)]
124pub struct HxReplaceUrl(pub String);
125
126impl IntoResponseParts for HxReplaceUrl {
127 type Error = HxError;
128
129 fn into_response_parts(self, mut res: ResponseParts) -> Result<ResponseParts, Self::Error> {
130 res.headers_mut().insert(
131 headers::HX_REPLACE_URL,
132 HeaderValue::from_maybe_shared(self.0)?,
133 );
134
135 Ok(res)
136 }
137}
138
139impl<'a> From<&'a str> for HxReplaceUrl {
140 fn from(value: &'a str) -> Self {
141 Self(value.to_string())
142 }
143}
144
145#[derive(Debug, Copy, Clone)]
151pub struct HxReswap(pub SwapOption);
152
153impl IntoResponseParts for HxReswap {
154 type Error = Infallible;
155
156 fn into_response_parts(self, mut res: ResponseParts) -> Result<ResponseParts, Self::Error> {
157 res.headers_mut().insert(headers::HX_RESWAP, self.0.into());
158
159 Ok(res)
160 }
161}
162
163impl From<SwapOption> for HxReswap {
164 fn from(value: SwapOption) -> Self {
165 Self(value)
166 }
167}
168
169#[derive(Debug, Clone)]
177pub struct HxRetarget(pub String);
178
179impl IntoResponseParts for HxRetarget {
180 type Error = HxError;
181
182 fn into_response_parts(self, mut res: ResponseParts) -> Result<ResponseParts, Self::Error> {
183 res.headers_mut().insert(
184 headers::HX_RETARGET,
185 HeaderValue::from_maybe_shared(self.0)?,
186 );
187
188 Ok(res)
189 }
190}
191
192impl<T: Into<String>> From<T> for HxRetarget {
193 fn from(value: T) -> Self {
194 Self(value.into())
195 }
196}
197
198#[derive(Debug, Clone)]
206pub struct HxReselect(pub String);
207
208impl IntoResponseParts for HxReselect {
209 type Error = HxError;
210
211 fn into_response_parts(self, mut res: ResponseParts) -> Result<ResponseParts, Self::Error> {
212 res.headers_mut().insert(
213 headers::HX_RESELECT,
214 HeaderValue::from_maybe_shared(self.0)?,
215 );
216
217 Ok(res)
218 }
219}
220
221impl<T: Into<String>> From<T> for HxReselect {
222 fn from(value: T) -> Self {
223 Self(value.into())
224 }
225}
226
227#[derive(Debug, Copy, Clone)]
230pub enum SwapOption {
231 InnerHtml,
233 OuterHtml,
235 BeforeBegin,
237 AfterBegin,
239 BeforeEnd,
241 AfterEnd,
243 Delete,
245 None,
248}
249
250#[cfg(feature = "serde")]
253impl ::serde::Serialize for SwapOption {
254 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
255 where
256 S: ::serde::Serializer,
257 {
258 const UNIT_NAME: &str = "SwapOption";
259 match self {
260 Self::InnerHtml => serializer.serialize_unit_variant(UNIT_NAME, 0, HX_SWAP_INNER_HTML),
261 Self::OuterHtml => serializer.serialize_unit_variant(UNIT_NAME, 1, HX_SWAP_OUTER_HTML),
262 Self::BeforeBegin => {
263 serializer.serialize_unit_variant(UNIT_NAME, 2, HX_SWAP_BEFORE_BEGIN)
264 }
265 Self::AfterBegin => {
266 serializer.serialize_unit_variant(UNIT_NAME, 3, HX_SWAP_AFTER_BEGIN)
267 }
268 Self::BeforeEnd => serializer.serialize_unit_variant(UNIT_NAME, 4, HX_SWAP_BEFORE_END),
269 Self::AfterEnd => serializer.serialize_unit_variant(UNIT_NAME, 5, HX_SWAP_AFTER_END),
270 Self::Delete => serializer.serialize_unit_variant(UNIT_NAME, 6, HX_SWAP_DELETE),
271 Self::None => serializer.serialize_unit_variant(UNIT_NAME, 7, HX_SWAP_NONE),
272 }
273 }
274}
275
276impl From<SwapOption> for HeaderValue {
277 fn from(value: SwapOption) -> Self {
278 match value {
279 SwapOption::InnerHtml => HeaderValue::from_static(HX_SWAP_INNER_HTML),
280 SwapOption::OuterHtml => HeaderValue::from_static(HX_SWAP_OUTER_HTML),
281 SwapOption::BeforeBegin => HeaderValue::from_static(HX_SWAP_BEFORE_BEGIN),
282 SwapOption::AfterBegin => HeaderValue::from_static(HX_SWAP_AFTER_BEGIN),
283 SwapOption::BeforeEnd => HeaderValue::from_static(HX_SWAP_BEFORE_END),
284 SwapOption::AfterEnd => HeaderValue::from_static(HX_SWAP_AFTER_END),
285 SwapOption::Delete => HeaderValue::from_static(HX_SWAP_DELETE),
286 SwapOption::None => HeaderValue::from_static(HX_SWAP_NONE),
287 }
288 }
289}