1pub use dog_schema_macros::schema;
2
3use dog_core::errors::DogError;
4use serde_json::{json, Map, Value};
5
6#[derive(Default)]
7pub struct SchemaErrors {
8 map: Map<String, Value>,
9}
10
11impl SchemaErrors {
12 pub fn push_schema(&mut self, msg: impl Into<String>) {
13 Self::push_to(&mut self.map, "_schema", msg);
14 }
15
16 pub fn push_field(&mut self, field: &str, msg: impl Into<String>) {
17 Self::push_to(&mut self.map, field, msg);
18 }
19
20 fn push_to(map: &mut Map<String, Value>, key: &str, msg: impl Into<String>) {
21 let msg = Value::String(msg.into());
22 match map.get_mut(key) {
23 Some(Value::Array(arr)) => arr.push(msg),
24 Some(_) => {
25 map.insert(key.to_string(), Value::Array(vec![msg]));
26 }
27 None => {
28 map.insert(key.to_string(), Value::Array(vec![msg]));
29 }
30 }
31 }
32
33 pub fn is_empty(&self) -> bool {
34 self.map.is_empty()
35 }
36
37 pub fn into_unprocessable_anyhow(self, message: &str) -> anyhow::Error {
38 DogError::unprocessable(message)
39 .with_errors(Value::Object(self.map))
40 .into_anyhow()
41 }
42}
43
44pub fn unprocessable(message: &str, errors: Value) -> anyhow::Error {
45 DogError::unprocessable(message).with_errors(errors).into_anyhow()
46}
47
48pub fn schema_error(message: &str, msg: impl Into<String>) -> anyhow::Error {
49 unprocessable(message, json!({"_schema": [msg.into()]}))
50}