1use std::mem;
2
3use crate::{
4 error::{JsonError, Result},
5 operation::Operator,
6 path::Path,
7};
8
9use serde_json::Value;
10
11pub trait Routable {
12 fn route_get(&self, paths: &Path) -> Result<Option<&Value>>;
13
14 fn route_get_mut(&mut self, paths: &Path) -> Result<Option<&mut Value>>;
15}
16
17pub trait Appliable {
18 fn apply(&mut self, paths: Path, operator: Operator) -> Result<()>;
19}
20
21impl Routable for Value {
22 fn route_get(&self, paths: &Path) -> Result<Option<&Value>> {
23 match self {
24 Value::Array(array) => array.route_get(paths),
25 Value::Object(obj) => obj.route_get(paths),
26 Value::Null => Ok(None),
27 _ => {
28 if paths.is_empty() {
29 Ok(Some(self))
30 } else {
31 Err(JsonError::BadPath)
32 }
33 }
34 }
35 }
36
37 fn route_get_mut(&mut self, paths: &Path) -> Result<Option<&mut Value>> {
38 match self {
39 Value::Array(array) => array.route_get_mut(paths),
40 Value::Object(obj) => obj.route_get_mut(paths),
41 _ => {
42 if paths.is_empty() {
43 Ok(Some(self))
44 } else {
45 Err(JsonError::BadPath)
46 }
47 }
48 }
49 }
50}
51
52impl Routable for serde_json::Map<String, serde_json::Value> {
53 fn route_get(&self, paths: &Path) -> Result<Option<&Value>> {
54 let k = paths.first_key_path().ok_or(JsonError::BadPath)?;
55 if let Some(v) = self.get(k) {
56 let next_level = paths.next_level();
57 if next_level.is_empty() {
58 Ok(Some(v))
59 } else {
60 v.route_get(&next_level)
61 }
62 } else {
63 Ok(None)
64 }
65 }
66
67 fn route_get_mut(&mut self, paths: &Path) -> Result<Option<&mut Value>> {
68 let k = paths.first_key_path().ok_or(JsonError::BadPath)?;
69 if let Some(v) = self.get_mut(k) {
70 let next_level = paths.next_level();
71 if next_level.is_empty() {
72 Ok(Some(v))
73 } else {
74 v.route_get_mut(&next_level)
75 }
76 } else {
77 Ok(None)
78 }
79 }
80}
81
82impl Routable for Vec<serde_json::Value> {
83 fn route_get(&self, paths: &Path) -> Result<Option<&Value>> {
84 let i = paths.first_index_path().ok_or(JsonError::BadPath)?;
85 if let Some(v) = self.get(*i) {
86 let next_level = paths.next_level();
87 if next_level.is_empty() {
88 Ok(Some(v))
89 } else {
90 v.route_get(&next_level)
91 }
92 } else {
93 Ok(None)
94 }
95 }
96
97 fn route_get_mut(&mut self, paths: &Path) -> Result<Option<&mut Value>> {
98 let i = paths.first_index_path().ok_or(JsonError::BadPath)?;
99 if let Some(v) = self.get_mut(*i) {
100 let next_level = paths.next_level();
101 if next_level.is_empty() {
102 Ok(Some(v))
103 } else {
104 v.route_get_mut(&next_level)
105 }
106 } else {
107 Ok(None)
108 }
109 }
110}
111
112impl Appliable for Value {
113 fn apply(&mut self, paths: Path, op: Operator) -> Result<()> {
114 if paths.len() > 1 {
115 let (left, right) = paths.split_at(paths.len() - 1);
116 return self
117 .route_get_mut(&left)?
118 .ok_or(JsonError::BadPath)?
119 .apply(right, op);
120 }
121 match self {
122 Value::Array(array) => array.apply(paths, op),
123 Value::Object(obj) => obj.apply(paths, op),
124 _ => match op {
125 Operator::SubType(_, op, f) => {
126 if let Some(v) = f.apply(Some(self), &op)? {
127 _ = mem::replace(self, v);
128 }
129 Ok(())
130 }
131 _ => Err(JsonError::InvalidOperation(
132 "Operation can only apply on array or object".into(),
133 )),
134 },
135 }
136 }
137}
138
139impl Appliable for serde_json::Map<String, serde_json::Value> {
140 fn apply(&mut self, paths: Path, op: Operator) -> Result<()> {
141 assert!(paths.len() == 1);
142
143 let k = paths.first_key_path().ok_or(JsonError::BadPath)?;
144 let target_value = self.get(k);
145 match &op {
146 Operator::SubType(_, op, f) => {
147 if let Some(v) = f.apply(target_value, op)? {
148 self.insert(k.clone(), v);
149 }
150 Ok(())
151 }
152 Operator::ObjectInsert(v) => {
153 self.insert(k.clone(), v.clone());
154 Ok(())
155 }
156 Operator::ObjectDelete(_) => {
157 if target_value.is_some() {
158 self.remove(k);
162 }
164 Ok(())
165 }
166 Operator::ObjectReplace(new_v, _) => {
167 if target_value.is_some() {
168 self.insert(k.clone(), new_v.clone());
172 }
174 Ok(())
175 }
176 _ => Err(JsonError::BadPath),
177 }
178 }
179}
180
181impl Appliable for Vec<serde_json::Value> {
182 fn apply(&mut self, paths: Path, op: Operator) -> Result<()> {
183 assert!(paths.len() == 1);
184
185 let index = paths.first_index_path().ok_or(JsonError::BadPath)?;
186 let target_value = self.get(*index);
187 match op {
188 Operator::SubType(_, op, f) => {
189 if let Some(v) = f.apply(target_value, &op)? {
190 self[*index] = v;
191 }
192 Ok(())
193 }
194 Operator::ListInsert(v) => {
195 if *index > self.len() {
196 self.push(v.clone())
197 } else {
198 self.insert(*index, v.clone());
199 }
200 Ok(())
201 }
202 Operator::ListDelete(_) => {
203 if target_value.is_some() {
204 self.remove(*index);
208 }
210 Ok(())
211 }
212 Operator::ListReplace(new_v, _) => {
213 if target_value.is_some() {
214 self[*index] = new_v.clone();
218 }
220 Ok(())
221 }
222 Operator::ListMove(new_index) => {
223 if let Some(target_v) = target_value {
224 if *index != new_index {
225 let new_v = target_v.clone();
226 self.remove(*index);
227 self.insert(new_index, new_v);
228 }
229 }
230 Ok(())
231 }
232 _ => Err(JsonError::BadPath),
233 }
234 }
235}
236
237#[cfg(test)]
238mod tests {
239 use crate::path::Path;
240
241 use super::*;
242 use test_log::test;
243
244 #[test]
245 fn test_route_get_by_path_only_has_object() {
246 let json: Value =
247 serde_json::from_str(r#"{"level1":"world", "level12":{"level2":"world2"}}"#).unwrap();
248
249 let paths = Path::try_from(r#"["level1"]"#).unwrap();
251 assert_eq!(
252 json.route_get(&paths).unwrap().unwrap().to_string(),
253 r#""world""#
254 );
255 let paths = Path::try_from(r#"["level12", "level2"]"#).unwrap();
256 assert_eq!(
257 json.route_get(&paths).unwrap().unwrap().to_string(),
258 r#""world2""#
259 );
260 let paths = Path::try_from(r#"["level3"]"#).unwrap();
261 assert!(json.route_get(&paths).unwrap().is_none());
262
263 let json: Value =
265 serde_json::from_str(r#"{"level1":[1,{"hello":[1,[7,8]]}], "level12":"world"}"#)
266 .unwrap();
267 let paths = Path::try_from(r#"["level1", 1, "hello"]"#).unwrap();
268
269 assert_eq!(
270 json.route_get(&paths).unwrap().unwrap().to_string(),
271 r#"[1,[7,8]]"#
272 );
273 }
274
275 #[test]
276 fn test_route_get_by_path_has_array() {
277 let json: Value =
278 serde_json::from_str(r#"{"level1":["a","b"], "level12":[123, {"level2":["c","d"]}]}"#)
279 .unwrap();
280 let paths = Path::try_from(r#"["level1", 1]"#).unwrap();
282 assert_eq!(
283 json.route_get(&paths).unwrap().unwrap().to_string(),
284 r#""b""#
285 );
286 let paths = Path::try_from(r#"["level12", 0]"#).unwrap();
287
288 assert_eq!(
290 json.route_get(&paths).unwrap().unwrap().to_string(),
291 r#"123"#
292 );
293 let paths = Path::try_from(r#"["level12", 1, "level2"]"#).unwrap();
294 assert_eq!(
295 json.route_get(&paths).unwrap().unwrap().to_string(),
296 r#"["c","d"]"#
297 );
298 let json: Value =
299 serde_json::from_str(r#"{"level1":[1,{"hello":[1,[7,8]]}], "level12":"world"}"#)
300 .unwrap();
301 let paths = Path::try_from(r#"["level1", 1, "hello", 1]"#).unwrap();
302
303 assert_eq!(
304 json.route_get(&paths).unwrap().unwrap().to_string(),
305 r#"[7,8]"#
306 );
307 }
308}