1use bytes::Bytes;
8
9pub trait ValkeyWrite {
15 fn write_arg(&mut self, arg: &[u8]);
17
18 fn write_arg_fmt(&mut self, arg: impl std::fmt::Display) {
20 self.write_arg(arg.to_string().as_bytes())
21 }
22}
23
24impl ValkeyWrite for Vec<Vec<u8>> {
25 fn write_arg(&mut self, arg: &[u8]) {
26 self.push(arg.to_owned());
27 }
28
29 fn write_arg_fmt(&mut self, arg: impl std::fmt::Display) {
30 self.push(arg.to_string().into_bytes())
31 }
32}
33
34impl ValkeyWrite for crate::cmd::Cmd {
35 fn write_arg(&mut self, arg: &[u8]) {
36 redis::RedisWrite::write_arg(self.as_redis_mut(), arg);
37 }
38
39 fn write_arg_fmt(&mut self, arg: impl std::fmt::Display) {
40 redis::RedisWrite::write_arg_fmt(self.as_redis_mut(), arg);
41 }
42}
43
44#[derive(Clone, Copy, Debug, PartialEq, Eq)]
50pub enum ValkeyNumericBehavior {
51 NonNumeric,
53 NumberIsInteger,
55 NumberIsFloat,
57}
58
59pub trait ToValkeyArgs {
81 fn write_valkey_args<W: ?Sized + ValkeyWrite>(&self, out: &mut W);
83
84 fn to_valkey_args(&self) -> Vec<Vec<u8>> {
86 let mut out = Vec::new();
87 self.write_valkey_args(&mut out);
88 out
89 }
90
91 fn describe_numeric_behavior(&self) -> ValkeyNumericBehavior {
94 ValkeyNumericBehavior::NonNumeric
95 }
96
97 fn num_of_args(&self) -> usize {
99 let mut counter = ArgCounter(0);
100 self.write_valkey_args(&mut counter);
101 counter.0
102 }
103
104 #[doc(hidden)]
106 fn num_of_args_from_slice(items: &[Self]) -> usize
107 where
108 Self: Sized,
109 {
110 items.iter().map(Self::num_of_args).sum()
111 }
112
113 #[doc(hidden)]
115 fn write_valkey_args_from_slice<W: ?Sized + ValkeyWrite>(items: &[Self], out: &mut W)
116 where
117 Self: Sized,
118 {
119 Self::write_valkey_args_from_iter(items.iter(), out);
120 }
121
122 #[doc(hidden)]
124 fn write_valkey_args_from_iter<'a, I, W: ?Sized + ValkeyWrite>(items: I, out: &mut W)
125 where
126 I: Iterator<Item = &'a Self>,
127 Self: Sized + 'a,
128 {
129 for item in items {
130 item.write_valkey_args(out);
131 }
132 }
133}
134
135macro_rules! impl_to_valkey_args_int {
137 ($($t:ty),* $(,)?) => {$(
138 impl ToValkeyArgs for $t {
139 fn write_valkey_args<W: ?Sized + ValkeyWrite>(&self, out: &mut W) {
140 out.write_arg_fmt(self);
141 }
142 fn describe_numeric_behavior(&self) -> ValkeyNumericBehavior {
143 ValkeyNumericBehavior::NumberIsInteger
144 }
145 }
146 )*};
147}
148
149impl_to_valkey_args_int!(i8, i16, u16, i32, u32, i64, u64, isize, usize);
150
151macro_rules! impl_to_valkey_args_nonzero {
153 ($($t:ty),* $(,)?) => {$(
154 impl ToValkeyArgs for $t {
155 fn write_valkey_args<W: ?Sized + ValkeyWrite>(&self, out: &mut W) {
156 out.write_arg_fmt(self);
157 }
158 fn describe_numeric_behavior(&self) -> ValkeyNumericBehavior {
159 ValkeyNumericBehavior::NumberIsInteger
160 }
161 }
162 )*};
163}
164
165impl_to_valkey_args_nonzero!(
166 core::num::NonZeroU8,
167 core::num::NonZeroI8,
168 core::num::NonZeroU16,
169 core::num::NonZeroI16,
170 core::num::NonZeroU32,
171 core::num::NonZeroI32,
172 core::num::NonZeroU64,
173 core::num::NonZeroI64,
174 core::num::NonZeroUsize,
175 core::num::NonZeroIsize,
176);
177
178macro_rules! impl_to_valkey_args_float {
180 ($($t:ty),* $(,)?) => {$(
181 impl ToValkeyArgs for $t {
182 fn write_valkey_args<W: ?Sized + ValkeyWrite>(&self, out: &mut W) {
183 let mut buf = ryu::Buffer::new();
184 out.write_arg(buf.format(*self).as_bytes());
185 }
186 fn describe_numeric_behavior(&self) -> ValkeyNumericBehavior {
187 ValkeyNumericBehavior::NumberIsFloat
188 }
189 }
190 )*};
191}
192
193impl_to_valkey_args_float!(f32, f64);
194
195impl ToValkeyArgs for u8 {
197 fn write_valkey_args<W: ?Sized + ValkeyWrite>(&self, out: &mut W) {
198 out.write_arg_fmt(self);
199 }
200
201 fn write_valkey_args_from_slice<W: ?Sized + ValkeyWrite>(items: &[u8], out: &mut W) {
204 out.write_arg(items);
205 }
206
207 fn num_of_args_from_slice(_items: &[u8]) -> usize {
208 1
209 }
210}
211
212impl ToValkeyArgs for bool {
214 fn write_valkey_args<W: ?Sized + ValkeyWrite>(&self, out: &mut W) {
215 out.write_arg(if *self { b"1" } else { b"0" });
216 }
217}
218
219impl ToValkeyArgs for String {
221 fn write_valkey_args<W: ?Sized + ValkeyWrite>(&self, out: &mut W) {
222 out.write_arg(self.as_bytes());
223 }
224}
225
226impl ToValkeyArgs for &str {
228 fn write_valkey_args<W: ?Sized + ValkeyWrite>(&self, out: &mut W) {
229 out.write_arg(self.as_bytes());
230 }
231}
232
233impl ToValkeyArgs for Bytes {
235 fn write_valkey_args<W: ?Sized + ValkeyWrite>(&self, out: &mut W) {
236 out.write_arg(self.as_ref());
237 }
238}
239
240impl<T: ToValkeyArgs> ToValkeyArgs for Vec<T> {
242 fn write_valkey_args<W: ?Sized + ValkeyWrite>(&self, out: &mut W) {
243 T::write_valkey_args_from_slice(self, out);
244 }
245
246 fn num_of_args(&self) -> usize {
247 T::num_of_args_from_slice(self)
248 }
249}
250
251impl<T: ToValkeyArgs> ToValkeyArgs for &[T] {
253 fn write_valkey_args<W: ?Sized + ValkeyWrite>(&self, out: &mut W) {
254 T::write_valkey_args_from_slice(self, out);
255 }
256
257 fn num_of_args(&self) -> usize {
258 T::num_of_args_from_slice(self)
259 }
260}
261
262impl<T: ToValkeyArgs, const N: usize> ToValkeyArgs for &[T; N] {
264 fn write_valkey_args<W: ?Sized + ValkeyWrite>(&self, out: &mut W) {
265 T::write_valkey_args_from_slice(self.as_slice(), out);
266 }
267
268 fn num_of_args(&self) -> usize {
269 T::num_of_args_from_slice(self.as_slice())
270 }
271}
272
273impl<T: ToValkeyArgs> ToValkeyArgs for Option<T> {
275 fn write_valkey_args<W: ?Sized + ValkeyWrite>(&self, out: &mut W) {
276 if let Some(x) = self {
277 x.write_valkey_args(out);
278 }
279 }
280
281 fn describe_numeric_behavior(&self) -> ValkeyNumericBehavior {
282 match self {
283 Some(x) => x.describe_numeric_behavior(),
284 None => ValkeyNumericBehavior::NonNumeric,
285 }
286 }
287
288 fn num_of_args(&self) -> usize {
289 self.as_ref().map_or(0, ToValkeyArgs::num_of_args)
290 }
291}
292
293impl<T: ToValkeyArgs> ToValkeyArgs for &T {
295 fn write_valkey_args<W: ?Sized + ValkeyWrite>(&self, out: &mut W) {
296 (*self).write_valkey_args(out);
297 }
298
299 fn describe_numeric_behavior(&self) -> ValkeyNumericBehavior {
300 (*self).describe_numeric_behavior()
301 }
302
303 fn num_of_args(&self) -> usize {
304 (*self).num_of_args()
305 }
306}
307
308impl<T: ToValkeyArgs + std::cmp::Eq + std::hash::Hash, S: std::hash::BuildHasher> ToValkeyArgs
310 for std::collections::HashSet<T, S>
311{
312 fn write_valkey_args<W: ?Sized + ValkeyWrite>(&self, out: &mut W) {
313 T::write_valkey_args_from_iter(self.iter(), out);
314 }
315}
316
317impl<T: ToValkeyArgs + std::cmp::Eq + std::hash::Hash + Ord> ToValkeyArgs
319 for std::collections::BTreeSet<T>
320{
321 fn write_valkey_args<W: ?Sized + ValkeyWrite>(&self, out: &mut W) {
322 T::write_valkey_args_from_iter(self.iter(), out);
323 }
324}
325
326impl<K: ToValkeyArgs, V: ToValkeyArgs> ToValkeyArgs for std::collections::BTreeMap<K, V>
329where
330 K: std::cmp::Eq + std::hash::Hash + Ord,
331{
332 fn write_valkey_args<W: ?Sized + ValkeyWrite>(&self, out: &mut W) {
333 for (key, value) in self {
334 assert!(key.num_of_args() == 1 && value.num_of_args() == 1);
335 key.write_valkey_args(out);
336 value.write_valkey_args(out);
337 }
338 }
339}
340
341impl<K: ToValkeyArgs, V: ToValkeyArgs, S: std::hash::BuildHasher> ToValkeyArgs
344 for std::collections::HashMap<K, V, S>
345where
346 K: std::cmp::Eq + std::hash::Hash,
347{
348 fn write_valkey_args<W: ?Sized + ValkeyWrite>(&self, out: &mut W) {
349 for (key, value) in self {
350 assert!(key.num_of_args() == 1 && value.num_of_args() == 1);
351 key.write_valkey_args(out);
352 value.write_valkey_args(out);
353 }
354 }
355}
356
357macro_rules! impl_to_valkey_args_tuple {
359 ($( ($($name:ident),+) ),+ $(,)?) => {$(
360 #[doc(hidden)]
361 impl<$($name: ToValkeyArgs),*> ToValkeyArgs for ($($name,)*) {
362 #[allow(non_snake_case, unused_variables)]
363 fn write_valkey_args<W: ?Sized + ValkeyWrite>(&self, out: &mut W) {
364 let ($(ref $name,)*) = *self;
365 $($name.write_valkey_args(out);)*
366 }
367 }
368 )+};
369}
370
371impl_to_valkey_args_tuple! {
372 (T1),
373 (T1, T2),
374 (T1, T2, T3),
375 (T1, T2, T3, T4),
376 (T1, T2, T3, T4, T5),
377 (T1, T2, T3, T4, T5, T6),
378 (T1, T2, T3, T4, T5, T6, T7),
379 (T1, T2, T3, T4, T5, T6, T7, T8),
380 (T1, T2, T3, T4, T5, T6, T7, T8, T9),
381 (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10),
382 (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11),
383 (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12),
384}
385
386pub trait ToSingleValkeyArg: ToValkeyArgs {}
404
405macro_rules! impl_to_single_valkey_arg {
406 ($($t:ty),* $(,)?) => {$(
407 impl ToSingleValkeyArg for $t {}
408 )*};
409}
410
411impl_to_single_valkey_arg!(
412 i8,
413 i16,
414 u16,
415 i32,
416 u32,
417 i64,
418 u64,
419 isize,
420 usize,
421 core::num::NonZeroU8,
422 core::num::NonZeroI8,
423 core::num::NonZeroU16,
424 core::num::NonZeroI16,
425 core::num::NonZeroU32,
426 core::num::NonZeroI32,
427 core::num::NonZeroU64,
428 core::num::NonZeroI64,
429 core::num::NonZeroUsize,
430 core::num::NonZeroIsize,
431 f32,
432 f64,
433 u8,
434 bool,
435 String,
436 &str,
437 Bytes,
438 Vec<u8>,
439 &[u8],
440);
441
442impl<const N: usize> ToSingleValkeyArg for &[u8; N] {}
443
444impl<T: ToSingleValkeyArg> ToSingleValkeyArg for &T {}
445
446struct ArgCounter(usize);
450
451impl ValkeyWrite for ArgCounter {
452 fn write_arg(&mut self, _arg: &[u8]) {
453 self.0 += 1;
454 }
455
456 fn write_arg_fmt(&mut self, _arg: impl std::fmt::Display) {
457 self.0 += 1;
458 }
459}
460
461#[cfg(test)]
464mod tests {
465 use super::*;
466
467 const TEXT: &[u8] = b"key";
469 const BINARY: &[u8] = &[0u8, 1, 2, 255, 0, 42];
470 const NUMBER: i64 = -7;
471
472 #[test]
473 fn vec_writer() {
474 let mut out: Vec<Vec<u8>> = Vec::new();
475 out.write_arg(TEXT);
476 out.write_arg(BINARY);
477 out.write_arg_fmt(NUMBER);
478
479 assert_eq!(out, vec![TEXT.to_vec(), BINARY.to_vec(), b"-7".to_vec()]);
480 }
481
482 #[test]
483 fn cmd_writer() {
484 let mut out = crate::cmd::Cmd::new();
485 out.write_arg(TEXT);
486 out.write_arg(BINARY);
487 out.write_arg_fmt(NUMBER);
488
489 assert_eq!(
490 out.as_redis().get_packed_command(),
491 crate::cmd::Cmd::new()
492 .arg(TEXT)
493 .arg(BINARY)
494 .arg(NUMBER)
495 .as_redis()
496 .get_packed_command()
497 );
498 }
499}
500
501#[cfg(test)]
502mod to_valkey_args_tests {
503 use super::*;
504 use crate::test_utils::assert_args;
505 use crate::test_utils::assert_args_empty;
506 use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
507 use std::sync::LazyLock;
508
509 static HASH_SET_0: LazyLock<HashSet<&str>> = LazyLock::new(HashSet::new);
510 static HASH_SET_1: LazyLock<HashSet<&str>> = LazyLock::new(|| HashSet::from(["x"]));
511 static HASH_SET_2: LazyLock<HashSet<&str>> = LazyLock::new(|| HashSet::from(["a", "b", "c"]));
512
513 static BTREE_SET_0: LazyLock<BTreeSet<&str>> = LazyLock::new(BTreeSet::new);
514 static BTREE_SET_1: LazyLock<BTreeSet<&str>> = LazyLock::new(|| BTreeSet::from(["x"]));
515 static BTREE_SET_2: LazyLock<BTreeSet<&str>> =
516 LazyLock::new(|| BTreeSet::from(["a", "b", "c"]));
517
518 static HASH_MAP_0: LazyLock<HashMap<&str, i64>> = LazyLock::new(HashMap::new);
519 static HASH_MAP_1: LazyLock<HashMap<&str, i64>> = LazyLock::new(|| HashMap::from([("k", 1)]));
520 static HASH_MAP_2: LazyLock<HashMap<&str, i64>> =
521 LazyLock::new(|| HashMap::from([("f1", 1), ("f2", 2)]));
522
523 static BTREE_MAP_0: LazyLock<BTreeMap<&str, i64>> = LazyLock::new(BTreeMap::new);
524 static BTREE_MAP_1: LazyLock<BTreeMap<&str, i64>> =
525 LazyLock::new(|| BTreeMap::from([("k", 1)]));
526 static BTREE_MAP_2: LazyLock<BTreeMap<&str, i64>> =
527 LazyLock::new(|| BTreeMap::from([("f1", 1), ("f2", 2)]));
528
529 #[test]
530 fn to_valkey_args_matches_redis_encoding() {
531 use redis::ToRedisArgs;
532 macro_rules! same {
533 ($v:expr) => {
534 assert_eq!(
535 $v.to_valkey_args(),
536 $v.to_redis_args(),
537 "encoding of {:?}",
538 $v
539 );
540 };
541 }
542
543 same!(1i8);
545 same!(2i16);
546 same!(3i32);
547 same!(4i64);
548 same!(5isize);
549 same!(0u8);
550 same!(255u8);
551 same!(6u16);
552 same!(7u32);
553 same!(8u64);
554 same!(9usize);
555 same!(i64::MAX);
556 same!(i64::MIN);
557 same!(u64::MAX);
558
559 same!(core::num::NonZeroI8::new(-1).unwrap());
561 same!(core::num::NonZeroI16::new(-2).unwrap());
562 same!(core::num::NonZeroI32::new(-3).unwrap());
563 same!(core::num::NonZeroI64::new(-4).unwrap());
564 same!(core::num::NonZeroIsize::new(-5).unwrap());
565 same!(core::num::NonZeroU8::new(1).unwrap());
566 same!(core::num::NonZeroU16::new(2).unwrap());
567 same!(core::num::NonZeroU32::new(3).unwrap());
568 same!(core::num::NonZeroU64::new(4).unwrap());
569 same!(core::num::NonZeroUsize::new(5).unwrap());
570
571 same!(1.5f32);
573 same!(0.0f64);
574 same!(1.5f64);
575 same!(-2.25f64);
576 same!(0.1f64);
577 same!(1e20f64);
578 same!(-1e-20f64);
579 same!(std::f64::consts::PI);
580
581 same!(b"raw".to_vec());
583 same!(&b"raw"[..]);
584
585 same!(true);
587 same!(false);
588
589 same!("hello");
591 same!(String::from("world"));
592
593 same!(vec!["a", "b", "c"]);
595 same!(&["a", "b"][..]);
596 same!(&["a", "b"]);
597 same!(&[("f1", 1i64), ("f2", 2i64)][..]);
598
599 same!(Some(5i64));
601 same!(Option::<i64>::None);
602
603 same!(&5i64);
605 same!(&"x");
606
607 same!(&*HASH_SET_0);
609 same!(&*BTREE_SET_0);
610 same!(&*HASH_MAP_0);
611 same!(&*BTREE_MAP_0);
612
613 same!(&*HASH_SET_1);
614 same!(&*BTREE_SET_1);
615 same!(&*HASH_MAP_1);
616 same!(&*BTREE_MAP_1);
617
618 same!(&*HASH_SET_2);
619 same!(&*BTREE_SET_2);
620 same!(&*HASH_MAP_2);
621 same!(&*BTREE_MAP_2);
622
623 same!((1,));
625 same!((1, 2));
626 same!((1, 2, 3));
627 same!((1, 2, 3, 4));
628 same!((1, 2, 3, 4, 5));
629 same!((1, 2, 3, 4, 5, 6));
630 same!((1, 2, 3, 4, 5, 6, 7));
631 same!((1, 2, 3, 4, 5, 6, 7, 8));
632 same!((1, 2, 3, 4, 5, 6, 7, 8, 9));
633 same!((1, 2, 3, 4, 5, 6, 7, 8, 9, 10));
634 same!((1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11));
635 same!((1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12));
636 }
637
638 #[test]
640 fn to_valkey_args_bytes() {
641 assert_eq!(
642 Bytes::from_static(b"\x00\xff data").to_valkey_args(),
643 vec![b"\x00\xff data".to_vec()]
644 );
645 }
646
647 #[test]
648 fn num_of_args() {
649 assert_args(1i8, &["1"]);
651 assert_args(-1i64, &["-1"]);
652 assert_args(1usize, &["1"]);
653
654 assert_args(core::num::NonZeroU8::new(1).unwrap(), &["1"]);
656
657 assert_args(1.5f64, &["1.5"]);
659
660 assert_args(b"bytes".to_vec(), &["bytes"]);
662 assert_args(Vec::<u8>::new(), &[""]);
663 assert_args(&b"bytes"[..], &["bytes"]);
664 assert_args(b"bytes", &["bytes"]);
665 assert_args(vec![0xFFu8, 0x00], &[[0xFFu8, 0x00].as_slice()]);
666
667 assert_args(true, &["1"]);
669
670 assert_args("k", &["k"]);
672 assert_args(String::from("k"), &["k"]);
673
674 assert_args(Bytes::from_static(b"b"), &["b"]);
676
677 assert_args(vec!["one"], &["one"]);
679 assert_args(vec!["a", "b", "c"], &["a", "b", "c"]);
680 assert_args_empty(Vec::<&str>::new());
681 assert_args(&["a", "b"][..], &["a", "b"]);
682 assert_args(&["a", "b"], &["a", "b"]);
683 assert_args(vec![vec!["a", "b"], vec!["c"]], &["a", "b", "c"]);
684 assert_args(&[("f1", 1i64), ("f2", 2i64)][..], &["f1", "1", "f2", "2"]);
685
686 assert_args_empty(Option::<i64>::None);
688 assert_args(Some(1i64), &["1"]);
689 assert_args(Some(vec!["a", "b"]), &["a", "b"]);
690
691 #[allow(clippy::needless_borrows_for_generic_args)]
694 {
695 assert_args(&1i64, &["1"]);
696 assert_args(&&vec!["a", "b"], &["a", "b"]);
697 }
698
699 assert_args_empty(&*HASH_SET_0);
701 assert_args_empty(&*BTREE_SET_0);
702 assert_args_empty(&*HASH_MAP_0);
703 assert_args_empty(&*BTREE_MAP_0);
704
705 assert_args(&*HASH_SET_1, &["x"]);
706 assert_args(&*BTREE_SET_1, &["x"]);
707 assert_args(&*HASH_MAP_1, &["k", "1"]);
708 assert_args(&*BTREE_MAP_1, &["k", "1"]);
709
710 assert_args(&*BTREE_SET_2, &["a", "b", "c"]);
711 assert_args(&*BTREE_MAP_2, &["f1", "1", "f2", "2"]);
712
713 assert_eq!(HASH_SET_2.to_valkey_args().len(), 3);
715 assert_eq!(HASH_SET_2.num_of_args(), 3);
716 assert_eq!(HASH_MAP_2.to_valkey_args().len(), 4);
717 assert_eq!(HASH_MAP_2.num_of_args(), 4);
718
719 assert_args((1i64,), &["1"]);
721 assert_args((1i64, 2i64), &["1", "2"]);
722 assert_args(("a", 1, 2.5), &["a", "1", "2.5"]);
723 assert_args((vec!["a", "b"], "c"), &["a", "b", "c"]);
724 }
725
726 #[test]
727 fn describe_numeric_behavior() {
728 use ValkeyNumericBehavior::{NonNumeric, NumberIsFloat, NumberIsInteger};
729 macro_rules! num {
730 ($v:expr, $b:expr) => {
731 assert_eq!(
732 $v.describe_numeric_behavior(),
733 $b,
734 "numeric behavior of {:?}",
735 $v
736 );
737 };
738 }
739
740 num!(1i8, NumberIsInteger);
742 num!(2i16, NumberIsInteger);
743 num!(3i32, NumberIsInteger);
744 num!(4i64, NumberIsInteger);
745 num!(5isize, NumberIsInteger);
746 num!(6u16, NumberIsInteger);
747 num!(7u32, NumberIsInteger);
748 num!(8u64, NumberIsInteger);
749 num!(9usize, NumberIsInteger);
750
751 num!(core::num::NonZeroI8::new(-1).unwrap(), NumberIsInteger);
753 num!(core::num::NonZeroI16::new(-2).unwrap(), NumberIsInteger);
754 num!(core::num::NonZeroI32::new(-3).unwrap(), NumberIsInteger);
755 num!(core::num::NonZeroI64::new(-4).unwrap(), NumberIsInteger);
756 num!(core::num::NonZeroIsize::new(-5).unwrap(), NumberIsInteger);
757 num!(core::num::NonZeroU8::new(1).unwrap(), NumberIsInteger);
758 num!(core::num::NonZeroU16::new(2).unwrap(), NumberIsInteger);
759 num!(core::num::NonZeroU32::new(3).unwrap(), NumberIsInteger);
760 num!(core::num::NonZeroU64::new(4).unwrap(), NumberIsInteger);
761 num!(core::num::NonZeroUsize::new(5).unwrap(), NumberIsInteger);
762
763 num!(1.5f32, NumberIsFloat);
765 num!(1.5f64, NumberIsFloat);
766
767 num!(0u8, NonNumeric);
770 num!(b"raw".to_vec(), NonNumeric);
771 num!(&b"raw"[..], NonNumeric);
772
773 num!(true, NonNumeric);
775
776 num!("hello", NonNumeric);
778 num!(String::from("world"), NonNumeric);
779
780 num!(Bytes::from_static(b"b"), NonNumeric);
782
783 num!(vec!["a", "b"], NonNumeric);
785 num!(&["a", "b"][..], NonNumeric);
786 num!(&["a", "b"], NonNumeric);
787
788 num!(Some(5i64), NumberIsInteger);
790 num!(Some(1.5f64), NumberIsFloat);
791 num!(Some("x"), NonNumeric);
792 num!(Option::<f64>::None, NonNumeric);
793
794 num!(&5i64, NumberIsInteger);
796 num!(&1.5f64, NumberIsFloat);
797 num!(&&5i64, NumberIsInteger);
798 num!(&"x", NonNumeric);
799
800 num!(&*HASH_SET_2, NonNumeric);
802 num!(&*BTREE_SET_2, NonNumeric);
803 num!(&*HASH_MAP_2, NonNumeric);
804 num!(&*BTREE_MAP_2, NonNumeric);
805
806 num!((1,), NonNumeric);
808 num!((1, 2), NonNumeric);
809 num!((1, 2, 3), NonNumeric);
810 }
811}
812
813#[cfg(test)]
814mod to_single_arg {
815 use super::*;
816
817 fn assert_single<T: ToSingleValkeyArg>(value: T) {
819 assert_eq!(value.num_of_args(), 1);
820 }
821
822 #[test]
823 fn to_single_valkey_arg_impls_encode_one_arg() {
824 assert_single(1i8);
826 assert_single(1i64);
827 assert_single(1usize);
828 assert_single(255u8);
829
830 assert_single(core::num::NonZeroU64::new(1).unwrap());
832
833 assert_single(1.5f32);
835 assert_single(1.5f64);
836
837 assert_single(true);
839
840 assert_single("k");
842 assert_single(String::from("k"));
843
844 assert_single(Bytes::from_static(b"b"));
846
847 assert_single(b"raw".to_vec());
849 assert_single(&b"raw"[..]);
850 assert_single(b"raw");
851 assert_single(Vec::<u8>::new());
852
853 #[allow(clippy::needless_borrows_for_generic_args)]
856 {
857 assert_single(&"k");
858 assert_single(&&5i64);
859 }
860 }
861}