1 use crate::error::Error;
2 use crate::formatter::RedisJsonFormatter;
3 use crate::manager::err_msg_json_path_doesnt_exist_with_param;
4 use crate::manager::{err_msg_json_expected, err_msg_json_path_doesnt_exist_with_param_or};
5 use crate::manager::{AddUpdateInfo, Manager, ReadHolder, SetUpdateInfo, UpdateInfo, WriteHolder};
6 use crate::nodevisitor::{StaticPathElement, StaticPathParser, VisitStatus};
7 use crate::redisjson::{normalize_arr_indices, Format, Path};
8 use jsonpath_lib::select::select_value::{SelectValue, SelectValueType};
9 use jsonpath_lib::select::Selector;
10 use redis_module::{Context, RedisValue};
11 use redis_module::{NextArg, RedisError, RedisResult, RedisString, REDIS_OK};
12 use std::cmp::Ordering;
13 
14 use crate::redisjson::SetOptions;
15 
16 use serde_json::{Number, Value};
17 
18 use itertools::FoldWhile::{Continue, Done};
19 use itertools::{EitherOrBoth, Itertools};
20 use serde::{Serialize, Serializer};
21 use std::collections::HashMap;
22 
23 const JSON_ROOT_PATH: &str = "$";
24 const JSON_ROOT_PATH_LEGACY: &str = ".";
25 const CMD_ARG_NOESCAPE: &str = "NOESCAPE";
26 const CMD_ARG_INDENT: &str = "INDENT";
27 const CMD_ARG_NEWLINE: &str = "NEWLINE";
28 const CMD_ARG_SPACE: &str = "SPACE";
29 const CMD_ARG_FORMAT: &str = "FORMAT";
30 
31 // Compile time evaluation of the max len() of all elements of the array
max_strlen(arr: &[&str]) -> usize32 const fn max_strlen(arr: &[&str]) -> usize {
33     let mut max_strlen = 0;
34     let arr_len = arr.len();
35     if arr_len < 1 {
36         return max_strlen;
37     }
38     let mut pos = 0;
39     while pos < arr_len {
40         let curr_strlen = arr[pos].len();
41         if max_strlen < curr_strlen {
42             max_strlen = curr_strlen;
43         }
44         pos += 1;
45     }
46     max_strlen
47 }
48 
49 // We use this constant to further optimize json_get command, by calculating the max subcommand length
50 // Any subcommand added to JSON.GET should be included on the following array
51 const JSONGET_SUBCOMMANDS_MAXSTRLEN: usize = max_strlen(&[
52     CMD_ARG_NOESCAPE,
53     CMD_ARG_INDENT,
54     CMD_ARG_NEWLINE,
55     CMD_ARG_SPACE,
56     CMD_ARG_FORMAT,
57 ]);
58 
59 enum Values<'a, V: SelectValue> {
60     Single(&'a V),
61     Multi(Vec<&'a V>),
62 }
63 
64 impl<'a, V: SelectValue> Serialize for Values<'a, V> {
serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer,65     fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
66     where
67         S: Serializer,
68     {
69         match self {
70             Values::Single(v) => v.serialize(serializer),
71             Values::Multi(v) => v.serialize(serializer),
72         }
73     }
74 }
75 
76 pub struct KeyValue<'a, V: SelectValue> {
77     val: &'a V,
78 }
79 
80 impl<'a, V: SelectValue> KeyValue<'a, V> {
new(v: &'a V) -> KeyValue<'a, V>81     pub fn new(v: &'a V) -> KeyValue<'a, V> {
82         KeyValue { val: v }
83     }
84 
get_first<'b>(&'a self, path: &'b str) -> Result<&'a V, Error>85     fn get_first<'b>(&'a self, path: &'b str) -> Result<&'a V, Error> {
86         let results = self.get_values(path)?;
87         match results.first() {
88             Some(s) => Ok(s),
89             None => Err(err_msg_json_path_doesnt_exist_with_param(path)
90                 .as_str()
91                 .into()),
92         }
93     }
94 
resp_serialize(&'a self, path: Path) -> RedisResult95     fn resp_serialize(&'a self, path: Path) -> RedisResult {
96         if path.is_legacy() {
97             let v = self.get_first(path.get_path())?;
98             Ok(self.resp_serialize_inner(v))
99         } else {
100             Ok(self
101                 .get_values(path.get_path())?
102                 .iter()
103                 .map(|v| self.resp_serialize_inner(v))
104                 .collect::<Vec<RedisValue>>()
105                 .into())
106         }
107     }
108 
resp_serialize_inner(&'a self, v: &V) -> RedisValue109     fn resp_serialize_inner(&'a self, v: &V) -> RedisValue {
110         match v.get_type() {
111             SelectValueType::Null => RedisValue::Null,
112 
113             SelectValueType::Bool => {
114                 let bool_val = v.get_bool();
115                 match bool_val {
116                     true => RedisValue::SimpleString("true".to_string()),
117                     false => RedisValue::SimpleString("false".to_string()),
118                 }
119             }
120 
121             SelectValueType::Long => RedisValue::Integer(v.get_long()),
122 
123             SelectValueType::Double => RedisValue::Float(v.get_double()),
124 
125             SelectValueType::String => RedisValue::BulkString(v.get_str()),
126 
127             SelectValueType::Array => {
128                 let mut res: Vec<RedisValue> = Vec::with_capacity(v.len().unwrap() + 1);
129                 res.push(RedisValue::SimpleStringStatic("["));
130                 v.values()
131                     .unwrap()
132                     .for_each(|v| res.push(self.resp_serialize_inner(v)));
133                 RedisValue::Array(res)
134             }
135 
136             SelectValueType::Object => {
137                 let mut res: Vec<RedisValue> = Vec::with_capacity(v.len().unwrap() + 1);
138                 res.push(RedisValue::SimpleStringStatic("{"));
139                 for (k, v) in v.items().unwrap() {
140                     res.push(RedisValue::BulkString(k.to_string()));
141                     res.push(self.resp_serialize_inner(v));
142                 }
143                 RedisValue::Array(res)
144             }
145         }
146     }
147 
get_values<'b>(&'a self, path: &'b str) -> Result<Vec<&'a V>, Error>148     fn get_values<'b>(&'a self, path: &'b str) -> Result<Vec<&'a V>, Error> {
149         let mut selector = Selector::new();
150         selector.str_path(path)?;
151         selector.value(self.val);
152         let results = selector.select()?;
153         Ok(results)
154     }
155 
serialize_object<O: Serialize>( o: &O, indent: Option<&str>, newline: Option<&str>, space: Option<&str>, ) -> String156     pub fn serialize_object<O: Serialize>(
157         o: &O,
158         indent: Option<&str>,
159         newline: Option<&str>,
160         space: Option<&str>,
161     ) -> String {
162         let formatter = RedisJsonFormatter::new(indent, space, newline);
163 
164         let mut out = serde_json::Serializer::with_formatter(Vec::new(), formatter);
165         o.serialize(&mut out).unwrap();
166         String::from_utf8(out.into_inner()).unwrap()
167     }
168 
to_json_multi( &'a self, paths: &mut Vec<Path>, indent: Option<&str>, newline: Option<&str>, space: Option<&str>, is_legacy: bool, ) -> Result<RedisValue, Error>169     fn to_json_multi(
170         &'a self,
171         paths: &mut Vec<Path>,
172         indent: Option<&str>,
173         newline: Option<&str>,
174         space: Option<&str>,
175         is_legacy: bool,
176     ) -> Result<RedisValue, Error> {
177         // TODO: Creating a temp doc here duplicates memory usage. This can be very memory inefficient.
178         // A better way would be to create a doc of references to the original doc but no current support
179         // in serde_json. I'm going for this implementation anyway because serde_json isn't supposed to be
180         // memory efficient and we're using it anyway. See https://github.com/serde-rs/json/issues/635.
181         let mut missing_path = None;
182         let temp_doc = paths.drain(..).fold(HashMap::new(), |mut acc, path: Path| {
183             let mut selector = Selector::new();
184             selector.value(self.val);
185             if selector.str_path(path.get_path()).is_err() {
186                 return acc;
187             }
188             let value = match selector.select() {
189                 Ok(s) if is_legacy && !s.is_empty() => Some(Values::Single(s[0])),
190                 Ok(s) if !is_legacy => Some(Values::Multi(s)),
191                 _ => None,
192             };
193 
194             if value.is_none() && missing_path.is_none() {
195                 missing_path = Some(path.get_original().to_string());
196             }
197             acc.insert(path.get_original(), value);
198             acc
199         });
200         if let Some(p) = missing_path {
201             return Err(err_msg_json_path_doesnt_exist_with_param(p.as_str()).into());
202         }
203         Ok(Self::serialize_object(&temp_doc, indent, newline, space).into())
204     }
205 
to_json_single( &'a self, path: &str, indent: Option<&str>, newline: Option<&str>, space: Option<&str>, is_legacy: bool, ) -> Result<RedisValue, Error>206     fn to_json_single(
207         &'a self,
208         path: &str,
209         indent: Option<&str>,
210         newline: Option<&str>,
211         space: Option<&str>,
212         is_legacy: bool,
213     ) -> Result<RedisValue, Error> {
214         if is_legacy {
215             Ok(self.to_string_single(path, indent, newline, space)?.into())
216         } else {
217             Ok(self.to_string_multi(path, indent, newline, space)?.into())
218         }
219     }
220 
to_json( &'a self, paths: &mut Vec<Path>, indent: Option<&str>, newline: Option<&str>, space: Option<&str>, format: Format, ) -> Result<RedisValue, Error>221     fn to_json(
222         &'a self,
223         paths: &mut Vec<Path>,
224         indent: Option<&str>,
225         newline: Option<&str>,
226         space: Option<&str>,
227         format: Format,
228     ) -> Result<RedisValue, Error> {
229         if format == Format::BSON {
230             return Err("ERR Soon to come...".into());
231         }
232         let is_legacy = !paths.iter().any(|p| !p.is_legacy());
233         if paths.len() > 1 {
234             self.to_json_multi(paths, indent, newline, space, is_legacy)
235         } else {
236             self.to_json_single(paths[0].get_path(), indent, newline, space, is_legacy)
237         }
238     }
239 
find_add_paths(&mut self, path: &str) -> Result<Vec<UpdateInfo>, Error>240     fn find_add_paths(&mut self, path: &str) -> Result<Vec<UpdateInfo>, Error> {
241         let mut parsed_static_path = StaticPathParser::check(path)?;
242 
243         if parsed_static_path.valid != VisitStatus::Valid {
244             return Err("Err: wrong static path".into());
245         }
246         if parsed_static_path.static_path_elements.len() < 2 {
247             return Err("Err: path must end with object key to set".into());
248         }
249 
250         let last = parsed_static_path.static_path_elements.pop().unwrap();
251 
252         if let StaticPathElement::ObjectKey(key) = last {
253             if let StaticPathElement::Root = parsed_static_path.static_path_elements.last().unwrap()
254             {
255                 // Adding to the root
256                 Ok(vec![UpdateInfo::AUI(AddUpdateInfo {
257                     path: Vec::new(),
258                     key,
259                 })])
260             } else {
261                 // Adding somewhere in existing object, use jsonpath_lib::replace_with
262                 let p = parsed_static_path
263                     .static_path_elements
264                     .iter()
265                     .map(|e| e.to_string())
266                     .collect::<Vec<_>>()
267                     .join("");
268                 let mut selector = Selector::default();
269                 if let Err(e) = selector.str_path(&p) {
270                     return Err(e.into());
271                 }
272                 selector.value(self.val);
273                 let mut res = selector.select_with_paths(|_| true)?;
274                 Ok(res
275                     .drain(..)
276                     .map(|v| {
277                         UpdateInfo::AUI(AddUpdateInfo {
278                             path: v,
279                             key: key.to_string(),
280                         })
281                     })
282                     .collect())
283             }
284         } else if let StaticPathElement::ArrayIndex(_) = last {
285             // if we reach here with array path we must be out of range
286             // otherwise the path would be valid to be set and we would not
287             // have reached here!!
288             Err("ERR array index out of range".into())
289         } else {
290             Err("ERR path not an object or array".into())
291         }
292     }
293 
find_paths( &mut self, path: &str, option: &SetOptions, ) -> Result<Vec<UpdateInfo>, Error>294     pub fn find_paths(
295         &mut self,
296         path: &str,
297         option: &SetOptions,
298     ) -> Result<Vec<UpdateInfo>, Error> {
299         if SetOptions::NotExists != *option {
300             let mut selector = Selector::default();
301             let mut res = selector
302                 .str_path(path)?
303                 .value(self.val)
304                 .select_with_paths(|_| true)?;
305             if !res.is_empty() {
306                 return Ok(res
307                     .drain(..)
308                     .map(|v| UpdateInfo::SUI(SetUpdateInfo { path: v }))
309                     .collect());
310             }
311         }
312         if SetOptions::AlreadyExists != *option {
313             self.find_add_paths(path)
314         } else {
315             Ok(Vec::new()) // empty vector means no updates
316         }
317     }
318 
serialize(results: &V, format: Format) -> Result<String, Error>319     pub fn serialize(results: &V, format: Format) -> Result<String, Error> {
320         let res = match format {
321             Format::JSON => serde_json::to_string(results)?,
322             Format::BSON => return Err("ERR Soon to come...".into()), //results.into() as Bson,
323         };
324         Ok(res)
325     }
326 
to_string(&self, path: &str, format: Format) -> Result<String, Error>327     pub fn to_string(&self, path: &str, format: Format) -> Result<String, Error> {
328         let results = self.get_first(path)?;
329         Self::serialize(results, format)
330     }
331 
to_string_single( &self, path: &str, indent: Option<&str>, newline: Option<&str>, space: Option<&str>, ) -> Result<String, Error>332     pub fn to_string_single(
333         &self,
334         path: &str,
335         indent: Option<&str>,
336         newline: Option<&str>,
337         space: Option<&str>,
338     ) -> Result<String, Error> {
339         let result = self.get_first(path)?;
340         Ok(Self::serialize_object(&result, indent, newline, space))
341     }
342 
to_string_multi( &self, path: &str, indent: Option<&str>, newline: Option<&str>, space: Option<&str>, ) -> Result<String, Error>343     pub fn to_string_multi(
344         &self,
345         path: &str,
346         indent: Option<&str>,
347         newline: Option<&str>,
348         space: Option<&str>,
349     ) -> Result<String, Error> {
350         let results = self.get_values(path)?;
351         Ok(Self::serialize_object(&results, indent, newline, space))
352     }
353 
get_type(&self, path: &str) -> Result<String, Error>354     pub fn get_type(&self, path: &str) -> Result<String, Error> {
355         let s = Self::value_name(self.get_first(path)?);
356         Ok(s.to_string())
357     }
358 
value_name(value: &V) -> &str359     pub fn value_name(value: &V) -> &str {
360         match value.get_type() {
361             SelectValueType::Null => "null",
362             SelectValueType::Bool => "boolean",
363             SelectValueType::Long => "integer",
364             SelectValueType::Double => "number",
365             SelectValueType::String => "string",
366             SelectValueType::Array => "array",
367             SelectValueType::Object => "object",
368         }
369     }
370 
str_len(&self, path: &str) -> Result<usize, Error>371     pub fn str_len(&self, path: &str) -> Result<usize, Error> {
372         let first = self.get_first(path)?;
373         match first.get_type() {
374             SelectValueType::String => Ok(first.get_str().len()),
375             _ => Err(
376                 err_msg_json_expected("string", self.get_type(path).unwrap().as_str())
377                     .as_str()
378                     .into(),
379             ),
380         }
381     }
382 
arr_len(&self, path: &str) -> Result<usize, Error>383     pub fn arr_len(&self, path: &str) -> Result<usize, Error> {
384         let first = self.get_first(path)?;
385         match first.get_type() {
386             SelectValueType::Array => Ok(first.len().unwrap()),
387             _ => Err(
388                 err_msg_json_expected("array", self.get_type(path).unwrap().as_str())
389                     .as_str()
390                     .into(),
391             ),
392         }
393     }
394 
obj_len(&self, path: &str) -> Result<ObjectLen, Error>395     pub fn obj_len(&self, path: &str) -> Result<ObjectLen, Error> {
396         match self.get_first(path) {
397             Ok(first) => match first.get_type() {
398                 SelectValueType::Object => Ok(ObjectLen::Len(first.len().unwrap())),
399                 _ => Err(
400                     err_msg_json_expected("object", self.get_type(path).unwrap().as_str())
401                         .as_str()
402                         .into(),
403                 ),
404             },
405             _ => Ok(ObjectLen::NoneExisting),
406         }
407     }
408 
is_equal<T1: SelectValue, T2: SelectValue>(&self, a: &T1, b: &T2) -> bool409     pub fn is_equal<T1: SelectValue, T2: SelectValue>(&self, a: &T1, b: &T2) -> bool {
410         match (a.get_type(), b.get_type()) {
411             (SelectValueType::Null, SelectValueType::Null) => true,
412             (SelectValueType::Bool, SelectValueType::Bool) => a.get_bool() == b.get_bool(),
413             (SelectValueType::Long, SelectValueType::Long) => a.get_long() == b.get_long(),
414             (SelectValueType::Double, SelectValueType::Double) => a.get_double() == b.get_double(),
415             (SelectValueType::String, SelectValueType::String) => a.get_str() == b.get_str(),
416             (SelectValueType::Array, SelectValueType::Array) => {
417                 if a.len().unwrap() != b.len().unwrap() {
418                     false
419                 } else {
420                     for (i, e) in a.values().unwrap().into_iter().enumerate() {
421                         if !self.is_equal(e, b.get_index(i).unwrap()) {
422                             return false;
423                         }
424                     }
425                     true
426                 }
427             }
428             (SelectValueType::Object, SelectValueType::Object) => {
429                 if a.len().unwrap() != b.len().unwrap() {
430                     false
431                 } else {
432                     for k in a.keys().unwrap() {
433                         let temp1 = a.get_key(k);
434                         let temp2 = b.get_key(k);
435                         match (temp1, temp2) {
436                             (Some(a1), Some(b1)) => {
437                                 if !self.is_equal(a1, b1) {
438                                     return false;
439                                 }
440                             }
441                             (_, _) => return false,
442                         }
443                     }
444                     true
445                 }
446             }
447             (_, _) => false,
448         }
449     }
450 
arr_index( &self, path: &str, scalar_value: Value, start: i64, end: i64, ) -> Result<RedisValue, Error>451     pub fn arr_index(
452         &self,
453         path: &str,
454         scalar_value: Value,
455         start: i64,
456         end: i64,
457     ) -> Result<RedisValue, Error> {
458         let res = self
459             .get_values(path)?
460             .iter()
461             .map(|value| {
462                 self.arr_first_index_single(value, &scalar_value, start, end)
463                     .into()
464             })
465             .collect::<Vec<RedisValue>>();
466         Ok(res.into())
467     }
468 
arr_index_legacy( &self, path: &str, scalar_value: Value, start: i64, end: i64, ) -> Result<RedisValue, Error>469     pub fn arr_index_legacy(
470         &self,
471         path: &str,
472         scalar_value: Value,
473         start: i64,
474         end: i64,
475     ) -> Result<RedisValue, Error> {
476         let arr = self.get_first(path)?;
477         match self.arr_first_index_single(arr, &scalar_value, start, end) {
478             FoundIndex::NotArray => Err(Error::from(err_msg_json_expected(
479                 "array",
480                 self.get_type(path).unwrap().as_str(),
481             ))),
482             i => Ok(i.into()),
483         }
484     }
485 
486     /// Returns first array index of `v` in `arr`, or NotFound if not found in `arr`, or NotArray if `arr` is not an array
arr_first_index_single(&self, arr: &V, v: &Value, start: i64, end: i64) -> FoundIndex487     fn arr_first_index_single(&self, arr: &V, v: &Value, start: i64, end: i64) -> FoundIndex {
488         if !arr.is_array() {
489             return FoundIndex::NotArray;
490         }
491 
492         let len = arr.len().unwrap() as i64;
493         if len == 0 {
494             return FoundIndex::NotFound;
495         }
496         // end=0 means INFINITY to support backward with RedisJSON
497         let (start, end) = normalize_arr_indices(start, end, len);
498 
499         if end < start {
500             // don't search at all
501             return FoundIndex::NotFound;
502         }
503 
504         for index in start..end {
505             if self.is_equal(arr.get_index(index as usize).unwrap(), v) {
506                 return FoundIndex::Index(index);
507             }
508         }
509 
510         FoundIndex::NotFound
511     }
512 
obj_keys(&self, path: &str) -> Result<Box<dyn Iterator<Item = &'_ str> + '_>, Error>513     pub fn obj_keys(&self, path: &str) -> Result<Box<dyn Iterator<Item = &'_ str> + '_>, Error> {
514         self.get_first(path)?.keys().ok_or_else(|| {
515             err_msg_json_expected("object", self.get_type(path).unwrap().as_str())
516                 .as_str()
517                 .into()
518         })
519     }
520 }
521 
command_json_get<M: Manager>( manager: M, ctx: &Context, args: Vec<RedisString>, ) -> RedisResult522 pub fn command_json_get<M: Manager>(
523     manager: M,
524     ctx: &Context,
525     args: Vec<RedisString>,
526 ) -> RedisResult {
527     let mut args = args.into_iter().skip(1);
528     let key = args.next_arg()?;
529 
530     // Set Capcity to 1 assumiung the common case has one path
531     let mut paths: Vec<Path> = Vec::with_capacity(1);
532     let mut format = Format::JSON;
533     let mut indent = None;
534     let mut space = None;
535     let mut newline = None;
536     while let Ok(arg) = args.next_str() {
537         match arg {
538             // fast way to consider arg a path by using the max length of all possible subcommands
539             // See #390 for the comparison of this function with/without this optimization
540             arg if arg.len() > JSONGET_SUBCOMMANDS_MAXSTRLEN => paths.push(Path::new(arg)),
541             arg if arg.eq_ignore_ascii_case(CMD_ARG_INDENT) => indent = Some(args.next_str()?),
542             arg if arg.eq_ignore_ascii_case(CMD_ARG_NEWLINE) => newline = Some(args.next_str()?),
543             arg if arg.eq_ignore_ascii_case(CMD_ARG_SPACE) => space = Some(args.next_str()?),
544             // Silently ignore. Compatibility with ReJSON v1.0 which has this option. See #168 TODO add support
545             arg if arg.eq_ignore_ascii_case(CMD_ARG_NOESCAPE) => continue,
546             arg if arg.eq_ignore_ascii_case(CMD_ARG_FORMAT) => {
547                 format = Format::from_str(args.next_str()?)?
548             }
549             _ => paths.push(Path::new(arg)),
550         };
551     }
552 
553     // path is optional -> no path found we use root "$"
554     if paths.is_empty() {
555         paths.push(Path::new(JSON_ROOT_PATH_LEGACY));
556     }
557 
558     let key = manager.open_key_read(ctx, &key)?;
559     let value = match key.get_value()? {
560         Some(doc) => KeyValue::new(doc).to_json(&mut paths, indent, newline, space, format)?,
561         None => RedisValue::Null,
562     };
563 
564     Ok(value)
565 }
566 
command_json_set<M: Manager>( manager: M, ctx: &Context, args: Vec<RedisString>, ) -> RedisResult567 pub fn command_json_set<M: Manager>(
568     manager: M,
569     ctx: &Context,
570     args: Vec<RedisString>,
571 ) -> RedisResult {
572     let mut args = args.into_iter().skip(1);
573 
574     let key = args.next_arg()?;
575     let path = Path::new(args.next_str()?);
576     let value = args.next_str()?;
577 
578     let mut format = Format::JSON;
579     let mut set_option = SetOptions::None;
580 
581     while let Some(s) = args.next() {
582         match s.try_as_str()? {
583             arg if arg.eq_ignore_ascii_case("NX") && set_option == SetOptions::None => {
584                 set_option = SetOptions::NotExists
585             }
586             arg if arg.eq_ignore_ascii_case("XX") && set_option == SetOptions::None => {
587                 set_option = SetOptions::AlreadyExists
588             }
589             arg if arg.eq_ignore_ascii_case("FORMAT") => {
590                 format = Format::from_str(args.next_str()?)?;
591             }
592             _ => return Err(RedisError::Str("ERR syntax error")),
593         };
594     }
595 
596     let mut redis_key = manager.open_key_write(ctx, key)?;
597     let current = redis_key.get_value()?;
598 
599     let val = manager.from_str(value, format)?;
600 
601     match (current, set_option) {
602         (Some(ref mut doc), ref op) => {
603             if path.get_path() == JSON_ROOT_PATH {
604                 if *op != SetOptions::NotExists {
605                     redis_key.set_value(Vec::new(), val)?;
606                     redis_key.apply_changes(ctx, "json.set")?;
607                     REDIS_OK
608                 } else {
609                     Ok(RedisValue::Null)
610                 }
611             } else {
612                 let mut update_info = KeyValue::new(*doc).find_paths(path.get_path(), op)?;
613                 if !update_info.is_empty() {
614                     let mut res = false;
615                     if update_info.len() == 1 {
616                         res = match update_info.pop().unwrap() {
617                             UpdateInfo::SUI(sui) => redis_key.set_value(sui.path, val)?,
618                             UpdateInfo::AUI(aui) => redis_key.dict_add(aui.path, &aui.key, val)?,
619                         }
620                     } else {
621                         for ui in update_info {
622                             res = match ui {
623                                 UpdateInfo::SUI(sui) => {
624                                     redis_key.set_value(sui.path, val.clone())?
625                                 }
626                                 UpdateInfo::AUI(aui) => {
627                                     redis_key.dict_add(aui.path, &aui.key, val.clone())?
628                                 }
629                             }
630                         }
631                     }
632                     if res {
633                         redis_key.apply_changes(ctx, "json.set")?;
634                         REDIS_OK
635                     } else {
636                         Ok(RedisValue::Null)
637                     }
638                 } else {
639                     Ok(RedisValue::Null)
640                 }
641             }
642         }
643         (None, SetOptions::AlreadyExists) => Ok(RedisValue::Null),
644         (None, _) => {
645             if path.get_path() == JSON_ROOT_PATH {
646                 redis_key.set_value(Vec::new(), val)?;
647                 redis_key.apply_changes(ctx, "json.set")?;
648                 REDIS_OK
649             } else {
650                 Err(RedisError::Str(
651                     "ERR new objects must be created at the root",
652                 ))
653             }
654         }
655     }
656 }
657 
find_paths<T: SelectValue, F: FnMut(&T) -> bool>( path: &str, doc: &T, f: F, ) -> Result<Vec<Vec<String>>, RedisError>658 fn find_paths<T: SelectValue, F: FnMut(&T) -> bool>(
659     path: &str,
660     doc: &T,
661     f: F,
662 ) -> Result<Vec<Vec<String>>, RedisError> {
663     Ok(Selector::default()
664         .str_path(path)?
665         .value(doc)
666         .select_with_paths(f)?)
667 }
668 
669 /// Returns tuples of Value and its concrete path which match the given `path`
get_all_values_and_paths<'a, T: SelectValue>( path: &str, doc: &'a T, ) -> Result<Vec<(&'a T, Vec<String>)>, RedisError>670 fn get_all_values_and_paths<'a, T: SelectValue>(
671     path: &str,
672     doc: &'a T,
673 ) -> Result<Vec<(&'a T, Vec<String>)>, RedisError> {
674     Ok(Selector::default()
675         .str_path(path)?
676         .value(doc)
677         .select_values_with_paths()?)
678 }
679 
680 /// Returns a Vec of paths with `None` for Values that do not match the filter
filter_paths<T, F>( mut values_and_paths: Vec<(&T, Vec<String>)>, f: F, ) -> Vec<Option<Vec<String>>> where F: Fn(&T) -> bool,681 fn filter_paths<T, F>(
682     mut values_and_paths: Vec<(&T, Vec<String>)>,
683     f: F,
684 ) -> Vec<Option<Vec<String>>>
685 where
686     F: Fn(&T) -> bool,
687 {
688     values_and_paths
689         .drain(..)
690         .map(|(v, p)| match f(v) {
691             true => Some(p),
692             _ => None,
693         })
694         .collect::<Vec<Option<Vec<String>>>>()
695 }
696 
697 /// Returns a Vec of Values with `None` for Values that do not match the filter
filter_values<T, F>(mut values_and_paths: Vec<(&T, Vec<String>)>, f: F) -> Vec<Option<&T>> where F: Fn(&T) -> bool,698 fn filter_values<T, F>(mut values_and_paths: Vec<(&T, Vec<String>)>, f: F) -> Vec<Option<&T>>
699 where
700     F: Fn(&T) -> bool,
701 {
702     values_and_paths
703         .drain(..)
704         .map(|(v, _)| match f(v) {
705             true => Some(v),
706             _ => None,
707         })
708         .collect::<Vec<Option<&T>>>()
709 }
710 
find_all_paths<T: SelectValue, F: FnMut(&T) -> bool>( path: &str, doc: &T, f: F, ) -> Result<Vec<Option<Vec<String>>>, RedisError> where F: Fn(&T) -> bool,711 fn find_all_paths<T: SelectValue, F: FnMut(&T) -> bool>(
712     path: &str,
713     doc: &T,
714     f: F,
715 ) -> Result<Vec<Option<Vec<String>>>, RedisError>
716 where
717     F: Fn(&T) -> bool,
718 {
719     let res = get_all_values_and_paths(path, doc)?;
720     match res.is_empty() {
721         false => Ok(filter_paths(res, f)),
722         _ => Ok(vec![]),
723     }
724 }
725 
find_all_values<'a, T: SelectValue, F: FnMut(&T) -> bool>( path: &str, doc: &'a T, f: F, ) -> Result<Vec<Option<&'a T>>, RedisError> where F: Fn(&T) -> bool,726 fn find_all_values<'a, T: SelectValue, F: FnMut(&T) -> bool>(
727     path: &str,
728     doc: &'a T,
729     f: F,
730 ) -> Result<Vec<Option<&'a T>>, RedisError>
731 where
732     F: Fn(&T) -> bool,
733 {
734     let res = get_all_values_and_paths(path, doc)?;
735     match res.is_empty() {
736         false => Ok(filter_values(res, f)),
737         _ => Ok(vec![]),
738     }
739 }
740 
to_json_value<T>(values: Vec<Option<T>>, none_value: Value) -> Vec<Value> where Value: From<T>,741 fn to_json_value<T>(values: Vec<Option<T>>, none_value: Value) -> Vec<Value>
742 where
743     Value: From<T>,
744 {
745     values
746         .into_iter()
747         .map(|n| match n {
748             Some(t) => t.into(),
749             _ => none_value.clone(),
750         })
751         .collect::<Vec<Value>>()
752 }
753 
754 /// Sort the paths so higher indices precede lower indices on the same array,
755 /// And if one path is a sub-path of the other, then paths with shallower hierarchy (closer to the top-level) precedes paths with deeper hierarchy
prepare_paths_for_deletion(paths: &mut Vec<Vec<String>>)756 fn prepare_paths_for_deletion(paths: &mut Vec<Vec<String>>) {
757     paths.sort_by(|v1, v2| {
758         v1.iter()
759             .zip_longest(v2.iter())
760             .fold_while(Ordering::Equal, |_acc, v| {
761                 match v {
762                     EitherOrBoth::Left(_) => Done(Ordering::Greater), // Shorter paths before longer paths
763                     EitherOrBoth::Right(_) => Done(Ordering::Less), // Shorter paths before longer paths
764                     EitherOrBoth::Both(p1, p2) => {
765                         let i1 = p1.parse::<usize>();
766                         let i2 = p2.parse::<usize>();
767                         match (i1, i2) {
768                             (Err(_), Err(_)) => match p1.cmp(p2) {
769                                 // String compare
770                                 Ordering::Less => Done(Ordering::Less),
771                                 Ordering::Equal => Continue(Ordering::Equal),
772                                 Ordering::Greater => Done(Ordering::Greater),
773                             },
774                             (Ok(_), Err(_)) => Done(Ordering::Greater), //String before Numeric
775                             (Err(_), Ok(_)) => Done(Ordering::Less),    //String before Numeric
776                             (Ok(i1), Ok(i2)) => {
777                                 // Numeric compare - higher indices before lower ones
778                                 if i1 < i2 {
779                                     Done(Ordering::Greater)
780                                 } else if i2 < i1 {
781                                     Done(Ordering::Less)
782                                 } else {
783                                     Continue(Ordering::Equal)
784                                 }
785                             }
786                         }
787                     }
788                 }
789             })
790             .into_inner()
791     });
792 }
793 
command_json_del<M: Manager>( manager: M, ctx: &Context, args: Vec<RedisString>, ) -> RedisResult794 pub fn command_json_del<M: Manager>(
795     manager: M,
796     ctx: &Context,
797     args: Vec<RedisString>,
798 ) -> RedisResult {
799     let mut args = args.into_iter().skip(1);
800 
801     let key = args.next_arg()?;
802     let path = match args.next() {
803         None => Path::new(JSON_ROOT_PATH_LEGACY),
804         Some(s) => Path::new(s.try_as_str()?),
805     };
806 
807     let mut redis_key = manager.open_key_write(ctx, key)?;
808     let deleted = match redis_key.get_value()? {
809         Some(doc) => {
810             let res = if path.get_path() == JSON_ROOT_PATH {
811                 redis_key.delete()?;
812                 1
813             } else {
814                 let mut paths = find_paths(path.get_path(), doc, |_| true)?;
815                 prepare_paths_for_deletion(&mut paths);
816                 let mut changed = 0;
817                 for p in paths {
818                     if redis_key.delete_path(p)? {
819                         changed += 1;
820                     }
821                 }
822                 changed
823             };
824             if res > 0 {
825                 redis_key.apply_changes(ctx, "json.del")?;
826             }
827             res
828         }
829         None => 0,
830     };
831     Ok((deleted as i64).into())
832 }
833 
command_json_mget<M: Manager>( manager: M, ctx: &Context, args: Vec<RedisString>, ) -> RedisResult834 pub fn command_json_mget<M: Manager>(
835     manager: M,
836     ctx: &Context,
837     args: Vec<RedisString>,
838 ) -> RedisResult {
839     if args.len() < 3 {
840         return Err(RedisError::WrongArity);
841     }
842 
843     args.last().ok_or(RedisError::WrongArity).and_then(|path| {
844         let path = Path::new(path.try_as_str()?);
845         let keys = &args[1..args.len() - 1];
846 
847         let to_string =
848             |doc: &M::V| KeyValue::new(doc).to_string_multi(path.get_path(), None, None, None);
849         let to_string_legacy =
850             |doc: &M::V| KeyValue::new(doc).to_string_single(path.get_path(), None, None, None);
851         let is_legacy = path.is_legacy();
852 
853         let results: Result<Vec<RedisValue>, RedisError> = keys
854             .iter()
855             .map(|key| {
856                 manager
857                     .open_key_read(ctx, key)?
858                     .get_value()?
859                     .map(|doc| {
860                         if !is_legacy {
861                             to_string(doc)
862                         } else {
863                             to_string_legacy(doc)
864                         }
865                     })
866                     .transpose()
867                     .map_or_else(|_| Ok(RedisValue::Null), |v| Ok(v.into()))
868             })
869             .collect();
870 
871         Ok(results?.into())
872     })
873 }
874 
command_json_type<M: Manager>( manager: M, ctx: &Context, args: Vec<RedisString>, ) -> RedisResult875 pub fn command_json_type<M: Manager>(
876     manager: M,
877     ctx: &Context,
878     args: Vec<RedisString>,
879 ) -> RedisResult {
880     let mut args = args.into_iter().skip(1);
881     let key = args.next_arg()?;
882     let path = Path::new(args.next_str().unwrap_or(JSON_ROOT_PATH_LEGACY));
883 
884     let key = manager.open_key_read(ctx, &key)?;
885 
886     if !path.is_legacy() {
887         json_type::<M>(&key, path.get_path())
888     } else {
889         json_type_legacy::<M>(&key, path.get_path())
890     }
891 }
892 
json_type<M>(redis_key: &M::ReadHolder, path: &str) -> RedisResult where M: Manager,893 fn json_type<M>(redis_key: &M::ReadHolder, path: &str) -> RedisResult
894 where
895     M: Manager,
896 {
897     let root = redis_key.get_value()?;
898     let res = match root {
899         Some(root) => KeyValue::new(root)
900             .get_values(path)?
901             .iter()
902             .map(|v| (KeyValue::value_name(*v)).into())
903             .collect::<Vec<RedisValue>>()
904             .into(),
905         None => RedisValue::Null,
906     };
907     Ok(res)
908 }
909 
json_type_legacy<M>(redis_key: &M::ReadHolder, path: &str) -> RedisResult where M: Manager,910 fn json_type_legacy<M>(redis_key: &M::ReadHolder, path: &str) -> RedisResult
911 where
912     M: Manager,
913 {
914     let value = redis_key.get_value()?.map_or_else(
915         || RedisValue::Null,
916         |doc| match KeyValue::new(doc).get_type(path) {
917             Ok(s) => s.into(),
918             Err(_) => RedisValue::Null,
919         },
920     );
921 
922     Ok(value)
923 }
924 
925 enum NumOp {
926     Incr,
927     Mult,
928     Pow,
929 }
930 
command_json_num_op<M>( manager: M, ctx: &Context, args: Vec<RedisString>, cmd: &str, op: NumOp, ) -> RedisResult where M: Manager,931 fn command_json_num_op<M>(
932     manager: M,
933     ctx: &Context,
934     args: Vec<RedisString>,
935     cmd: &str,
936     op: NumOp,
937 ) -> RedisResult
938 where
939     M: Manager,
940 {
941     let mut args = args.into_iter().skip(1);
942 
943     let key = args.next_arg()?;
944     let path = Path::new(args.next_str()?);
945     let number = args.next_str()?;
946 
947     let mut redis_key = manager.open_key_write(ctx, key)?;
948 
949     if !path.is_legacy() {
950         json_num_op::<M>(&mut redis_key, ctx, path.get_path(), number, op, cmd)
951     } else {
952         json_num_op_legacy::<M>(&mut redis_key, ctx, path.get_path(), number, op, cmd)
953     }
954 }
955 
json_num_op<M>( redis_key: &mut M::WriteHolder, ctx: &Context, path: &str, number: &str, op: NumOp, cmd: &str, ) -> RedisResult where M: Manager,956 fn json_num_op<M>(
957     redis_key: &mut M::WriteHolder,
958     ctx: &Context,
959     path: &str,
960     number: &str,
961     op: NumOp,
962     cmd: &str,
963 ) -> RedisResult
964 where
965     M: Manager,
966 {
967     let root = redis_key
968         .get_value()?
969         .ok_or_else(RedisError::nonexistent_key)?;
970     let paths = find_all_paths(path, root, |v| match v.get_type() {
971         SelectValueType::Double | SelectValueType::Long => true,
972         _ => false,
973     })?;
974 
975     let mut res = vec![];
976     let mut need_notify = false;
977     for p in paths {
978         res.push(match p {
979             Some(p) => {
980                 need_notify = true;
981                 Some(match op {
982                     NumOp::Incr => redis_key.incr_by(p, number)?,
983                     NumOp::Mult => redis_key.mult_by(p, number)?,
984                     NumOp::Pow => redis_key.pow_by(p, number)?,
985                 })
986             }
987             _ => None,
988         });
989     }
990     if need_notify {
991         redis_key.apply_changes(ctx, cmd)?;
992     }
993 
994     let res = to_json_value::<Number>(res, Value::Null);
995     Ok(KeyValue::<M::V>::serialize_object(&res, None, None, None).into())
996 }
997 
json_num_op_legacy<M>( redis_key: &mut M::WriteHolder, ctx: &Context, path: &str, number: &str, op: NumOp, cmd: &str, ) -> RedisResult where M: Manager,998 fn json_num_op_legacy<M>(
999     redis_key: &mut M::WriteHolder,
1000     ctx: &Context,
1001     path: &str,
1002     number: &str,
1003     op: NumOp,
1004     cmd: &str,
1005 ) -> RedisResult
1006 where
1007     M: Manager,
1008 {
1009     let root = redis_key
1010         .get_value()?
1011         .ok_or_else(RedisError::nonexistent_key)?;
1012     let paths = find_paths(path, root, |v| {
1013         v.get_type() == SelectValueType::Double || v.get_type() == SelectValueType::Long
1014     })?;
1015     if !paths.is_empty() {
1016         let mut res = None;
1017         for p in paths {
1018             res = Some(match op {
1019                 NumOp::Incr => redis_key.incr_by(p, number)?,
1020                 NumOp::Mult => redis_key.mult_by(p, number)?,
1021                 NumOp::Pow => redis_key.pow_by(p, number)?,
1022             });
1023         }
1024         redis_key.apply_changes(ctx, cmd)?;
1025         Ok(res.unwrap().to_string().into())
1026     } else {
1027         Err(RedisError::String(
1028             err_msg_json_path_doesnt_exist_with_param_or(path, "does not contains a number"),
1029         ))
1030     }
1031 }
1032 
command_json_num_incrby<M: Manager>( manager: M, ctx: &Context, args: Vec<RedisString>, ) -> RedisResult1033 pub fn command_json_num_incrby<M: Manager>(
1034     manager: M,
1035     ctx: &Context,
1036     args: Vec<RedisString>,
1037 ) -> RedisResult {
1038     command_json_num_op(manager, ctx, args, "json.numincrby", NumOp::Incr)
1039 }
1040 
command_json_num_multby<M: Manager>( manager: M, ctx: &Context, args: Vec<RedisString>, ) -> RedisResult1041 pub fn command_json_num_multby<M: Manager>(
1042     manager: M,
1043     ctx: &Context,
1044     args: Vec<RedisString>,
1045 ) -> RedisResult {
1046     command_json_num_op(manager, ctx, args, "json.nummultby", NumOp::Mult)
1047 }
1048 
command_json_num_powby<M: Manager>( manager: M, ctx: &Context, args: Vec<RedisString>, ) -> RedisResult1049 pub fn command_json_num_powby<M: Manager>(
1050     manager: M,
1051     ctx: &Context,
1052     args: Vec<RedisString>,
1053 ) -> RedisResult {
1054     command_json_num_op(manager, ctx, args, "json.numpowby", NumOp::Pow)
1055 }
1056 
command_json_bool_toggle<M: Manager>( manager: M, ctx: &Context, args: Vec<RedisString>, ) -> RedisResult1057 pub fn command_json_bool_toggle<M: Manager>(
1058     manager: M,
1059     ctx: &Context,
1060     args: Vec<RedisString>,
1061 ) -> RedisResult {
1062     let mut args = args.into_iter().skip(1);
1063     let key = args.next_arg()?;
1064     let path = Path::new(args.next_str()?);
1065     let mut redis_key = manager.open_key_write(ctx, key)?;
1066 
1067     if !path.is_legacy() {
1068         json_bool_toggle::<M>(&mut redis_key, ctx, path.get_path())
1069     } else {
1070         json_bool_toggle_legacy::<M>(&mut redis_key, ctx, path.get_path())
1071     }
1072 }
1073 
json_bool_toggle<M>(redis_key: &mut M::WriteHolder, ctx: &Context, path: &str) -> RedisResult where M: Manager,1074 fn json_bool_toggle<M>(redis_key: &mut M::WriteHolder, ctx: &Context, path: &str) -> RedisResult
1075 where
1076     M: Manager,
1077 {
1078     let root = redis_key
1079         .get_value()?
1080         .ok_or_else(RedisError::nonexistent_key)?;
1081     let paths = find_all_paths(path, root, |v| v.get_type() == SelectValueType::Bool)?;
1082     let mut res: Vec<RedisValue> = vec![];
1083     let mut need_notify = false;
1084     for p in paths {
1085         res.push(match p {
1086             Some(p) => {
1087                 need_notify = true;
1088                 RedisValue::Integer((redis_key.bool_toggle(p)?).into())
1089             }
1090             None => RedisValue::Null,
1091         });
1092     }
1093     if need_notify {
1094         redis_key.apply_changes(ctx, "json.arrpop")?;
1095     }
1096     Ok(res.into())
1097 }
1098 
json_bool_toggle_legacy<M>( redis_key: &mut M::WriteHolder, ctx: &Context, path: &str, ) -> RedisResult where M: Manager,1099 fn json_bool_toggle_legacy<M>(
1100     redis_key: &mut M::WriteHolder,
1101     ctx: &Context,
1102     path: &str,
1103 ) -> RedisResult
1104 where
1105     M: Manager,
1106 {
1107     let root = redis_key
1108         .get_value()?
1109         .ok_or_else(RedisError::nonexistent_key)?;
1110     let paths = find_paths(path, root, |v| v.get_type() == SelectValueType::Bool)?;
1111     if !paths.is_empty() {
1112         let mut res = false;
1113         for p in paths {
1114             res = redis_key.bool_toggle(p)?;
1115         }
1116         redis_key.apply_changes(ctx, "json.toggle")?;
1117         Ok(res.to_string().into())
1118     } else {
1119         Err(RedisError::String(
1120             err_msg_json_path_doesnt_exist_with_param_or(path, "not a bool"),
1121         ))
1122     }
1123 }
1124 
command_json_str_append<M: Manager>( manager: M, ctx: &Context, args: Vec<RedisString>, ) -> RedisResult1125 pub fn command_json_str_append<M: Manager>(
1126     manager: M,
1127     ctx: &Context,
1128     args: Vec<RedisString>,
1129 ) -> RedisResult {
1130     let mut args = args.into_iter().skip(1);
1131 
1132     let key = args.next_arg()?;
1133     let path_or_json = args.next_str()?;
1134 
1135     let path;
1136     let json;
1137 
1138     // path is optional
1139     if let Ok(val) = args.next_arg() {
1140         path = Path::new(path_or_json);
1141         json = val.try_as_str()?;
1142     } else {
1143         path = Path::new(JSON_ROOT_PATH_LEGACY);
1144         json = path_or_json;
1145     }
1146 
1147     let mut redis_key = manager.open_key_write(ctx, key)?;
1148 
1149     if !path.is_legacy() {
1150         json_str_append::<M>(&mut redis_key, ctx, path.get_path(), json)
1151     } else {
1152         json_str_append_legacy::<M>(&mut redis_key, ctx, path.get_path(), json)
1153     }
1154 }
1155 
json_str_append<M>( redis_key: &mut M::WriteHolder, ctx: &Context, path: &str, json: &str, ) -> RedisResult where M: Manager,1156 fn json_str_append<M>(
1157     redis_key: &mut M::WriteHolder,
1158     ctx: &Context,
1159     path: &str,
1160     json: &str,
1161 ) -> RedisResult
1162 where
1163     M: Manager,
1164 {
1165     let root = redis_key
1166         .get_value()?
1167         .ok_or_else(RedisError::nonexistent_key)?;
1168 
1169     let paths = find_all_paths(path, root, |v| v.get_type() == SelectValueType::String)?;
1170 
1171     let mut res: Vec<RedisValue> = vec![];
1172     let mut need_notify = false;
1173     for p in paths {
1174         res.push(match p {
1175             Some(p) => {
1176                 need_notify = true;
1177                 (redis_key.str_append(p, json.to_string())?).into()
1178             }
1179             _ => RedisValue::Null,
1180         });
1181     }
1182     if need_notify {
1183         redis_key.apply_changes(ctx, "json.strappend")?;
1184     }
1185     Ok(res.into())
1186 }
1187 
json_str_append_legacy<M>( redis_key: &mut M::WriteHolder, ctx: &Context, path: &str, json: &str, ) -> RedisResult where M: Manager,1188 fn json_str_append_legacy<M>(
1189     redis_key: &mut M::WriteHolder,
1190     ctx: &Context,
1191     path: &str,
1192     json: &str,
1193 ) -> RedisResult
1194 where
1195     M: Manager,
1196 {
1197     let root = redis_key
1198         .get_value()?
1199         .ok_or_else(RedisError::nonexistent_key)?;
1200 
1201     let paths = find_paths(path, root, |v| v.get_type() == SelectValueType::String)?;
1202     if !paths.is_empty() {
1203         let mut res = None;
1204         for p in paths {
1205             res = Some(redis_key.str_append(p, json.to_string())?);
1206         }
1207         redis_key.apply_changes(ctx, "json.strappend")?;
1208         Ok(res.unwrap().into())
1209     } else {
1210         Err(RedisError::String(
1211             err_msg_json_path_doesnt_exist_with_param_or(path, "not a string"),
1212         ))
1213     }
1214 }
1215 
command_json_str_len<M: Manager>( manager: M, ctx: &Context, args: Vec<RedisString>, ) -> RedisResult1216 pub fn command_json_str_len<M: Manager>(
1217     manager: M,
1218     ctx: &Context,
1219     args: Vec<RedisString>,
1220 ) -> RedisResult {
1221     let mut args = args.into_iter().skip(1);
1222     let key = args.next_arg()?;
1223     let path = Path::new(args.next_str().unwrap_or(JSON_ROOT_PATH_LEGACY));
1224 
1225     let key = manager.open_key_read(ctx, &key)?;
1226 
1227     if !path.is_legacy() {
1228         json_str_len::<M>(&key, path.get_path())
1229     } else {
1230         json_str_len_legacy::<M>(&key, path.get_path())
1231     }
1232 }
1233 
json_str_len<M>(redis_key: &M::ReadHolder, path: &str) -> RedisResult where M: Manager,1234 fn json_str_len<M>(redis_key: &M::ReadHolder, path: &str) -> RedisResult
1235 where
1236     M: Manager,
1237 {
1238     let root = redis_key
1239         .get_value()?
1240         .ok_or_else(RedisError::nonexistent_key)?;
1241     let values = find_all_values(path, root, |v| v.get_type() == SelectValueType::String)?;
1242     let mut res: Vec<RedisValue> = vec![];
1243     for v in values {
1244         res.push(match v {
1245             Some(v) => (v.get_str().len() as i64).into(),
1246             _ => RedisValue::Null,
1247         });
1248     }
1249     Ok(res.into())
1250 }
1251 
json_str_len_legacy<M>(redis_key: &M::ReadHolder, path: &str) -> RedisResult where M: Manager,1252 fn json_str_len_legacy<M>(redis_key: &M::ReadHolder, path: &str) -> RedisResult
1253 where
1254     M: Manager,
1255 {
1256     match redis_key.get_value()? {
1257         Some(doc) => Ok(RedisValue::Integer(KeyValue::new(doc).str_len(path)? as i64)),
1258         None => Ok(RedisValue::Null),
1259     }
1260 }
1261 
command_json_arr_append<M: Manager>( manager: M, ctx: &Context, args: Vec<RedisString>, ) -> RedisResult1262 pub fn command_json_arr_append<M: Manager>(
1263     manager: M,
1264     ctx: &Context,
1265     args: Vec<RedisString>,
1266 ) -> RedisResult {
1267     let mut args = args.into_iter().skip(1).peekable();
1268 
1269     let key = args.next_arg()?;
1270     let path = Path::new(args.next_str()?);
1271 
1272     // We require at least one JSON item to append
1273     args.peek().ok_or(RedisError::WrongArity)?;
1274 
1275     let args = args.try_fold::<_, _, Result<_, RedisError>>(
1276         Vec::with_capacity(args.len()),
1277         |mut acc, arg| {
1278             let json = arg.try_as_str()?;
1279             acc.push(manager.from_str(json, Format::JSON)?);
1280             Ok(acc)
1281         },
1282     )?;
1283 
1284     let mut redis_key = manager.open_key_write(ctx, key)?;
1285 
1286     if !path.is_legacy() {
1287         json_arr_append::<M>(&mut redis_key, ctx, path.get_path(), args)
1288     } else {
1289         json_arr_append_legacy::<M>(&mut redis_key, ctx, &path, args)
1290     }
1291 }
1292 
json_arr_append_legacy<M>( redis_key: &mut M::WriteHolder, ctx: &Context, path: &Path, args: Vec<M::O>, ) -> RedisResult where M: Manager,1293 fn json_arr_append_legacy<M>(
1294     redis_key: &mut M::WriteHolder,
1295     ctx: &Context,
1296     path: &Path,
1297     args: Vec<M::O>,
1298 ) -> RedisResult
1299 where
1300     M: Manager,
1301 {
1302     let root = redis_key
1303         .get_value()?
1304         .ok_or_else(RedisError::nonexistent_key)?;
1305     let mut paths = find_paths(path.get_path(), root, |v| {
1306         v.get_type() == SelectValueType::Array
1307     })?;
1308     if paths.is_empty() {
1309         Err(RedisError::String(
1310             err_msg_json_path_doesnt_exist_with_param_or(path.get_original(), "not an array"),
1311         ))
1312     } else if paths.len() == 1 {
1313         let res = redis_key.arr_append(paths.pop().unwrap(), args)?;
1314         redis_key.apply_changes(ctx, "json.arrappend")?;
1315         Ok(res.into())
1316     } else {
1317         let mut res = 0;
1318         for p in paths {
1319             res = redis_key.arr_append(p, args.clone())?;
1320         }
1321         redis_key.apply_changes(ctx, "json.arrappend")?;
1322         Ok(res.into())
1323     }
1324 }
1325 
json_arr_append<M>( redis_key: &mut M::WriteHolder, ctx: &Context, path: &str, args: Vec<M::O>, ) -> RedisResult where M: Manager,1326 fn json_arr_append<M>(
1327     redis_key: &mut M::WriteHolder,
1328     ctx: &Context,
1329     path: &str,
1330     args: Vec<M::O>,
1331 ) -> RedisResult
1332 where
1333     M: Manager,
1334 {
1335     let root = redis_key
1336         .get_value()?
1337         .ok_or_else(RedisError::nonexistent_key)?;
1338     let paths = find_all_paths(path, root, |v| v.get_type() == SelectValueType::Array)?;
1339 
1340     let mut res = vec![];
1341     let mut need_notify = false;
1342     for p in paths {
1343         res.push(match p {
1344             Some(p) => {
1345                 need_notify = true;
1346                 (redis_key.arr_append(p, args.clone())? as i64).into()
1347             }
1348             _ => RedisValue::Null,
1349         });
1350     }
1351     if need_notify {
1352         redis_key.apply_changes(ctx, "json.arrappend")?;
1353     }
1354     Ok(res.into())
1355 }
1356 
1357 enum FoundIndex {
1358     Index(i64),
1359     NotFound,
1360     NotArray,
1361 }
1362 
1363 impl From<FoundIndex> for RedisValue {
from(e: FoundIndex) -> Self1364     fn from(e: FoundIndex) -> Self {
1365         match e {
1366             FoundIndex::NotFound => RedisValue::Integer(-1),
1367             FoundIndex::NotArray => RedisValue::Null,
1368             FoundIndex::Index(i) => RedisValue::Integer(i),
1369         }
1370     }
1371 }
1372 
1373 pub enum ObjectLen {
1374     Len(usize),
1375     NoneExisting,
1376     NotObject,
1377 }
1378 
command_json_arr_index<M: Manager>( manager: M, ctx: &Context, args: Vec<RedisString>, ) -> RedisResult1379 pub fn command_json_arr_index<M: Manager>(
1380     manager: M,
1381     ctx: &Context,
1382     args: Vec<RedisString>,
1383 ) -> RedisResult {
1384     let mut args = args.into_iter().skip(1);
1385 
1386     let key = args.next_arg()?;
1387     let path = Path::new(args.next_str()?);
1388     let json_scalar = args.next_str()?;
1389     let start: i64 = args.next().map(|v| v.parse_integer()).unwrap_or(Ok(0))?;
1390     let end: i64 = args.next().map(|v| v.parse_integer()).unwrap_or(Ok(0))?;
1391 
1392     args.done()?; // TODO: Add to other functions as well to terminate args list
1393 
1394     let key = manager.open_key_read(ctx, &key)?;
1395 
1396     let is_legacy = path.is_legacy();
1397     let scalar_value: Value = serde_json::from_str(json_scalar)?;
1398     if !is_legacy && (scalar_value.is_array() || scalar_value.is_object()) {
1399         return Err(RedisError::String(err_msg_json_expected(
1400             "scalar",
1401             json_scalar,
1402         )));
1403     }
1404 
1405     let res = key.get_value()?.map_or_else(
1406         || {
1407             Err(Error::from(err_msg_json_path_doesnt_exist_with_param(
1408                 path.get_original(),
1409             )))
1410         },
1411         |doc| {
1412             if path.is_legacy() {
1413                 KeyValue::new(doc).arr_index_legacy(path.get_path(), scalar_value, start, end)
1414             } else {
1415                 KeyValue::new(doc).arr_index(path.get_path(), scalar_value, start, end)
1416             }
1417         },
1418     )?;
1419 
1420     Ok(res)
1421 }
1422 
command_json_arr_insert<M: Manager>( manager: M, ctx: &Context, args: Vec<RedisString>, ) -> RedisResult1423 pub fn command_json_arr_insert<M: Manager>(
1424     manager: M,
1425     ctx: &Context,
1426     args: Vec<RedisString>,
1427 ) -> RedisResult {
1428     let mut args = args.into_iter().skip(1).peekable();
1429 
1430     let key = args.next_arg()?;
1431     let path = Path::new(args.next_str()?);
1432     let index = args.next_i64()?;
1433 
1434     // We require at least one JSON item to insert
1435     args.peek().ok_or(RedisError::WrongArity)?;
1436     let args = args.try_fold::<_, _, Result<_, RedisError>>(
1437         Vec::with_capacity(args.len()),
1438         |mut acc, arg| {
1439             let json = arg.try_as_str()?;
1440             acc.push(manager.from_str(json, Format::JSON)?);
1441             Ok(acc)
1442         },
1443     )?;
1444     let mut redis_key = manager.open_key_write(ctx, key)?;
1445     if !path.is_legacy() {
1446         json_arr_insert::<M>(&mut redis_key, ctx, path.get_path(), index, args)
1447     } else {
1448         json_arr_insert_legacy::<M>(&mut redis_key, ctx, path.get_path(), index, args)
1449     }
1450 }
1451 
json_arr_insert<M>( redis_key: &mut M::WriteHolder, ctx: &Context, path: &str, index: i64, args: Vec<M::O>, ) -> RedisResult where M: Manager,1452 fn json_arr_insert<M>(
1453     redis_key: &mut M::WriteHolder,
1454     ctx: &Context,
1455     path: &str,
1456     index: i64,
1457     args: Vec<M::O>,
1458 ) -> RedisResult
1459 where
1460     M: Manager,
1461 {
1462     let root = redis_key
1463         .get_value()?
1464         .ok_or_else(RedisError::nonexistent_key)?;
1465 
1466     let paths = find_all_paths(path, root, |v| v.get_type() == SelectValueType::Array)?;
1467 
1468     let mut res: Vec<RedisValue> = vec![];
1469     let mut need_notify = false;
1470     for p in paths {
1471         res.push(match p {
1472             Some(p) => {
1473                 need_notify = true;
1474                 (redis_key.arr_insert(p, &args, index)? as i64).into()
1475             }
1476             _ => RedisValue::Null,
1477         });
1478     }
1479 
1480     if need_notify {
1481         redis_key.apply_changes(ctx, "json.arrinsert")?;
1482     }
1483     Ok(res.into())
1484 }
1485 
json_arr_insert_legacy<M>( redis_key: &mut M::WriteHolder, ctx: &Context, path: &str, index: i64, args: Vec<M::O>, ) -> RedisResult where M: Manager,1486 fn json_arr_insert_legacy<M>(
1487     redis_key: &mut M::WriteHolder,
1488     ctx: &Context,
1489     path: &str,
1490     index: i64,
1491     args: Vec<M::O>,
1492 ) -> RedisResult
1493 where
1494     M: Manager,
1495 {
1496     let root = redis_key
1497         .get_value()?
1498         .ok_or_else(RedisError::nonexistent_key)?;
1499 
1500     let paths = find_paths(path, root, |v| v.get_type() == SelectValueType::Array)?;
1501     if !paths.is_empty() {
1502         let mut res = None;
1503         for p in paths {
1504             res = Some(redis_key.arr_insert(p, &args, index)?);
1505         }
1506         redis_key.apply_changes(ctx, "json.arrinsert")?;
1507         Ok(res.unwrap().into())
1508     } else {
1509         Err(RedisError::String(
1510             err_msg_json_path_doesnt_exist_with_param_or(path, "not an array"),
1511         ))
1512     }
1513 }
1514 
command_json_arr_len<M: Manager>( manager: M, ctx: &Context, args: Vec<RedisString>, ) -> RedisResult1515 pub fn command_json_arr_len<M: Manager>(
1516     manager: M,
1517     ctx: &Context,
1518     args: Vec<RedisString>,
1519 ) -> RedisResult {
1520     let mut args = args.into_iter().skip(1);
1521     let key = args.next_arg()?;
1522     let path = Path::new(args.next_str().unwrap_or(JSON_ROOT_PATH_LEGACY));
1523     let is_legacy = path.is_legacy();
1524     let key = manager.open_key_read(ctx, &key)?;
1525     let root = match key.get_value()? {
1526         Some(k) => k,
1527         None if is_legacy => {
1528             return Ok(RedisValue::Null);
1529         }
1530         None => {
1531             return Err(RedisError::nonexistent_key());
1532         }
1533     };
1534     let values = find_all_values(path.get_path(), root, |v| {
1535         v.get_type() == SelectValueType::Array
1536     })?;
1537     if is_legacy && values.is_empty() {
1538         return Err(RedisError::String(
1539             err_msg_json_path_doesnt_exist_with_param(path.get_original()),
1540         ));
1541     }
1542     let mut res = vec![];
1543     for v in values {
1544         let cur_val: RedisValue = match v {
1545             Some(v) => (v.len().unwrap() as i64).into(),
1546             _ => {
1547                 if !is_legacy {
1548                     RedisValue::Null
1549                 } else {
1550                     return Err(RedisError::String(
1551                         err_msg_json_path_doesnt_exist_with_param_or(
1552                             path.get_original(),
1553                             "not an array",
1554                         ),
1555                     ));
1556                 }
1557             }
1558         };
1559         if !is_legacy {
1560             res.push(cur_val);
1561         } else {
1562             return Ok(cur_val);
1563         }
1564     }
1565     Ok(res.into())
1566 }
1567 
command_json_arr_pop<M: Manager>( manager: M, ctx: &Context, args: Vec<RedisString>, ) -> RedisResult1568 pub fn command_json_arr_pop<M: Manager>(
1569     manager: M,
1570     ctx: &Context,
1571     args: Vec<RedisString>,
1572 ) -> RedisResult {
1573     let mut args = args.into_iter().skip(1);
1574 
1575     let key = args.next_arg()?;
1576 
1577     let (path, index) = match args.next() {
1578         None => (Path::new(JSON_ROOT_PATH_LEGACY), i64::MAX),
1579         Some(s) => {
1580             let path = Path::new(s.try_as_str()?);
1581             let index = args.next_i64().unwrap_or(-1);
1582             (path, index)
1583         }
1584     };
1585 
1586     let mut redis_key = manager.open_key_write(ctx, key)?;
1587     if !path.is_legacy() {
1588         json_arr_pop::<M>(&mut redis_key, ctx, path.get_path(), index)
1589     } else {
1590         json_arr_pop_legacy::<M>(&mut redis_key, ctx, path.get_path(), index)
1591     }
1592 }
1593 
json_arr_pop<M>( redis_key: &mut M::WriteHolder, ctx: &Context, path: &str, index: i64, ) -> RedisResult where M: Manager,1594 fn json_arr_pop<M>(
1595     redis_key: &mut M::WriteHolder,
1596     ctx: &Context,
1597     path: &str,
1598     index: i64,
1599 ) -> RedisResult
1600 where
1601     M: Manager,
1602 {
1603     let root = redis_key
1604         .get_value()?
1605         .ok_or_else(RedisError::nonexistent_key)?;
1606 
1607     let paths = find_all_paths(path, root, |v| v.get_type() == SelectValueType::Array)?;
1608     let mut res: Vec<RedisValue> = vec![];
1609     let mut need_notify = false;
1610     for p in paths {
1611         res.push(match p {
1612             Some(p) => match redis_key.arr_pop(p, index)? {
1613                 Some(v) => {
1614                     need_notify = true;
1615                     v.into()
1616                 }
1617                 _ => RedisValue::Null, // Empty array
1618             },
1619             _ => RedisValue::Null, // Not an array
1620         });
1621     }
1622     if need_notify {
1623         redis_key.apply_changes(ctx, "json.arrpop")?;
1624     }
1625     Ok(res.into())
1626 }
1627 
json_arr_pop_legacy<M>( redis_key: &mut M::WriteHolder, ctx: &Context, path: &str, index: i64, ) -> RedisResult where M: Manager,1628 fn json_arr_pop_legacy<M>(
1629     redis_key: &mut M::WriteHolder,
1630     ctx: &Context,
1631     path: &str,
1632     index: i64,
1633 ) -> RedisResult
1634 where
1635     M: Manager,
1636 {
1637     let root = redis_key
1638         .get_value()?
1639         .ok_or_else(RedisError::nonexistent_key)?;
1640 
1641     let paths = find_paths(path, root, |v| v.get_type() == SelectValueType::Array)?;
1642     if !paths.is_empty() {
1643         let mut res = None;
1644         for p in paths {
1645             res = Some(redis_key.arr_pop(p, index)?);
1646         }
1647         match res.unwrap() {
1648             Some(r) => {
1649                 redis_key.apply_changes(ctx, "json.arrpop")?;
1650                 Ok(r.into())
1651             }
1652             None => Ok(().into()),
1653         }
1654     } else {
1655         Err(RedisError::String(
1656             err_msg_json_path_doesnt_exist_with_param_or(path, "not an array"),
1657         ))
1658     }
1659 }
1660 
command_json_arr_trim<M: Manager>( manager: M, ctx: &Context, args: Vec<RedisString>, ) -> RedisResult1661 pub fn command_json_arr_trim<M: Manager>(
1662     manager: M,
1663     ctx: &Context,
1664     args: Vec<RedisString>,
1665 ) -> RedisResult {
1666     let mut args = args.into_iter().skip(1);
1667 
1668     let key = args.next_arg()?;
1669     let path = Path::new(args.next_str()?);
1670     let start = args.next_i64()?;
1671     let stop = args.next_i64()?;
1672 
1673     let mut redis_key = manager.open_key_write(ctx, key)?;
1674 
1675     if !path.is_legacy() {
1676         json_arr_trim::<M>(&mut redis_key, ctx, path.get_path(), start, stop)
1677     } else {
1678         json_arr_trim_legacy::<M>(&mut redis_key, ctx, path.get_path(), start, stop)
1679     }
1680 }
json_arr_trim<M>( redis_key: &mut M::WriteHolder, ctx: &Context, path: &str, start: i64, stop: i64, ) -> RedisResult where M: Manager,1681 fn json_arr_trim<M>(
1682     redis_key: &mut M::WriteHolder,
1683     ctx: &Context,
1684     path: &str,
1685     start: i64,
1686     stop: i64,
1687 ) -> RedisResult
1688 where
1689     M: Manager,
1690 {
1691     let root = redis_key
1692         .get_value()?
1693         .ok_or_else(RedisError::nonexistent_key)?;
1694 
1695     let paths = find_all_paths(path, root, |v| v.get_type() == SelectValueType::Array)?;
1696     let mut res: Vec<RedisValue> = vec![];
1697     let mut need_notify = false;
1698     for p in paths {
1699         res.push(match p {
1700             Some(p) => {
1701                 need_notify = true;
1702                 (redis_key.arr_trim(p, start, stop)?).into()
1703             }
1704             _ => RedisValue::Null,
1705         });
1706     }
1707     if need_notify {
1708         redis_key.apply_changes(ctx, "json.arrtrim")?;
1709     }
1710     Ok(res.into())
1711 }
1712 
json_arr_trim_legacy<M>( redis_key: &mut M::WriteHolder, ctx: &Context, path: &str, start: i64, stop: i64, ) -> RedisResult where M: Manager,1713 fn json_arr_trim_legacy<M>(
1714     redis_key: &mut M::WriteHolder,
1715     ctx: &Context,
1716     path: &str,
1717     start: i64,
1718     stop: i64,
1719 ) -> RedisResult
1720 where
1721     M: Manager,
1722 {
1723     let root = redis_key
1724         .get_value()?
1725         .ok_or_else(RedisError::nonexistent_key)?;
1726 
1727     let paths = find_paths(path, root, |v| v.get_type() == SelectValueType::Array)?;
1728     if !paths.is_empty() {
1729         let mut res = None;
1730         for p in paths {
1731             res = Some(redis_key.arr_trim(p, start, stop)?);
1732         }
1733         redis_key.apply_changes(ctx, "json.arrtrim")?;
1734         Ok(res.unwrap().into())
1735     } else {
1736         Err(RedisError::String(
1737             err_msg_json_path_doesnt_exist_with_param_or(path, "not an array"),
1738         ))
1739     }
1740 }
1741 
command_json_obj_keys<M: Manager>( manager: M, ctx: &Context, args: Vec<RedisString>, ) -> RedisResult1742 pub fn command_json_obj_keys<M: Manager>(
1743     manager: M,
1744     ctx: &Context,
1745     args: Vec<RedisString>,
1746 ) -> RedisResult {
1747     let mut args = args.into_iter().skip(1);
1748     let key = args.next_arg()?;
1749     let path = Path::new(args.next_str().unwrap_or(JSON_ROOT_PATH_LEGACY));
1750 
1751     let mut key = manager.open_key_read(ctx, &key)?;
1752     if !path.is_legacy() {
1753         json_obj_keys::<M>(&mut key, path.get_path())
1754     } else {
1755         json_obj_keys_legacy::<M>(&mut key, path.get_path())
1756     }
1757 }
1758 
json_obj_keys<M>(redis_key: &mut M::ReadHolder, path: &str) -> RedisResult where M: Manager,1759 fn json_obj_keys<M>(redis_key: &mut M::ReadHolder, path: &str) -> RedisResult
1760 where
1761     M: Manager,
1762 {
1763     let root = redis_key
1764         .get_value()?
1765         .ok_or_else(RedisError::nonexistent_key)?;
1766     let res: RedisValue = {
1767         let values = find_all_values(path, root, |v| v.get_type() == SelectValueType::Object)?;
1768         let mut res: Vec<RedisValue> = vec![];
1769         for v in values {
1770             res.push(match v {
1771                 Some(v) => v.keys().unwrap().collect::<Vec<&str>>().into(),
1772                 _ => RedisValue::Null,
1773             });
1774         }
1775         res.into()
1776     };
1777     Ok(res.into())
1778 }
1779 
json_obj_keys_legacy<M>(redis_key: &mut M::ReadHolder, path: &str) -> RedisResult where M: Manager,1780 fn json_obj_keys_legacy<M>(redis_key: &mut M::ReadHolder, path: &str) -> RedisResult
1781 where
1782     M: Manager,
1783 {
1784     let root = match redis_key.get_value()? {
1785         Some(v) => v,
1786         _ => return Ok(RedisValue::Null),
1787     };
1788     let value = match KeyValue::new(root).get_first(path) {
1789         Ok(v) => match v.get_type() {
1790             SelectValueType::Object => v.keys().unwrap().collect::<Vec<&str>>().into(),
1791             _ => {
1792                 return Err(RedisError::String(
1793                     err_msg_json_path_doesnt_exist_with_param_or(path, "not an object"),
1794                 ))
1795             }
1796         },
1797         _ => RedisValue::Null,
1798     };
1799     Ok(value)
1800 }
1801 
command_json_obj_len<M: Manager>( manager: M, ctx: &Context, args: Vec<RedisString>, ) -> RedisResult1802 pub fn command_json_obj_len<M: Manager>(
1803     manager: M,
1804     ctx: &Context,
1805     args: Vec<RedisString>,
1806 ) -> RedisResult {
1807     let mut args = args.into_iter().skip(1);
1808     let key = args.next_arg()?;
1809     let path = Path::new(args.next_str().unwrap_or(JSON_ROOT_PATH_LEGACY));
1810 
1811     let key = manager.open_key_read(ctx, &key)?;
1812     if !path.is_legacy() {
1813         json_obj_len::<M>(&key, path.get_path())
1814     } else {
1815         json_obj_len_legacy::<M>(&key, path.get_path())
1816     }
1817 }
1818 
json_obj_len<M>(redis_key: &M::ReadHolder, path: &str) -> RedisResult where M: Manager,1819 fn json_obj_len<M>(redis_key: &M::ReadHolder, path: &str) -> RedisResult
1820 where
1821     M: Manager,
1822 {
1823     let root = redis_key.get_value()?;
1824     let res = match root {
1825         Some(root) => find_all_values(path, root, |v| v.get_type() == SelectValueType::Object)?
1826             .iter()
1827             .map(|v| match *v {
1828                 Some(v) => RedisValue::Integer(v.len().unwrap() as i64),
1829                 None => RedisValue::Null,
1830             })
1831             .collect::<Vec<RedisValue>>()
1832             .into(),
1833         None => {
1834             return Err(RedisError::String(
1835                 err_msg_json_path_doesnt_exist_with_param_or(path, "not an object"),
1836             ))
1837         }
1838     };
1839     Ok(res)
1840 }
1841 
json_obj_len_legacy<M>(redis_key: &M::ReadHolder, path: &str) -> RedisResult where M: Manager,1842 fn json_obj_len_legacy<M>(redis_key: &M::ReadHolder, path: &str) -> RedisResult
1843 where
1844     M: Manager,
1845 {
1846     match redis_key.get_value()? {
1847         Some(doc) => match KeyValue::new(doc).obj_len(path)? {
1848             ObjectLen::Len(l) => Ok(RedisValue::Integer(l as i64)),
1849             _ => Ok(RedisValue::Null),
1850         },
1851         None => Ok(RedisValue::Null),
1852     }
1853 }
1854 
command_json_clear<M: Manager>( manager: M, ctx: &Context, args: Vec<RedisString>, ) -> RedisResult1855 pub fn command_json_clear<M: Manager>(
1856     manager: M,
1857     ctx: &Context,
1858     args: Vec<RedisString>,
1859 ) -> RedisResult {
1860     let mut args = args.into_iter().skip(1);
1861     let key = args.next_arg()?;
1862     let paths = args.try_fold::<_, _, Result<Vec<Path>, RedisError>>(
1863         Vec::with_capacity(args.len()),
1864         |mut acc, arg| {
1865             let s = arg.try_as_str()?;
1866             acc.push(Path::new(s));
1867             Ok(acc)
1868         },
1869     )?;
1870 
1871     let paths = if paths.is_empty() {
1872         vec![Path::new(JSON_ROOT_PATH)]
1873     } else {
1874         paths
1875     };
1876 
1877     let path = paths.first().unwrap().get_path();
1878 
1879     let mut redis_key = manager.open_key_write(ctx, key)?;
1880 
1881     let root = redis_key
1882         .get_value()?
1883         .ok_or_else(RedisError::nonexistent_key)?;
1884 
1885     let paths = find_paths(path, root, |v| {
1886         v.get_type() == SelectValueType::Array || v.get_type() == SelectValueType::Object
1887     })?;
1888     let mut cleared = 0;
1889     if !paths.is_empty() {
1890         for p in paths {
1891             cleared += redis_key.clear(p)?;
1892         }
1893     }
1894     if cleared > 0 {
1895         redis_key.apply_changes(ctx, "json.clear")?;
1896     }
1897     Ok(cleared.into())
1898 }
1899 
command_json_debug<M: Manager>( manager: M, ctx: &Context, args: Vec<RedisString>, ) -> RedisResult1900 pub fn command_json_debug<M: Manager>(
1901     manager: M,
1902     ctx: &Context,
1903     args: Vec<RedisString>,
1904 ) -> RedisResult {
1905     let mut args = args.into_iter().skip(1);
1906     match args.next_str()?.to_uppercase().as_str() {
1907         "MEMORY" => {
1908             let key = args.next_arg()?;
1909             let path = Path::new(args.next_str().unwrap_or(JSON_ROOT_PATH_LEGACY));
1910 
1911             let key = manager.open_key_read(ctx, &key)?;
1912             if path.is_legacy() {
1913                 Ok(match key.get_value()? {
1914                     Some(doc) => {
1915                         manager.get_memory(KeyValue::new(doc).get_first(path.get_path())?)?
1916                     }
1917                     None => 0,
1918                 }
1919                 .into())
1920             } else {
1921                 Ok(match key.get_value()? {
1922                     Some(doc) => KeyValue::new(doc)
1923                         .get_values(path.get_path())?
1924                         .iter()
1925                         .map(|v| manager.get_memory(v).unwrap())
1926                         .collect::<Vec<usize>>(),
1927                     None => vec![],
1928                 }
1929                 .into())
1930             }
1931         }
1932         "HELP" => {
1933             let results = vec![
1934                 "MEMORY <key> [path] - reports memory usage",
1935                 "HELP                - this message",
1936             ];
1937             Ok(results.into())
1938         }
1939         _ => Err(RedisError::Str(
1940             "ERR unknown subcommand - try `JSON.DEBUG HELP`",
1941         )),
1942     }
1943 }
1944 
command_json_resp<M: Manager>( manager: M, ctx: &Context, args: Vec<RedisString>, ) -> RedisResult1945 pub fn command_json_resp<M: Manager>(
1946     manager: M,
1947     ctx: &Context,
1948     args: Vec<RedisString>,
1949 ) -> RedisResult {
1950     let mut args = args.into_iter().skip(1);
1951 
1952     let key = args.next_arg()?;
1953     let path = match args.next() {
1954         None => Path::new(JSON_ROOT_PATH_LEGACY),
1955         Some(s) => Path::new(s.try_as_str()?),
1956     };
1957 
1958     let key = manager.open_key_read(ctx, &key)?;
1959     match key.get_value()? {
1960         Some(doc) => KeyValue::new(doc).resp_serialize(path),
1961         None => Ok(RedisValue::Null),
1962     }
1963 }
1964 
command_json_cache_info<M: Manager>( _manager: M, _ctx: &Context, _args: Vec<RedisString>, ) -> RedisResult1965 pub fn command_json_cache_info<M: Manager>(
1966     _manager: M,
1967     _ctx: &Context,
1968     _args: Vec<RedisString>,
1969 ) -> RedisResult {
1970     Err(RedisError::Str("Command was not implemented"))
1971 }
1972 
command_json_cache_init<M: Manager>( _manager: M, _ctx: &Context, _args: Vec<RedisString>, ) -> RedisResult1973 pub fn command_json_cache_init<M: Manager>(
1974     _manager: M,
1975     _ctx: &Context,
1976     _args: Vec<RedisString>,
1977 ) -> RedisResult {
1978     Err(RedisError::Str("Command was not implemented"))
1979 }
1980