1use thiserror::Error;
2
3#[derive(Error, Debug)]
4#[non_exhaustive]
5pub enum Error {
6 #[error(transparent)]
8 FluentUriParse(#[from] fluent_uri::ParseError),
9
10 #[error(transparent)]
12 JsonschemaValidation(#[from] Box<jsonschema::ValidationError<'static>>),
13
14 #[error(transparent)]
15 Reqwest(#[from] reqwest::Error),
17
18 #[error("json value is not an object or an array")]
20 ScalarJson(serde_json::Value),
21
22 #[error(transparent)]
23 SerdeJson(#[from] serde_json::Error),
25
26 #[error(transparent)]
27 Stac(#[from] stac::Error),
29
30 #[error("{} validation error(s)", .0.len())]
32 Validation(Vec<Validation>),
33}
34
35#[derive(Debug)]
37pub struct Validation {
38 id: Option<String>,
40
41 r#type: Option<stac::Type>,
43
44 error: jsonschema::ValidationError<'static>,
46}
47
48impl Validation {
49 pub(crate) fn new(
50 error: jsonschema::ValidationError<'_>,
51 value: Option<&serde_json::Value>,
52 ) -> Validation {
53 let mut id = None;
54 let mut r#type = None;
55 if let Some(value) = value.and_then(|v| v.as_object()) {
56 id = value.get("id").and_then(|v| v.as_str()).map(String::from);
57 r#type = value
58 .get("type")
59 .and_then(|v| v.as_str())
60 .and_then(|s| s.parse::<stac::Type>().ok());
61 }
62 Validation {
63 id,
64 r#type,
65 error: error.to_owned(),
66 }
67 }
68
69 pub fn into_json(self) -> serde_json::Value {
71 serde_json::json!({
72 "id": self.id,
73 "type": self.r#type,
74 "error": self.error.to_string(),
75 })
76 }
77}
78
79impl super::Error {
80 pub(crate) fn from_validation_errors<'a, I>(
81 errors: I,
82 value: Option<&serde_json::Value>,
83 ) -> super::Error
84 where
85 I: Iterator<Item = jsonschema::ValidationError<'a>>,
86 {
87 super::Error::Validation(errors.map(|error| Validation::new(error, value)).collect())
88 }
89}
90
91impl std::fmt::Display for Validation {
92 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
93 if let Some(r#type) = self.r#type {
94 if let Some(id) = self.id.as_ref() {
95 write!(f, "{}[id={id}]: {}", r#type, self.error)
96 } else {
97 write!(f, "{}: {}", r#type, self.error)
98 }
99 } else if let Some(id) = self.id.as_ref() {
100 write!(f, "[id={id}]: {}", self.error)
101 } else {
102 write!(f, "{}", self.error)
103 }
104 }
105}