redis_oxide/commands/
sorted_set.rs1use crate::commands::Command;
4use crate::core::{
5 error::{RedisError, RedisResult},
6 value::RespValue,
7};
8use crate::pipeline::PipelineCommand;
9use std::collections::HashMap;
10
11#[derive(Debug, Clone)]
13pub struct ZAddCommand {
14 key: String,
15 members: HashMap<String, f64>,
16}
17
18impl ZAddCommand {
19 #[must_use]
21 pub fn new(key: impl Into<String>, members: HashMap<String, f64>) -> Self {
22 Self {
23 key: key.into(),
24 members,
25 }
26 }
27}
28
29impl Command for ZAddCommand {
30 type Output = i64;
31
32 fn command_name(&self) -> &str {
33 "ZADD"
34 }
35
36 fn args(&self) -> Vec<RespValue> {
37 let mut args = vec![RespValue::from(self.key.clone())];
38 for (member, score) in &self.members {
39 args.push(RespValue::from(score.to_string()));
40 args.push(RespValue::from(member.clone()));
41 }
42 args
43 }
44
45 fn parse_response(&self, response: RespValue) -> RedisResult<Self::Output> {
46 response.as_int()
47 }
48
49 fn keys(&self) -> Vec<&[u8]> {
50 vec![self.key.as_bytes()]
51 }
52}
53
54impl PipelineCommand for ZAddCommand {
55 fn name(&self) -> &str {
56 self.command_name()
57 }
58
59 fn args(&self) -> Vec<RespValue> {
60 <Self as Command>::args(self)
61 }
62
63 fn key(&self) -> Option<String> {
64 Some(self.key.clone())
65 }
66}
67
68#[derive(Debug, Clone)]
70pub struct ZRemCommand {
71 key: String,
72 members: Vec<String>,
73}
74
75impl ZRemCommand {
76 #[must_use]
78 pub fn new(key: impl Into<String>, members: Vec<String>) -> Self {
79 Self {
80 key: key.into(),
81 members,
82 }
83 }
84}
85
86impl Command for ZRemCommand {
87 type Output = i64;
88
89 fn command_name(&self) -> &str {
90 "ZREM"
91 }
92
93 fn args(&self) -> Vec<RespValue> {
94 let mut args = vec![RespValue::from(self.key.clone())];
95 for member in &self.members {
96 args.push(RespValue::from(member.clone()));
97 }
98 args
99 }
100
101 fn parse_response(&self, response: RespValue) -> RedisResult<Self::Output> {
102 response.as_int()
103 }
104
105 fn keys(&self) -> Vec<&[u8]> {
106 vec![self.key.as_bytes()]
107 }
108}
109
110impl PipelineCommand for ZRemCommand {
111 fn name(&self) -> &str {
112 self.command_name()
113 }
114
115 fn args(&self) -> Vec<RespValue> {
116 <Self as Command>::args(self)
117 }
118
119 fn key(&self) -> Option<String> {
120 Some(self.key.clone())
121 }
122}
123
124#[derive(Debug, Clone)]
126pub struct ZRangeCommand {
127 key: String,
128 start: i64,
129 stop: i64,
130}
131
132impl ZRangeCommand {
133 #[must_use]
135 pub fn new(key: impl Into<String>, start: i64, stop: i64) -> Self {
136 Self {
137 key: key.into(),
138 start,
139 stop,
140 }
141 }
142}
143
144impl Command for ZRangeCommand {
145 type Output = Vec<String>;
146
147 fn command_name(&self) -> &str {
148 "ZRANGE"
149 }
150
151 fn args(&self) -> Vec<RespValue> {
152 vec![
153 RespValue::from(self.key.clone()),
154 RespValue::from(self.start),
155 RespValue::from(self.stop),
156 ]
157 }
158
159 fn parse_response(&self, response: RespValue) -> RedisResult<Self::Output> {
160 match response {
161 RespValue::Array(items) => {
162 let mut result = Vec::new();
163 for item in items {
164 match item {
165 RespValue::BulkString(b) => {
166 let s = String::from_utf8(b.to_vec())
167 .map_err(|e| RedisError::Type(format!("Invalid UTF-8: {e}")))?;
168 result.push(s);
169 }
170 RespValue::Null => {
171 }
173 _ => {
174 return Err(RedisError::Type(format!(
175 "Unexpected item type in ZRANGE response: {:?}",
176 item
177 )))
178 }
179 }
180 }
181 Ok(result)
182 }
183 _ => Err(RedisError::Type(format!(
184 "Unexpected response type for ZRANGE: {:?}",
185 response
186 ))),
187 }
188 }
189
190 fn keys(&self) -> Vec<&[u8]> {
191 vec![self.key.as_bytes()]
192 }
193}
194
195impl PipelineCommand for ZRangeCommand {
196 fn name(&self) -> &str {
197 self.command_name()
198 }
199
200 fn args(&self) -> Vec<RespValue> {
201 <Self as Command>::args(self)
202 }
203
204 fn key(&self) -> Option<String> {
205 Some(self.key.clone())
206 }
207}
208
209#[derive(Debug, Clone)]
211pub struct ZScoreCommand {
212 key: String,
213 member: String,
214}
215
216impl ZScoreCommand {
217 #[must_use]
219 pub fn new(key: impl Into<String>, member: impl Into<String>) -> Self {
220 Self {
221 key: key.into(),
222 member: member.into(),
223 }
224 }
225}
226
227impl Command for ZScoreCommand {
228 type Output = Option<f64>;
229
230 fn command_name(&self) -> &str {
231 "ZSCORE"
232 }
233
234 fn args(&self) -> Vec<RespValue> {
235 vec![
236 RespValue::from(self.key.clone()),
237 RespValue::from(self.member.clone()),
238 ]
239 }
240
241 fn parse_response(&self, response: RespValue) -> RedisResult<Self::Output> {
242 match response {
243 RespValue::BulkString(b) => {
244 let s = String::from_utf8(b.to_vec())
245 .map_err(|e| RedisError::Type(format!("Invalid UTF-8: {e}")))?;
246 let score = s
247 .parse::<f64>()
248 .map_err(|e| RedisError::Type(format!("Invalid float: {e}")))?;
249 Ok(Some(score))
250 }
251 RespValue::Null => Ok(None),
252 _ => Err(RedisError::Type(format!(
253 "Unexpected response type for ZSCORE: {:?}",
254 response
255 ))),
256 }
257 }
258
259 fn keys(&self) -> Vec<&[u8]> {
260 vec![self.key.as_bytes()]
261 }
262}
263
264impl PipelineCommand for ZScoreCommand {
265 fn name(&self) -> &str {
266 self.command_name()
267 }
268
269 fn args(&self) -> Vec<RespValue> {
270 <Self as Command>::args(self)
271 }
272
273 fn key(&self) -> Option<String> {
274 Some(self.key.clone())
275 }
276}
277
278#[derive(Debug, Clone)]
280pub struct ZCardCommand {
281 key: String,
282}
283
284impl ZCardCommand {
285 #[must_use]
287 pub fn new(key: impl Into<String>) -> Self {
288 Self { key: key.into() }
289 }
290}
291
292impl Command for ZCardCommand {
293 type Output = i64;
294
295 fn command_name(&self) -> &str {
296 "ZCARD"
297 }
298
299 fn args(&self) -> Vec<RespValue> {
300 vec![RespValue::from(self.key.clone())]
301 }
302
303 fn parse_response(&self, response: RespValue) -> RedisResult<Self::Output> {
304 response.as_int()
305 }
306
307 fn keys(&self) -> Vec<&[u8]> {
308 vec![self.key.as_bytes()]
309 }
310}
311
312impl PipelineCommand for ZCardCommand {
313 fn name(&self) -> &str {
314 self.command_name()
315 }
316
317 fn args(&self) -> Vec<RespValue> {
318 <Self as Command>::args(self)
319 }
320
321 fn key(&self) -> Option<String> {
322 Some(self.key.clone())
323 }
324}
325
326#[derive(Debug, Clone)]
328pub struct ZRankCommand {
329 key: String,
330 member: String,
331}
332
333impl ZRankCommand {
334 #[must_use]
336 pub fn new(key: impl Into<String>, member: impl Into<String>) -> Self {
337 Self {
338 key: key.into(),
339 member: member.into(),
340 }
341 }
342}
343
344impl Command for ZRankCommand {
345 type Output = Option<i64>;
346
347 fn command_name(&self) -> &str {
348 "ZRANK"
349 }
350
351 fn args(&self) -> Vec<RespValue> {
352 vec![
353 RespValue::from(self.key.clone()),
354 RespValue::from(self.member.clone()),
355 ]
356 }
357
358 fn parse_response(&self, response: RespValue) -> RedisResult<Self::Output> {
359 match response {
360 RespValue::Integer(rank) => Ok(Some(rank)),
361 RespValue::Null => Ok(None),
362 _ => Err(RedisError::Type(format!(
363 "Unexpected response type for ZRANK: {:?}",
364 response
365 ))),
366 }
367 }
368
369 fn keys(&self) -> Vec<&[u8]> {
370 vec![self.key.as_bytes()]
371 }
372}
373
374impl PipelineCommand for ZRankCommand {
375 fn name(&self) -> &str {
376 self.command_name()
377 }
378
379 fn args(&self) -> Vec<RespValue> {
380 <Self as Command>::args(self)
381 }
382
383 fn key(&self) -> Option<String> {
384 Some(self.key.clone())
385 }
386}
387
388#[derive(Debug, Clone)]
390pub struct ZRevRankCommand {
391 key: String,
392 member: String,
393}
394
395impl ZRevRankCommand {
396 #[must_use]
398 pub fn new(key: impl Into<String>, member: impl Into<String>) -> Self {
399 Self {
400 key: key.into(),
401 member: member.into(),
402 }
403 }
404}
405
406impl Command for ZRevRankCommand {
407 type Output = Option<i64>;
408
409 fn command_name(&self) -> &str {
410 "ZREVRANK"
411 }
412
413 fn args(&self) -> Vec<RespValue> {
414 vec![
415 RespValue::from(self.key.clone()),
416 RespValue::from(self.member.clone()),
417 ]
418 }
419
420 fn parse_response(&self, response: RespValue) -> RedisResult<Self::Output> {
421 match response {
422 RespValue::Integer(rank) => Ok(Some(rank)),
423 RespValue::Null => Ok(None),
424 _ => Err(RedisError::Type(format!(
425 "Unexpected response type for ZREVRANK: {:?}",
426 response
427 ))),
428 }
429 }
430
431 fn keys(&self) -> Vec<&[u8]> {
432 vec![self.key.as_bytes()]
433 }
434}
435
436impl PipelineCommand for ZRevRankCommand {
437 fn name(&self) -> &str {
438 self.command_name()
439 }
440
441 fn args(&self) -> Vec<RespValue> {
442 <Self as Command>::args(self)
443 }
444
445 fn key(&self) -> Option<String> {
446 Some(self.key.clone())
447 }
448}