divviup_client/
validation_errors.rs

1use pad_adapter::PadAdapter;
2use serde::{Deserialize, Serialize};
3use std::{
4    collections::HashMap,
5    fmt::{self, Display, Formatter, Write},
6};
7
8#[derive(Serialize, Deserialize, Debug)]
9pub struct ValidationError {
10    code: String,
11    #[serde(skip_serializing_if = "Option::is_none")]
12    message: Option<String>,
13    #[serde(skip_serializing_if = "HashMap::is_empty")]
14    params: HashMap<String, serde_json::Value>,
15}
16
17#[derive(Serialize, Deserialize, Debug)]
18#[serde(untagged)]
19pub enum ValidationErrors {
20    Map(HashMap<String, ValidationErrors>),
21    List(Vec<ValidationError>),
22}
23
24impl Display for ValidationError {
25    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
26        let code = &self.code;
27        match (&self.message, self.params.is_empty()) {
28            (None, true) => f.write_str(&self.code),
29            (Some(message), _) => f.write_fmt(format_args!("{code} {message}")),
30            (None, false) => f.write_fmt(format_args!(
31                "{code} {}",
32                serde_json::to_string(&self.params).unwrap()
33            )),
34        }
35    }
36}
37
38impl Display for ValidationErrors {
39    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
40        let mut pad_adapter = PadAdapter::with_padding(f, "  ");
41        match &self {
42            ValidationErrors::Map(map) => {
43                for (key, values) in map {
44                    write!(pad_adapter, "- {key}:\n{values}")?;
45                }
46            }
47            ValidationErrors::List(errors) => {
48                for value in errors {
49                    writeln!(pad_adapter, "* {value}")?;
50                }
51            }
52        }
53
54        Ok(())
55    }
56}