Skip to main content

ogcapi_types/common/
exception.rs

1use std::{error::Error, fmt::Display};
2
3use serde::{Deserialize, Serialize};
4use serde_json::{Map, Value};
5
6/// Exception based on [`RFC 7807`](https://datatracker.ietf.org/doc/html/rfc7807)
7#[serde_with::skip_serializing_none]
8#[derive(Serialize, Deserialize, Default, Debug, PartialEq, Eq, Clone)]
9pub struct Exception {
10    /// A URI reference that identifies the problem type.
11    pub r#type: String,
12    /// A short, human-readable summary of the problem type.
13    pub title: Option<String>,
14    /// The HTTP status code generated by the origin server for this occurrence
15    /// of the problem.
16    pub status: Option<u16>,
17    /// A human-readable explanation specific to this occurrence of the problem.
18    pub detail: Option<String>,
19    /// A URI reference that identifies the specific occurrence of the problem.
20    /// It may or may not yield further information if dereferenced.
21    pub instance: Option<String>,
22    #[serde(flatten, default, skip_serializing_if = "Map::is_empty")]
23    pub additional_properties: Map<String, Value>,
24}
25
26impl Exception {
27    pub fn new(r#type: impl ToString) -> Self {
28        Exception {
29            r#type: r#type.to_string(),
30            ..Default::default()
31        }
32    }
33
34    pub fn new_from_status(status: u16) -> Self {
35        let exception = Exception::new(format!(
36            "https://httpwg.org/specs/rfc7231.html#status.{}",
37            status
38        ));
39        exception.status(status)
40    }
41
42    pub fn title(mut self, title: impl ToString) -> Self {
43        self.title = Some(title.to_string());
44        self
45    }
46
47    pub fn status(mut self, status: u16) -> Self {
48        self.status = Some(status);
49        self
50    }
51
52    pub fn detail(mut self, detail: impl ToString) -> Self {
53        self.detail = Some(detail.to_string());
54        self
55    }
56
57    pub fn instance(mut self, instance: impl ToString) -> Self {
58        self.instance = Some(instance.to_string());
59        self
60    }
61}
62
63impl Display for Exception {
64    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
65        write!(f, "{}", serde_json::to_string_pretty(self).unwrap())
66    }
67}
68
69impl Error for Exception {}
70
71#[cfg(test)]
72mod tests {
73    use super::Exception;
74
75    #[test]
76    fn exception() {
77        let e = Exception::new_from_status(500);
78        println!("{:#?}", e);
79        println!("{}", serde_json::to_string_pretty(&e).unwrap());
80    }
81}