1
1
#[ macro_use]
2
2
extern crate redismodule;
3
3
4
- use redismodule:: { Context , RedisResult , NextArg , REDIS_OK , RedisError } ;
5
4
use redismodule:: native_types:: RedisType ;
5
+ use redismodule:: { Context , NextArg , RedisError , RedisResult , REDIS_OK } ;
6
6
7
7
mod redisjson;
8
8
9
- use crate :: redisjson:: RedisJSON ;
9
+ use crate :: redisjson:: { Error , RedisJSON } ;
10
10
11
11
static REDIS_JSON_TYPE : RedisType = RedisType :: new ( "RedisJSON" ) ;
12
12
@@ -25,7 +25,7 @@ fn json_del(ctx: &Context, args: Vec<String>) -> RedisResult {
25
25
let key = ctx. open_key_writable ( & key) ;
26
26
let deleted = match key. get_value :: < RedisJSON > ( & REDIS_JSON_TYPE ) ? {
27
27
Some ( doc) => doc. delete_path ( & path) ?,
28
- None => 0
28
+ None => 0 ,
29
29
} ;
30
30
Ok ( deleted. into ( ) )
31
31
}
@@ -37,13 +37,12 @@ fn json_set(ctx: &Context, args: Vec<String>) -> RedisResult {
37
37
let path = args. next_string ( ) ?;
38
38
let value = args. next_string ( ) ?;
39
39
40
- let set_option = args. next ( )
41
- . map ( |op| {
42
- match op. to_uppercase ( ) . as_str ( ) {
43
- "NX" => Ok ( SetOptions :: NotExists ) ,
44
- "XX" => Ok ( SetOptions :: AlreadyExists ) ,
45
- _ => Err ( RedisError :: Str ( "ERR syntax error" ) ) ,
46
- }
40
+ let set_option = args
41
+ . next ( )
42
+ . map ( |op| match op. to_uppercase ( ) . as_str ( ) {
43
+ "NX" => Ok ( SetOptions :: NotExists ) ,
44
+ "XX" => Ok ( SetOptions :: AlreadyExists ) ,
45
+ _ => Err ( RedisError :: Str ( "ERR syntax error" ) ) ,
47
46
} )
48
47
. transpose ( ) ?;
49
48
@@ -73,63 +72,62 @@ fn json_get(ctx: &Context, args: Vec<String>) -> RedisResult {
73
72
let mut path = loop {
74
73
let arg = match args. next_string ( ) {
75
74
Ok ( s) => s,
76
- Err ( _) => "$" . to_owned ( ) // path is optional
75
+ Err ( _) => "$" . to_owned ( ) , // path is optional
77
76
} ;
78
77
79
78
match arg. as_str ( ) {
80
- "INDENT" => args. next ( ) , // TODO add support
81
- "NEWLINE" => args. next ( ) , // TODO add support
82
- "SPACE" => args. next ( ) , // TODO add support
83
- "NOESCAPE" => continue , // TODO add support
84
- "." => break String :: from ( "$" ) , // backward compatibility suuport
85
- _ => break arg
79
+ "INDENT" => args. next ( ) , // TODO add support
80
+ "NEWLINE" => args. next ( ) , // TODO add support
81
+ "SPACE" => args. next ( ) , // TODO add support
82
+ "NOESCAPE" => continue , // TODO add support
83
+ "." => break String :: from ( "$" ) , // backward compatibility support
84
+ _ => break arg,
86
85
} ;
87
86
} ;
88
87
89
- if path. starts_with ( "." ) { // backward compatibility
88
+ if path. starts_with ( "." ) {
89
+ // backward compatibility
90
90
path. insert ( 0 , '$' ) ;
91
91
}
92
92
93
93
let key = ctx. open_key_writable ( & key) ;
94
94
95
95
let value = match key. get_value :: < RedisJSON > ( & REDIS_JSON_TYPE ) ? {
96
96
Some ( doc) => doc. to_string ( & path) ?. into ( ) ,
97
- None => ( ) . into ( )
97
+ None => ( ) . into ( ) ,
98
98
} ;
99
99
100
100
Ok ( value)
101
101
}
102
102
103
103
fn json_mget ( ctx : & Context , args : Vec < String > ) -> RedisResult {
104
-
105
104
if args. len ( ) < 3 {
106
105
return Err ( RedisError :: WrongArity ) ;
107
106
}
108
107
if let Some ( path) = args. last ( ) {
109
108
let mut path = path. clone ( ) ;
110
- if path. starts_with ( "." ) { // backward compatibility
109
+ if path. starts_with ( "." ) {
110
+ // backward compatibility
111
111
path. insert ( 0 , '$' ) ;
112
112
}
113
- let mut results: Vec < String > = Vec :: with_capacity ( args. len ( ) - 2 ) ;
114
- for key in & args[ 1 ..args. len ( ) - 1 ] {
113
+ let mut results: Vec < String > = Vec :: with_capacity ( args. len ( ) - 2 ) ;
114
+ for key in & args[ 1 ..args. len ( ) - 1 ] {
115
115
let redis_key = ctx. open_key_writable ( & key) ;
116
116
match redis_key. get_value :: < RedisJSON > ( & REDIS_JSON_TYPE ) ? {
117
117
Some ( doc) => {
118
118
let result = doc. to_string ( & path) ?;
119
119
results. push ( result) ;
120
- } ,
120
+ }
121
121
None => { }
122
122
} ;
123
-
124
123
}
125
124
Ok ( results. into ( ) )
126
125
} else {
127
126
Err ( RedisError :: WrongArity )
128
127
}
129
128
}
130
129
131
-
132
- fn json_strlen ( ctx : & Context , args : Vec < String > ) -> RedisResult {
130
+ fn json_str_len ( ctx : & Context , args : Vec < String > ) -> RedisResult {
133
131
let mut args = args. into_iter ( ) . skip ( 1 ) ;
134
132
let key = args. next_string ( ) ?;
135
133
let path = args. next_string ( ) ?;
@@ -138,7 +136,7 @@ fn json_strlen(ctx: &Context, args: Vec<String>) -> RedisResult {
138
136
139
137
let length = match key. get_value :: < RedisJSON > ( & REDIS_JSON_TYPE ) ? {
140
138
Some ( doc) => doc. str_len ( & path) ?. into ( ) ,
141
- None => ( ) . into ( )
139
+ None => ( ) . into ( ) ,
142
140
} ;
143
141
144
142
Ok ( length)
@@ -153,12 +151,107 @@ fn json_type(ctx: &Context, args: Vec<String>) -> RedisResult {
153
151
154
152
let value = match key. get_value :: < RedisJSON > ( & REDIS_JSON_TYPE ) ? {
155
153
Some ( doc) => doc. get_type ( & path) ?. into ( ) ,
156
- None => ( ) . into ( )
154
+ None => ( ) . into ( ) ,
157
155
} ;
158
156
159
157
Ok ( value)
160
158
}
161
159
160
+ fn json_num_incrby ( ctx : & Context , args : Vec < String > ) -> RedisResult {
161
+ json_num_op ( ctx, args, |num1, num2| num1 + num2)
162
+ }
163
+
164
+ fn json_num_multby ( ctx : & Context , args : Vec < String > ) -> RedisResult {
165
+ json_num_op ( ctx, args, |num1, num2| num1 * num2)
166
+ }
167
+
168
+ fn json_num_powby ( ctx : & Context , args : Vec < String > ) -> RedisResult {
169
+ json_num_op ( ctx, args, |num1, num2| num1. powf ( num2) )
170
+ }
171
+
172
+ fn json_num_op < F > ( ctx : & Context , args : Vec < String > , fun : F ) -> RedisResult
173
+ where F : Fn ( f64 , f64 ) -> f64 {
174
+ let mut args = args. into_iter ( ) . skip ( 1 ) ;
175
+
176
+ let key = args. next_string ( ) ?;
177
+ let path = args. next_string ( ) ?;
178
+ let number: f64 = args. next_string ( ) ?. parse ( ) ?;
179
+
180
+ let key = ctx. open_key_writable ( & key) ;
181
+
182
+ match key. get_value :: < RedisJSON > ( & REDIS_JSON_TYPE ) ? {
183
+ Some ( doc) => Ok ( doc. num_op ( & path, number, fun) ?. into ( ) ) ,
184
+ None => Err ( "ERR could not perform this operation on a key that doesn't exist" . into ( ) ) ,
185
+ }
186
+ }
187
+
188
+ fn json_str_append ( _ctx : & Context , _args : Vec < String > ) -> RedisResult {
189
+ Err ( "Command was not implemented" . into ( ) )
190
+ }
191
+
192
+ fn json_arr_append ( _ctx : & Context , _args : Vec < String > ) -> RedisResult {
193
+ Err ( "Command was not implemented" . into ( ) )
194
+ }
195
+
196
+ fn json_arr_index ( _ctx : & Context , _args : Vec < String > ) -> RedisResult {
197
+ Err ( "Command was not implemented" . into ( ) )
198
+ }
199
+
200
+ fn json_arr_insert ( _ctx : & Context , _args : Vec < String > ) -> RedisResult {
201
+ Err ( "Command was not implemented" . into ( ) )
202
+ }
203
+
204
+ fn json_arr_len ( ctx : & Context , args : Vec < String > ) -> RedisResult {
205
+ json_len ( ctx, args, |doc, path| doc. arr_len ( path) )
206
+ }
207
+
208
+ fn json_arr_pop ( _ctx : & Context , _args : Vec < String > ) -> RedisResult {
209
+ Err ( "Command was not implemented" . into ( ) )
210
+ }
211
+
212
+ fn json_arr_trim ( _ctx : & Context , _args : Vec < String > ) -> RedisResult {
213
+ Err ( "Command was not implemented" . into ( ) )
214
+ }
215
+
216
+ fn json_obj_keys ( _ctx : & Context , _args : Vec < String > ) -> RedisResult {
217
+ Err ( "Command was not implemented" . into ( ) )
218
+ }
219
+
220
+ fn json_obj_len ( ctx : & Context , args : Vec < String > ) -> RedisResult {
221
+ json_len ( ctx, args, |doc, path| doc. obj_len ( path) )
222
+ }
223
+
224
+ fn json_debug ( _ctx : & Context , _args : Vec < String > ) -> RedisResult {
225
+ Err ( "Command was not implemented" . into ( ) )
226
+ }
227
+
228
+ fn json_forget ( _ctx : & Context , _args : Vec < String > ) -> RedisResult {
229
+ Err ( "Command was not implemented" . into ( ) )
230
+ }
231
+
232
+ fn json_resp ( _ctx : & Context , _args : Vec < String > ) -> RedisResult {
233
+ Err ( "Command was not implemented" . into ( ) )
234
+ }
235
+
236
+ fn json_len < F : Fn ( & RedisJSON , & String ) -> Result < usize , Error > > (
237
+ ctx : & Context ,
238
+ args : Vec < String > ,
239
+ fun : F ,
240
+ ) -> RedisResult {
241
+ let mut args = args. into_iter ( ) . skip ( 1 ) ;
242
+ let key = args. next_string ( ) ?;
243
+ let path = args. next_string ( ) ?;
244
+
245
+ let key = ctx. open_key_writable ( & key) ;
246
+
247
+ let length = match key. get_value :: < RedisJSON > ( & REDIS_JSON_TYPE ) ? {
248
+ Some ( doc) => fun ( & doc, & path) ?. into ( ) ,
249
+ None => ( ) . into ( ) ,
250
+ } ;
251
+
252
+ Ok ( length)
253
+ }
254
+
162
255
//////////////////////////////////////////////////////
163
256
164
257
redis_module ! {
@@ -168,11 +261,26 @@ redis_module! {
168
261
REDIS_JSON_TYPE ,
169
262
] ,
170
263
commands: [
171
- [ "json.set" , json_set, "write" ] ,
172
264
[ "json.del" , json_del, "write" ] ,
173
265
[ "json.get" , json_get, "" ] ,
174
266
[ "json.mget" , json_mget, "" ] ,
175
- [ "json.strlen " , json_strlen , "" ] ,
267
+ [ "json.set " , json_set , "write " ] ,
176
268
[ "json.type" , json_type, "" ] ,
269
+ [ "json.numincrby" , json_num_incrby, "" ] ,
270
+ [ "json.nummultby" , json_num_multby, "" ] ,
271
+ [ "json.numpowby" , json_num_powby, "" ] ,
272
+ [ "json.strappend" , json_str_append, "" ] ,
273
+ [ "json.strlen" , json_str_len, "" ] ,
274
+ [ "json.arrappend" , json_arr_append, "" ] ,
275
+ [ "json.arrindex" , json_arr_index, "" ] ,
276
+ [ "json.arrinsert" , json_arr_insert, "" ] ,
277
+ [ "json.arrlen" , json_arr_len, "" ] ,
278
+ [ "json.arrpop" , json_arr_pop, "" ] ,
279
+ [ "json.arrtrim" , json_arr_trim, "" ] ,
280
+ [ "json.objkeys" , json_obj_keys, "" ] ,
281
+ [ "json.objlen" , json_obj_len, "" ] ,
282
+ [ "json.debug" , json_debug, "" ] ,
283
+ [ "json.forget" , json_forget, "" ] ,
284
+ [ "json.resp" , json_resp, "" ] ,
177
285
] ,
178
286
}
0 commit comments