1use crate::link::{Link, Links};
2use serde::{Deserialize, Serialize};
3
4#[derive(Debug, Default, Clone, Deserialize, Serialize)]
5#[serde(rename_all = "camelCase")]
6pub struct JsonApiError {
7 #[serde(skip_serializing_if = "Option::is_none")]
8 id: Option<String>,
9 #[serde(skip_serializing_if = "Option::is_none")]
10 links: Option<Links>,
11 #[serde(skip_serializing_if = "Option::is_none")]
12 status: Option<String>,
13 #[serde(skip_serializing_if = "Option::is_none")]
14 code: Option<String>,
15 #[serde(skip_serializing_if = "Option::is_none")]
16 title: Option<String>,
17 #[serde(skip_serializing_if = "Option::is_none")]
18 detail: Option<String>,
19 #[serde(skip_serializing_if = "Option::is_none")]
20 source: Option<Source>,
21 }
23
24impl JsonApiError {
25 pub fn new() -> Self {
26 JsonApiError {
27 id: None,
28 links: None,
29 status: None,
30 code: None,
31 title: None,
32 detail: None,
33 source: None,
34 }
35 }
36
37 pub fn finish(&self) -> Self {
38 self.clone()
39 }
40
41 pub fn id(&mut self, id: String) -> &mut Self {
42 self.id = Some(id);
43 self
44 }
45
46 pub fn links(&mut self, links: Vec<Link>) -> &mut Self {
47 let mut error = "";
48 let (mut has_about, mut has_pagination) = (false, false);
49 links.iter().for_each(|link| match link {
50 Link::About(_) | Link::AboutObject(_) => {
51 error = "When returning an error you need to have an about link.";
52 has_about = true
53 }
54 Link::First(_) | Link::Last(_) | Link::Previous(_) | Link::Next(_) => {
55 error = "Errors should not have pagination links.";
56 has_pagination = true
57 }
58 _ => (),
59 });
60 if !has_about || has_pagination {
61 panic!(error)
62 }
63 self.links = Some(Links::new(links));
64 self
65 }
66
67 pub fn status(&mut self, status: u32) -> &mut Self {
68 self.status = Some(status.to_string());
69 self
70 }
71
72 pub fn code(&mut self, code: isize) -> &mut Self {
73 self.code = Some(code.to_string());
74 self
75 }
76
77 pub fn title(&mut self, title: &str) -> &mut Self {
78 self.title = Some(title.to_string());
79 self
80 }
81
82 pub fn detail(&mut self, detail: &str) -> &mut Self {
83 self.detail = Some(detail.to_string());
84 self
85 }
86
87 pub fn source(&mut self, source: Source) -> &mut Self {
88 self.source = Some(source);
89 self
90 }
91}
92
93#[derive(Debug, Clone, Deserialize, Serialize)]
94#[serde(rename_all = "camelCase")]
95pub enum Source {
96 Pointer(String),
97 Parameter(String),
98}