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