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
100fn map_entries_are_strictly_canonical(entries: &[(Value, Value)]) -> bool {
103 entries.windows(2).all(|pair| {
104 let [left, right] = pair else {
105 return true;
106 };
107
108 compare_map_entry_keys(left, right) == Ordering::Less
109 })
110}
111
112pub(super) fn normalize_map_entries(
114 mut entries: Vec<(Value, Value)>,
115) -> Result<Vec<(Value, Value)>, MapValueError> {
116 validate_map_entries(&entries)?;
117 sort_map_entries_in_place(entries.as_mut_slice());
118
119 for i in 1..entries.len() {
120 let (left_key, _) = &entries[i - 1];
121 let (right_key, _) = &entries[i];
122 if Value::canonical_cmp_key(left_key, right_key) == Ordering::Equal {
123 return Err(MapValueError::DuplicateKey {
124 left_index: i - 1,
125 right_index: i,
126 });
127 }
128 }
129
130 Ok(entries)
131}
132
133impl Value {
134 pub fn validate_map_entries(entries: &[(Self, Self)]) -> Result<(), MapValueError> {
136 validate_map_entries(entries)
137 }
138
139 pub(crate) fn sort_map_entries_in_place(entries: &mut [(Self, Self)]) {
141 sort_map_entries_in_place(entries);
142 }
143
144 pub(crate) fn map_entries_are_strictly_canonical(entries: &[(Self, Self)]) -> bool {
147 map_entries_are_strictly_canonical(entries)
148 }
149
150 pub fn normalize_map_entries(
152 entries: Vec<(Self, Self)>,
153 ) -> Result<Vec<(Self, Self)>, MapValueError> {
154 normalize_map_entries(entries)
155 }
156}