1#[cfg(feature = "axum")]
2mod axum;
3mod headers;
4use std::collections::HashSet;
5
6use derive_more::{Display, From};
7use http::HeaderMap;
8use serde::{Deserialize, Serialize};
9
10#[derive(Debug, From, Display)]
11pub enum Error {
12 #[from]
13 InvalidJson(serde_json::Error),
14 EventIsNotSerializableAsObject,
15}
16
17#[derive(Debug, Serialize, Deserialize, Default, PartialEq)]
21#[serde(rename_all = "lowercase")]
22pub enum LayerMode {
23 #[default]
24 ROOT,
26 MODAL,
28 DRAWER,
30 POPUP,
32 COVER,
34}
35
36impl LayerMode {
37 pub fn is_root(&self) -> bool {
39 self == &LayerMode::ROOT
40 }
41
42 pub fn is_overlay(&self) -> bool {
44 self != &LayerMode::ROOT
45 }
46}
47
48#[derive(Debug, Serialize, Deserialize, PartialEq)]
52#[serde(rename_all = "lowercase")]
53pub enum MatchingLayer {
54 CURRENT,
56 PARENT,
58 CLOSEST,
60 OVERLAY,
62 ANCESTOR,
64 CHILD,
66 DESCENDANT,
68 SUBTREE,
70 INDEX(u32),
72}
73
74#[derive(Debug, Default)]
166pub struct Unpoly {
167 success: Option<bool>,
168 request_version: Option<String>,
169 request_context: Option<serde_json::Value>,
170 request_fail_context: Option<serde_json::Value>,
171 request_fail_mode: LayerMode,
172 request_mode: LayerMode,
173 request_target: Option<String>,
174 request_fail_target: Option<String>,
175 request_validate: Vec<String>,
176 response_context: Option<serde_json::Value>,
177 response_accept_layer: Option<serde_json::Value>,
178 response_dismiss_layer: Option<serde_json::Value>,
179 response_events: Vec<serde_json::Value>,
180 response_evict_cache: Option<String>,
181 response_expire_cache: Option<String>,
182 response_location: Option<String>,
183 response_method: Option<String>,
184 response_target: Option<String>,
185 response_title: Option<String>,
186 response_vary: HashSet<String>,
187}
188
189use serde_json::Value;
190
191impl Unpoly {
192 pub fn is_up(&mut self) -> bool {
196 if self.request_version.is_some() {
197 self.response_vary.insert("X-Up-Version".to_string());
198 true
199 } else {
200 false
201 }
202 }
203
204 pub fn success(&mut self) -> Option<bool> {
209 self.success
210 }
211
212 pub fn set_success(&mut self, success: bool) {
218 self.success = Some(success);
219 if success {
220 self.response_vary.insert("X-Up-Target".to_string());
221 self.response_target = self.request_target.clone();
222 } else {
223 self.response_vary.insert("X-Up-Fail-Target".to_string());
224 self.response_target = self.request_fail_target.clone();
225 }
226 }
227
228 pub fn mode(&mut self) -> &LayerMode {
232 if let Some(false) = self.success {
233 self.response_vary.insert("X-Up-Fail-Mode".to_string());
234 &self.request_fail_mode
235 } else {
236 self.response_vary.insert("X-Up-Mode".to_string());
237 &self.request_mode
238 }
239 }
240
241 pub fn emit_event_layer<S: Serialize>(
242 &mut self,
243 type_: impl Into<String>,
244 event: S,
245 matching_layer: MatchingLayer,
246 ) -> Result<(), Error> {
247 let mut event = serde_json::to_value(event)?;
248 if !event.is_object() {
249 return Err(Error::EventIsNotSerializableAsObject);
250 }
251
252 event.as_object_mut().unwrap().insert(
253 "layer".to_string(),
254 match matching_layer {
255 MatchingLayer::INDEX(index) => Value::Number(index.into()),
256 other => serde_json::to_value(other).unwrap(),
257 },
258 );
259
260 self.emit_event(type_, event)?;
261 Ok(())
262 }
263
264 pub fn accept_layer<S: Serialize>(&mut self, value: S) -> Result<(), Error> {
265 self.response_accept_layer = Some(serde_json::to_value(value)?);
266 self.response_dismiss_layer = None;
267 Ok(())
268 }
269
270 pub fn accept_layer_without_value(&mut self) -> Result<(), Error> {
271 self.accept_layer("null")?;
272 Ok(())
273 }
274
275 pub fn dismiss_layer<S: Serialize>(&mut self, value: S) -> Result<(), Error> {
276 self.response_dismiss_layer = Some(serde_json::to_value(value).unwrap());
277 self.response_accept_layer = None;
278 Ok(())
279 }
280
281 pub fn dismiss_layer_without_value(&mut self) -> Result<(), Error> {
282 self.dismiss_layer("null")?;
283 Ok(())
284 }
285
286 pub fn context(&mut self) -> Option<&Value> {
289 if self.response_context.is_some() {
290 return self.response_context.as_ref();
291 }
292 if Some(false) == self.success {
293 if self.request_fail_context.is_some() && self.is_up() {
294 self.response_vary.insert("X-Up-Fail-Context".to_string());
295 }
296 self.request_fail_context.as_ref()
297 } else {
298 if self.request_context.is_some() && self.is_up() {
299 self.response_vary.insert("X-Up-Context".to_string());
300 }
301 self.request_context.as_ref()
302 }
303 }
304
305 pub fn set_context<S: Serialize>(&mut self, layer: S) {
306 self.response_context = Some(serde_json::to_value(layer).unwrap());
307 }
308
309 pub fn target(&mut self) -> Option<&str> {
310 if self.response_target.is_some() {
311 return self.response_target.as_deref();
312 }
313 if let Some(false) = self.success {
314 self.response_vary.insert("X-Up-Fail-Target".to_string());
315 self.request_fail_target.as_deref()
316 } else {
317 self.response_vary.insert("X-Up-Target".to_string());
318 self.request_target.as_deref()
319 }
320 }
321
322 pub fn set_target(&mut self, target: impl Into<String>) {
323 self.response_target = Some(target.into());
324 }
325
326 pub fn validate(&mut self) -> &Vec<String> {
327 if !self.request_validate.is_empty() && self.is_up() {
328 self.response_vary.insert("X-Up-Validate".to_string());
329 }
330 &self.request_validate
331 }
332
333 pub fn title(&self) -> Option<&str> {
334 self.response_title.as_deref()
335 }
336
337 pub fn set_title(&mut self, title: impl Into<String>) {
338 self.response_title = Some(title.into());
339 }
340
341 pub fn location(&self) -> Option<&str> {
342 self.response_location.as_deref()
343 }
344
345 pub fn set_location(&mut self, location: impl Into<String>) {
346 self.response_location = Some(location.into());
347 }
348
349 pub fn method(&mut self) -> Option<&str> {
350 self.response_method.as_deref()
351 }
352
353 pub fn set_method(&mut self, method: impl Into<String>) {
354 self.response_method = Some(method.into());
355 }
356
357 pub fn emit_event<S: Serialize>(
358 &mut self,
359 type_: impl Into<String>,
360 event: S,
361 ) -> Result<(), Error> {
362 let mut event = serde_json::to_value(event)?;
363 if !event.is_object() {
364 return Err(Error::EventIsNotSerializableAsObject);
365 }
366
367 let type_: String = type_.into();
368
369 event
370 .as_object_mut()
371 .unwrap()
372 .insert("type".to_string(), Value::String(type_));
373
374 self.response_events.push(event);
375 Ok(())
376 }
377
378 pub fn set_evict_cache(&mut self, cache: impl Into<String>) {
379 self.response_evict_cache = Some(cache.into());
380 }
381
382 pub fn set_expire_cache(&mut self, cache: impl Into<String>) {
383 self.response_expire_cache = Some(cache.into());
384 }
385
386 pub fn get_headers(&self) -> Result<HeaderMap, Error> {
387 let mut headers = HeaderMap::new();
388 if let Some(title) = &self.response_title {
389 headers.insert(headers::TITLE, title.parse().unwrap());
390 }
391 if let Some(location) = &self.response_location {
392 headers.insert(headers::LOCATION, location.parse().unwrap());
393 }
394 if let Some(accept_layer) = &self.response_accept_layer {
395 headers.insert(
396 headers::ACCEPT_LAYER,
397 serde_json::to_string(accept_layer)?.parse().unwrap(),
398 );
399 }
400 if let Some(dismiss_layer) = &self.response_dismiss_layer {
401 headers.insert(
402 headers::DISMISS_LAYER,
403 serde_json::to_string(dismiss_layer)?.parse().unwrap(),
404 );
405 }
406 if let Some(context) = &self.response_context {
407 headers.insert(
408 headers::CONTEXT,
409 serde_json::to_string(context)?.parse().unwrap(),
410 );
411 }
412 if let Some(target) = &self.response_target {
413 headers.insert(headers::TARGET, target.parse().unwrap());
414 }
415 if let Some(method) = &self.response_method {
416 headers.insert(headers::METHOD, method.parse().unwrap());
417 }
418 if let Some(evict_cache) = &self.response_evict_cache {
419 headers.insert(headers::EVICT_CACHE, evict_cache.parse().unwrap());
420 }
421 if let Some(expire_cache) = &self.response_expire_cache {
422 headers.insert(headers::EXPIRE_CACHE, expire_cache.parse().unwrap());
423 }
424 if !self.response_events.is_empty() {
425 let events = serde_json::to_value(&self.response_events)?;
426 headers.insert(
427 headers::EVENTS,
428 serde_json::to_string(&events)?.parse().unwrap(),
429 );
430 }
431 if !self.response_vary.is_empty() {
432 let mut vary: Vec<&String> = self.response_vary.iter().collect();
433 vary.sort();
434 let vary = vary.iter().fold(
435 "".to_string(),
436 |a, b| if !a.is_empty() { a + "," } else { a } + b,
437 );
438 headers.insert(headers::VARY, vary.parse().unwrap());
439 }
440 Ok(headers)
441 }
442}