1use crate::value::Value;
8use std::cmp::Ordering;
9use std::fmt;
10
11#[derive(Clone, Debug, Eq, PartialEq)]
20pub enum MapValueError {
21 EmptyKey {
22 index: usize,
23 },
24 NonScalarKey {
25 index: usize,
26 key: Value,
27 },
28 NonScalarValue {
29 index: usize,
30 value: Value,
31 },
32 DuplicateKey {
33 left_index: usize,
34 right_index: usize,
35 },
36}
37
38impl fmt::Display for MapValueError {
39 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
40 f.write_str("map value error")
41 }
42}
43
44impl std::error::Error for MapValueError {}
45
46#[derive(Clone, Debug, Eq, PartialEq)]
55pub enum SchemaInvariantError {
56 InvalidMapValue(MapValueError),
57}
58
59impl fmt::Display for SchemaInvariantError {
60 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
61 f.write_str("schema invariant error")
62 }
63}
64
65impl std::error::Error for SchemaInvariantError {}
66
67impl From<MapValueError> for SchemaInvariantError {
68 fn from(value: MapValueError) -> Self {
69 Self::InvalidMapValue(value)
70 }
71}
72
73fn validate_map_entries(entries: &[(Value, Value)]) -> Result<(), MapValueError> {
75 for (index, (key, _value)) in entries.iter().enumerate() {
76 if matches!(key, Value::Null) {
77 return Err(MapValueError::EmptyKey { index });
78 }
79 if !key.is_scalar() {
80 return Err(MapValueError::NonScalarKey {
81 index,
82 key: key.clone(),
83 });
84 }
85 }
86
87 Ok(())
88}
89
90fn compare_map_entry_keys(left: &(Value, Value), right: &(Value, Value)) -> Ordering {
92 Value::canonical_cmp_key(&left.0, &right.0)
93}
94
95fn sort_map_entries_in_place(entries: &mut [(Value, Value)]) {
97 entries.sort_by(compare_map_entry_keys);
98}
99
100pub(super) fn normalize_map_entries(
102 mut entries: Vec<(Value, Value)>,
103) -> Result<Vec<(Value, Value)>, MapValueError> {
104 validate_map_entries(&entries)?;
105 sort_map_entries_in_place(entries.as_mut_slice());
106
107 for i in 1..entries.len() {
108 let (left_key, _) = &entries[i - 1];
109 let (right_key, _) = &entries[i];
110 if Value::canonical_cmp_key(left_key, right_key) == Ordering::Equal {
111 return Err(MapValueError::DuplicateKey {
112 left_index: i - 1,
113 right_index: i,
114 });
115 }
116 }
117
118 Ok(entries)
119}
120
121impl Value {
122 pub fn validate_map_entries(entries: &[(Self, Self)]) -> Result<(), MapValueError> {
124 validate_map_entries(entries)
125 }
126
127 pub fn normalize_map_entries(
129 entries: Vec<(Self, Self)>,
130 ) -> Result<Vec<(Self, Self)>, MapValueError> {
131 normalize_map_entries(entries)
132 }
133}