json_schema_tools/
key_order.rs

1use super::{constants::*, path::Path};
2use serde_json::Value;
3use std::cmp::Ordering;
4
5#[derive(Clone, Debug, Eq, PartialEq)]
6pub struct KeyOrderMismatch<'a> {
7    pub path: Path<'a>,
8    pub first: &'a str,
9    pub second: &'a str,
10}
11
12pub fn check_key_order(value: &Value) -> Vec<KeyOrderMismatch> {
13    super::util::nodes_with_path(value)
14        .iter()
15        .filter(|(path, _)| !path.allows_arbitrary_keys())
16        .filter_map(|(path, value)| {
17            value.as_object().and_then(|fields| {
18                let keys = fields.keys().map(|key| Key(key)).collect::<Vec<_>>();
19
20                keys.windows(2)
21                    .find(|window| window[0] >= window[1])
22                    .map(|bad_window| KeyOrderMismatch {
23                        path: path.clone(),
24                        first: bad_window[0].0,
25                        second: bad_window[1].0,
26                    })
27            })
28        })
29        .collect()
30}
31
32#[derive(Clone, Copy, Eq, PartialEq)]
33struct Key<'a>(&'a str);
34
35impl<'a> PartialOrd for Key<'a> {
36    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
37        if self == other {
38            Some(Ordering::Equal)
39        } else {
40            match (self.0, other.0) {
41                (ID_KEY, _) => Some(Ordering::Less),
42                (_, ID_KEY) => Some(Ordering::Greater),
43                (TITLE_KEY, _) => Some(Ordering::Less),
44                (_, TITLE_KEY) => Some(Ordering::Greater),
45                (DESCRIPTION_KEY, _) => Some(Ordering::Less),
46                (_, DESCRIPTION_KEY) => Some(Ordering::Greater),
47                (COMMENT_KEY, _) => Some(Ordering::Less),
48                (_, COMMENT_KEY) => Some(Ordering::Greater),
49                (TYPE_KEY, _) => Some(Ordering::Less),
50                (_, TYPE_KEY) => Some(Ordering::Greater),
51                (ADDITIONAL_PROPERTIES_KEY, _) => Some(Ordering::Less),
52                (_, ADDITIONAL_PROPERTIES_KEY) => Some(Ordering::Greater),
53                (PROPERTIES_KEY, _) => Some(Ordering::Less),
54                (_, PROPERTIES_KEY) => Some(Ordering::Greater),
55                (REQUIRED_KEY, _) => Some(Ordering::Less),
56                (_, REQUIRED_KEY) => Some(Ordering::Greater),
57                (EXAMPLES_KEY, _) => Some(Ordering::Greater),
58                (_, EXAMPLES_KEY) => Some(Ordering::Less),
59                (_, _) => None,
60            }
61        }
62    }
63}