1use crate::error::{JsonTy, ResolveError};
4use core::cmp::Ordering;
5use serde_json::Value;
6use std::ops::{Deref, Index, IndexMut};
7
8#[derive(Clone, Debug, PartialEq)]
10pub enum Idx {
11 Array(usize),
13 Object(String),
15}
16
17impl Idx {
18 #[must_use]
20 pub fn is_array(&self) -> bool {
21 matches!(self, Idx::Array(_))
22 }
23
24 #[must_use]
26 pub fn is_object(&self) -> bool {
27 matches!(self, Idx::Object(_))
28 }
29
30 #[must_use]
32 pub fn as_array(&self) -> Option<usize> {
33 match self {
34 Idx::Array(u) => Some(*u),
35 _ => None,
36 }
37 }
38
39 #[must_use]
41 pub fn as_object(&self) -> Option<&str> {
42 match self {
43 Idx::Object(s) => Some(s),
44 _ => None,
45 }
46 }
47}
48
49impl From<Idx> for Value {
50 fn from(idx: Idx) -> Self {
51 match idx {
52 Idx::Array(i) => Value::from(i),
53 Idx::Object(str) => Value::from(str),
54 }
55 }
56}
57
58impl Index<&Idx> for Value {
59 type Output = Value;
60
61 fn index(&self, index: &Idx) -> &Self::Output {
62 match (self, index) {
63 (Value::Array(a), Idx::Array(idx)) => &a[*idx],
64 (Value::Object(o), Idx::Object(idx)) => &o[idx],
65 (val, idx) => panic!("Invalid index {:?} for value {:?}", val, idx),
66 }
67 }
68}
69
70impl IndexMut<&Idx> for Value {
71 fn index_mut(&mut self, index: &Idx) -> &mut Self::Output {
72 match (self, index) {
73 (Value::Array(a), Idx::Array(idx)) => &mut a[*idx],
74 (Value::Object(o), Idx::Object(idx)) => &mut o[idx],
75 (val, idx) => panic!("Invalid index {:?} for value {:?}", val, idx),
76 }
77 }
78}
79
80#[derive(Clone, Debug, PartialEq)]
82pub struct IdxPath(Vec<Idx>);
83
84impl IdxPath {
85 pub(crate) const fn new(indices: Vec<Idx>) -> IdxPath {
86 IdxPath(indices)
87 }
88
89 #[must_use]
91 pub fn raw_path(&self) -> &[Idx] {
92 &self.0
93 }
94
95 #[must_use]
101 pub fn remove(&self, n: usize) -> IdxPath {
102 assert!(
103 n <= self.len(),
104 "Cannot remove {} items from path, path is only {} items long",
105 n,
106 self.len()
107 );
108 IdxPath(self.0[..self.len() - n].to_owned())
109 }
110
111 pub fn resolve_on<'a>(&self, value: &'a Value) -> Result<&'a Value, ResolveError> {
118 let mut cur = value;
119
120 for idx in &self.0 {
121 match idx {
122 Idx::Array(i) => {
123 cur = cur
124 .as_array()
125 .ok_or_else(|| ResolveError::mismatched(JsonTy::Array, cur))?
126 .get(*i)
127 .ok_or_else(|| ResolveError::MissingIdx(idx.clone()))?;
128 }
129 Idx::Object(i) => {
130 cur = cur
131 .as_object()
132 .ok_or_else(|| ResolveError::mismatched(JsonTy::Object, cur))?
133 .get(i)
134 .ok_or_else(|| ResolveError::MissingIdx(idx.clone()))?;
135 }
136 }
137 }
138
139 Ok(cur)
140 }
141
142 pub fn resolve_on_mut<'a>(&self, value: &'a mut Value) -> Result<&'a mut Value, ResolveError> {
149 let mut cur = value;
150
151 for idx in &self.0 {
152 match idx {
153 Idx::Array(i) => {
154 let json_ty = JsonTy::from(&*cur);
155 cur = cur
156 .as_array_mut()
157 .ok_or(ResolveError::MismatchedTy {
158 expected: JsonTy::Array,
159 actual: json_ty,
160 })?
161 .get_mut(*i)
162 .ok_or_else(|| ResolveError::MissingIdx(idx.clone()))?;
163 }
164 Idx::Object(i) => {
165 let json_ty = JsonTy::from(&*cur);
166 cur = cur
167 .as_object_mut()
168 .ok_or(ResolveError::MismatchedTy {
169 expected: JsonTy::Array,
170 actual: json_ty,
171 })?
172 .get_mut(i)
173 .ok_or_else(|| ResolveError::MissingIdx(idx.clone()))?;
174 }
175 }
176 }
177
178 Ok(cur)
179 }
180
181 pub(crate) fn sort_specific_last(left: &IdxPath, right: &IdxPath) -> Ordering {
182 if left.is_empty() && right.is_empty() {
183 return Ordering::Equal;
184 }
185
186 match right.len().cmp(&left.len()) {
187 Ordering::Equal => {
188 let left = &left.0[left.len() - 1];
189 let right = &right.0[right.len() - 1];
190 left.as_array()
191 .and_then(|l| right.as_array().map(|r| (l, r)))
192 .map_or(Ordering::Equal, |(l, r)| r.cmp(&l))
193 }
194 other => other,
195 }
196 }
197}
198
199impl Deref for IdxPath {
200 type Target = [Idx];
201
202 fn deref(&self) -> &Self::Target {
203 &self.0
204 }
205}
206
207impl From<Vec<Idx>> for IdxPath {
208 fn from(path: Vec<Idx>) -> Self {
209 IdxPath(path)
210 }
211}