redis_protocol/resp2/
encode.rs

1//! Functions for encoding frames into the RESP2 protocol.
2//!
3//! <https://redis.io/topics/protocol#resp-protocol-description>
4
5use crate::{error::RedisProtocolError, int2dec, resp2::types::*, types::CRLF};
6use cookie_factory::GenError;
7use core::str;
8
9#[cfg(feature = "bytes")]
10use crate::utils;
11#[cfg(feature = "bytes")]
12use bytes::BytesMut;
13
14fn gen_simplestring<'a>(x: (&'a mut [u8], usize), data: &[u8]) -> Result<(&'a mut [u8], usize), GenError> {
15  do_gen!(
16    x,
17    gen_be_u8!(FrameKind::SimpleString.to_byte()) >> gen_slice!(data) >> gen_slice!(CRLF.as_bytes())
18  )
19}
20
21fn gen_error<'a>(x: (&'a mut [u8], usize), data: &str) -> Result<(&'a mut [u8], usize), GenError> {
22  do_gen!(
23    x,
24    gen_be_u8!(FrameKind::Error.to_byte()) >> gen_slice!(data.as_bytes()) >> gen_slice!(CRLF.as_bytes())
25  )
26}
27
28fn gen_integer(x: (&mut [u8], usize), data: i64, as_bulkstring: bool) -> Result<(&mut [u8], usize), GenError> {
29  let (buf, buf_padding) = int2dec::i64_to_digits(data);
30
31  if as_bulkstring {
32    // a more optimized way to encode an i64 as a BulkString, which is how Redis expects integers in practice
33    let encoded_len = buf.len() - buf_padding;
34    let (len, len_padding) = int2dec::u64_to_digits(encoded_len as u64);
35
36    do_gen!(
37      x,
38      gen_be_u8!(FrameKind::BulkString.to_byte())
39        >> gen_slice!(&len[len_padding ..])
40        >> gen_slice!(CRLF.as_bytes())
41        >> gen_slice!(&buf[buf_padding ..])
42        >> gen_slice!(CRLF.as_bytes())
43    )
44  } else {
45    do_gen!(
46      x,
47      gen_be_u8!(FrameKind::Integer.to_byte()) >> gen_slice!(&buf[buf_padding ..]) >> gen_slice!(CRLF.as_bytes())
48    )
49  }
50}
51
52fn gen_bulkstring<'a>(x: (&'a mut [u8], usize), data: &[u8]) -> Result<(&'a mut [u8], usize), GenError> {
53  let (len, padding) = int2dec::u64_to_digits(data.len() as u64);
54
55  do_gen!(
56    x,
57    gen_be_u8!(FrameKind::BulkString.to_byte())
58      >> gen_slice!(&len[padding ..])
59      >> gen_slice!(CRLF.as_bytes())
60      >> gen_slice!(data)
61      >> gen_slice!(CRLF.as_bytes())
62  )
63}
64
65fn gen_null(x: (&mut [u8], usize)) -> Result<(&mut [u8], usize), GenError> {
66  do_gen!(x, gen_slice!(NULL.as_bytes()))
67}
68
69// The array encoding logic requires using one of the public frame types, but they each potentially require some
70// overhead to convert between. Converting from owned to bytes requires moving and adding a small ref counting layer
71// whereas converting the other direction most likely requires copying the contents. We could introduce a layer in the
72// middle that uses `&[u8]` and `&str` as the backing types, but even that would require an added `Vec` in the
73// intermediate frame's `Array` variant. For now, I'm just going to duplicate this function to avoid these tradeoffs.
74
75fn gen_owned_array<'a>(
76  x: (&'a mut [u8], usize),
77  data: &[OwnedFrame],
78  int_as_bulkstring: bool,
79) -> Result<(&'a mut [u8], usize), GenError> {
80  let (len, padding) = int2dec::u64_to_digits(data.len() as u64);
81  let mut x = do_gen!(
82    x,
83    gen_be_u8!(FrameKind::Array.to_byte()) >> gen_slice!(&len[padding ..]) >> gen_slice!(CRLF.as_bytes())
84  )?;
85
86  for frame in data.iter() {
87    x = match frame {
88      OwnedFrame::SimpleString(s) => gen_simplestring(x, s)?,
89      OwnedFrame::BulkString(b) => gen_bulkstring(x, b)?,
90      OwnedFrame::Null => gen_null(x)?,
91      OwnedFrame::Error(s) => gen_error(x, s)?,
92      OwnedFrame::Array(frames) => gen_owned_array(x, frames, int_as_bulkstring)?,
93      OwnedFrame::Integer(i) => gen_integer(x, *i, int_as_bulkstring)?,
94    };
95  }
96
97  // the trailing CRLF is added by the last inner value
98  Ok(x)
99}
100
101fn gen_borrowed_array<'a>(
102  x: (&'a mut [u8], usize),
103  data: &[BorrowedFrame],
104  int_as_bulkstring: bool,
105) -> Result<(&'a mut [u8], usize), GenError> {
106  let (len, padding) = int2dec::u64_to_digits(data.len() as u64);
107  let mut x = do_gen!(
108    x,
109    gen_be_u8!(FrameKind::Array.to_byte()) >> gen_slice!(&len[padding ..]) >> gen_slice!(CRLF.as_bytes())
110  )?;
111
112  for frame in data.iter() {
113    x = match frame {
114      BorrowedFrame::SimpleString(s) => gen_simplestring(x, s)?,
115      BorrowedFrame::BulkString(b) => gen_bulkstring(x, b)?,
116      BorrowedFrame::Null => gen_null(x)?,
117      BorrowedFrame::Error(s) => gen_error(x, s)?,
118      BorrowedFrame::Array(frames) => gen_borrowed_array(x, frames, int_as_bulkstring)?,
119      BorrowedFrame::Integer(i) => gen_integer(x, *i, int_as_bulkstring)?,
120    };
121  }
122
123  // the trailing CRLF is added by the last inner value
124  Ok(x)
125}
126
127#[cfg(feature = "bytes")]
128fn gen_bytes_array<'a>(
129  x: (&'a mut [u8], usize),
130  data: &[BytesFrame],
131  int_as_bulkstring: bool,
132) -> Result<(&'a mut [u8], usize), GenError> {
133  let (len, padding) = int2dec::u64_to_digits(data.len() as u64);
134  let mut x = do_gen!(
135    x,
136    gen_be_u8!(FrameKind::Array.to_byte()) >> gen_slice!(&len[padding ..]) >> gen_slice!(CRLF.as_bytes())
137  )?;
138
139  for frame in data.iter() {
140    x = match frame {
141      BytesFrame::SimpleString(ref s) => gen_simplestring(x, s)?,
142      BytesFrame::BulkString(ref b) => gen_bulkstring(x, b)?,
143      BytesFrame::Null => gen_null(x)?,
144      BytesFrame::Error(ref s) => gen_error(x, s)?,
145      BytesFrame::Array(ref frames) => gen_bytes_array(x, frames, int_as_bulkstring)?,
146      BytesFrame::Integer(ref i) => gen_integer(x, *i, int_as_bulkstring)?,
147    };
148  }
149
150  // the trailing CRLF is added by the last inner value
151  Ok(x)
152}
153
154fn gen_owned_frame(
155  buf: &mut [u8],
156  offset: usize,
157  frame: &OwnedFrame,
158  int_as_bulkstring: bool,
159) -> Result<usize, GenError> {
160  match frame {
161    OwnedFrame::BulkString(b) => gen_bulkstring((buf, offset), b).map(|(_, l)| l),
162    OwnedFrame::Null => gen_null((buf, offset)).map(|(_, l)| l),
163    OwnedFrame::Array(frames) => gen_owned_array((buf, offset), frames, int_as_bulkstring).map(|(_, l)| l),
164    OwnedFrame::Error(s) => gen_error((buf, offset), s).map(|(_, l)| l),
165    OwnedFrame::SimpleString(s) => gen_simplestring((buf, offset), s).map(|(_, l)| l),
166    OwnedFrame::Integer(i) => gen_integer((buf, offset), *i, int_as_bulkstring).map(|(_, l)| l),
167  }
168}
169
170fn gen_borrowed_frame(
171  buf: &mut [u8],
172  offset: usize,
173  frame: &BorrowedFrame,
174  int_as_bulkstring: bool,
175) -> Result<usize, GenError> {
176  match frame {
177    BorrowedFrame::BulkString(b) => gen_bulkstring((buf, offset), b).map(|(_, l)| l),
178    BorrowedFrame::Null => gen_null((buf, offset)).map(|(_, l)| l),
179    BorrowedFrame::Array(frames) => gen_borrowed_array((buf, offset), frames, int_as_bulkstring).map(|(_, l)| l),
180    BorrowedFrame::Error(s) => gen_error((buf, offset), s).map(|(_, l)| l),
181    BorrowedFrame::SimpleString(s) => gen_simplestring((buf, offset), s).map(|(_, l)| l),
182    BorrowedFrame::Integer(i) => gen_integer((buf, offset), *i, int_as_bulkstring).map(|(_, l)| l),
183  }
184}
185
186#[cfg(feature = "bytes")]
187fn gen_bytes_frame(
188  buf: &mut [u8],
189  offset: usize,
190  frame: &BytesFrame,
191  int_as_bulkstring: bool,
192) -> Result<usize, GenError> {
193  match frame {
194    BytesFrame::BulkString(b) => gen_bulkstring((buf, offset), b).map(|(_, l)| l),
195    BytesFrame::Null => gen_null((buf, offset)).map(|(_, l)| l),
196    BytesFrame::Array(frames) => gen_bytes_array((buf, offset), frames, int_as_bulkstring).map(|(_, l)| l),
197    BytesFrame::Error(s) => gen_error((buf, offset), s).map(|(_, l)| l),
198    BytesFrame::SimpleString(s) => gen_simplestring((buf, offset), s).map(|(_, l)| l),
199    BytesFrame::Integer(i) => gen_integer((buf, offset), *i, int_as_bulkstring).map(|(_, l)| l),
200  }
201}
202
203/// Attempt to encode a frame into `buf`.
204///
205/// The caller is responsible for extending `buf` if a `BufferTooSmall` error is returned.
206///
207/// Returns the number of bytes encoded.
208pub fn encode(buf: &mut [u8], frame: &OwnedFrame, int_as_bulkstring: bool) -> Result<usize, RedisProtocolError> {
209  encode_checks!(buf, 0, frame.encode_len(int_as_bulkstring));
210  gen_owned_frame(buf, 0, frame, int_as_bulkstring).map_err(|e| e.into())
211}
212
213/// Attempt to encode a borrowed frame into `buf`.
214///
215/// The caller is responsible for extending `buf` if a `BufferTooSmall` error is returned.
216///
217/// Returns the number of bytes encoded.
218pub fn encode_borrowed(
219  buf: &mut [u8],
220  frame: &BorrowedFrame,
221  int_as_bulkstring: bool,
222) -> Result<usize, RedisProtocolError> {
223  encode_checks!(buf, 0, frame.encode_len(int_as_bulkstring));
224  gen_borrowed_frame(buf, 0, frame, int_as_bulkstring).map_err(|e| e.into())
225}
226
227/// Attempt to encode a frame into `buf`.
228///
229/// The caller is responsible for extending `buf` if a `BufferTooSmall` error is returned.
230///
231/// Returns the number of bytes encoded.
232#[cfg(feature = "bytes")]
233#[cfg_attr(docsrs, doc(cfg(feature = "bytes")))]
234pub fn encode_bytes(
235  buf: &mut [u8],
236  frame: &BytesFrame,
237  int_as_bulkstring: bool,
238) -> Result<usize, RedisProtocolError> {
239  encode_checks!(buf, 0, frame.encode_len(int_as_bulkstring));
240  gen_bytes_frame(buf, 0, frame, int_as_bulkstring).map_err(|e| e.into())
241}
242
243/// Attempt to encode a frame at the end of `buf`, extending the buffer before encoding.
244///
245/// Returns the number of bytes encoded.
246#[cfg(feature = "bytes")]
247#[cfg_attr(docsrs, doc(cfg(feature = "bytes")))]
248pub fn extend_encode(
249  buf: &mut BytesMut,
250  frame: &BytesFrame,
251  int_as_bulkstring: bool,
252) -> Result<usize, RedisProtocolError> {
253  let amt = frame.encode_len(int_as_bulkstring);
254  let offset = buf.len();
255  utils::zero_extend(buf, amt);
256
257  gen_bytes_frame(buf, offset, frame, int_as_bulkstring).map_err(|e| e.into())
258}
259
260/// Attempt to encode a borrowed frame at the end of `buf`, extending the buffer before encoding.
261///
262/// Returns the number of bytes encoded.
263#[cfg(feature = "bytes")]
264#[cfg_attr(docsrs, doc(cfg(feature = "bytes")))]
265pub fn extend_encode_borrowed(
266  buf: &mut BytesMut,
267  frame: &BorrowedFrame,
268  int_as_bulkstring: bool,
269) -> Result<usize, RedisProtocolError> {
270  let amt = frame.encode_len(int_as_bulkstring);
271  let offset = buf.len();
272  utils::zero_extend(buf, amt);
273
274  gen_borrowed_frame(buf, offset, frame, int_as_bulkstring).map_err(|e| e.into())
275}
276
277// Regression tests duplicated for each frame type.
278
279#[cfg(test)]
280mod owned_tests {
281  use super::*;
282
283  fn encode_and_verify_empty(input: &OwnedFrame, expected: &str) {
284    let mut buf = vec![0; expected.len()];
285    let len = encode(&mut buf, input, false).unwrap();
286
287    assert_eq!(buf, expected.as_bytes(), "empty buf contents match");
288    assert_eq!(len, expected.as_bytes().len(), "empty expected len is correct");
289  }
290
291  fn encode_buf_and_verify_empty(input: &OwnedFrame, expected: &str) {
292    let mut buf = vec![0; expected.as_bytes().len()];
293    let len = encode(&mut buf, input, false).unwrap();
294
295    assert_eq!(buf, expected.as_bytes(), "empty buf contents match");
296    assert_eq!(len, expected.as_bytes().len(), "empty expected len is correct");
297  }
298
299  #[test]
300  fn should_encode_llen_req_example() {
301    let expected = "*2\r\n$4\r\nLLEN\r\n$6\r\nmylist\r\n";
302    let input = OwnedFrame::Array(vec![
303      OwnedFrame::BulkString("LLEN".into()),
304      OwnedFrame::BulkString("mylist".into()),
305    ]);
306
307    encode_and_verify_empty(&input, expected);
308  }
309
310  #[test]
311  fn should_encode_incr_req_example() {
312    let expected = "*2\r\n$4\r\nINCR\r\n$5\r\nmykey\r\n";
313    let input = OwnedFrame::Array(vec![
314      OwnedFrame::BulkString("INCR".into()),
315      OwnedFrame::BulkString("mykey".into()),
316    ]);
317
318    encode_and_verify_empty(&input, expected);
319  }
320
321  #[test]
322  fn should_encode_bitcount_req_example() {
323    let expected = "*2\r\n$8\r\nBITCOUNT\r\n$5\r\nmykey\r\n";
324    let input = OwnedFrame::Array(vec![
325      OwnedFrame::BulkString("BITCOUNT".into()),
326      OwnedFrame::BulkString("mykey".into()),
327    ]);
328
329    encode_and_verify_empty(&input, expected);
330  }
331
332  #[test]
333  fn should_encode_array_bulk_string_test() {
334    let expected = "*3\r\n$5\r\nWATCH\r\n$6\r\nWIBBLE\r\n$9\r\nfooBARbaz\r\n";
335    let input = OwnedFrame::Array(vec![
336      OwnedFrame::BulkString("WATCH".into()),
337      OwnedFrame::BulkString("WIBBLE".into()),
338      OwnedFrame::BulkString("fooBARbaz".into()),
339    ]);
340
341    encode_and_verify_empty(&input, expected);
342  }
343
344  #[test]
345  fn should_encode_array_null_test() {
346    let expected = "*3\r\n$4\r\nHSET\r\n$3\r\nfoo\r\n$-1\r\n";
347    let input = OwnedFrame::Array(vec![
348      OwnedFrame::BulkString("HSET".into()),
349      OwnedFrame::BulkString("foo".into()),
350      OwnedFrame::Null,
351    ]);
352
353    encode_and_verify_empty(&input, expected);
354  }
355
356  #[test]
357  fn should_encode_buf_llen_req_example() {
358    let expected = "*2\r\n$4\r\nLLEN\r\n$6\r\nmylist\r\n";
359    let input = OwnedFrame::Array(vec![
360      OwnedFrame::BulkString("LLEN".into()),
361      OwnedFrame::BulkString("mylist".into()),
362    ]);
363
364    encode_buf_and_verify_empty(&input, expected);
365  }
366
367  #[test]
368  fn should_encode_buf_incr_req_example() {
369    let expected = "*2\r\n$4\r\nINCR\r\n$5\r\nmykey\r\n";
370    let input = OwnedFrame::Array(vec![
371      OwnedFrame::BulkString("INCR".into()),
372      OwnedFrame::BulkString("mykey".into()),
373    ]);
374
375    encode_buf_and_verify_empty(&input, expected);
376  }
377
378  #[test]
379  fn should_encode_buf_bitcount_req_example() {
380    let expected = "*2\r\n$8\r\nBITCOUNT\r\n$5\r\nmykey\r\n";
381    let input = OwnedFrame::Array(vec![
382      OwnedFrame::BulkString("BITCOUNT".into()),
383      OwnedFrame::BulkString("mykey".into()),
384    ]);
385
386    encode_buf_and_verify_empty(&input, expected);
387  }
388
389  #[test]
390  fn should_encode_buf_array_bulk_string_test() {
391    let expected = "*3\r\n$5\r\nWATCH\r\n$6\r\nWIBBLE\r\n$9\r\nfooBARbaz\r\n";
392    let input = OwnedFrame::Array(vec![
393      OwnedFrame::BulkString("WATCH".into()),
394      OwnedFrame::BulkString("WIBBLE".into()),
395      OwnedFrame::BulkString("fooBARbaz".into()),
396    ]);
397
398    encode_buf_and_verify_empty(&input, expected);
399  }
400
401  #[test]
402  fn should_encode_buf_array_null_test() {
403    let expected = "*3\r\n$4\r\nHSET\r\n$3\r\nfoo\r\n$-1\r\n";
404    let input = OwnedFrame::Array(vec![
405      OwnedFrame::BulkString("HSET".into()),
406      OwnedFrame::BulkString("foo".into()),
407      OwnedFrame::Null,
408    ]);
409
410    encode_buf_and_verify_empty(&input, expected);
411  }
412
413  #[test]
414  fn should_encode_moved_error() {
415    let expected = "-MOVED 3999 127.0.0.1:6381\r\n";
416    let input = OwnedFrame::Error("MOVED 3999 127.0.0.1:6381".into());
417
418    encode_and_verify_empty(&input, expected);
419  }
420
421  #[test]
422  fn should_encode_ask_error() {
423    let expected = "-ASK 3999 127.0.0.1:6381\r\n";
424    let input = OwnedFrame::Error("ASK 3999 127.0.0.1:6381".into());
425
426    encode_and_verify_empty(&input, expected);
427  }
428
429  #[test]
430  fn should_encode_error() {
431    let expected = "-WRONGTYPE Operation against a key holding the wrong kind of value\r\n";
432    let input = OwnedFrame::Error("WRONGTYPE Operation against a key holding the wrong kind of value".into());
433
434    encode_and_verify_empty(&input, expected);
435  }
436
437  #[test]
438  fn should_encode_simplestring() {
439    let expected = "+OK\r\n";
440    let input = OwnedFrame::SimpleString("OK".into());
441
442    encode_and_verify_empty(&input, expected);
443  }
444
445  #[test]
446  fn should_encode_integer() {
447    let i1_expected = ":1000\r\n";
448    let i1_input = OwnedFrame::Integer(1000);
449
450    encode_and_verify_empty(&i1_input, i1_expected);
451  }
452
453  #[test]
454  fn should_encode_negative_integer() {
455    let i2_expected = ":-1000\r\n";
456    let i2_input = OwnedFrame::Integer(-1000);
457
458    encode_and_verify_empty(&i2_input, i2_expected);
459  }
460}
461
462#[cfg(test)]
463#[cfg(feature = "bytes")]
464mod bytes_tests {
465  use super::*;
466
467  const PADDING: &str = "foobar";
468
469  fn encode_and_verify_empty(input: &BytesFrame, expected: &str) {
470    let mut buf = BytesMut::new();
471    let len = extend_encode(&mut buf, input, false).unwrap();
472
473    assert_eq!(buf, expected.as_bytes(), "empty buf contents match");
474    assert_eq!(len, expected.as_bytes().len(), "empty expected len is correct");
475  }
476
477  fn encode_and_verify_non_empty(input: &BytesFrame, expected: &str) {
478    let mut buf = BytesMut::new();
479    buf.extend_from_slice(PADDING.as_bytes());
480
481    let len = extend_encode(&mut buf, input, false).unwrap();
482    let padded = [PADDING, expected].join("");
483
484    assert_eq!(buf, padded.as_bytes(), "padded buf contents match");
485    assert_eq!(len, padded.as_bytes().len(), "padded expected len is correct");
486  }
487
488  fn encode_buf_and_verify_empty(input: &BytesFrame, expected: &str) {
489    let mut buf = vec![0; expected.len()];
490    let len = encode_bytes(&mut buf, input, false).unwrap();
491
492    assert_eq!(buf, expected.as_bytes(), "empty buf contents match");
493    assert_eq!(len, expected.as_bytes().len(), "empty expected len is correct");
494  }
495
496  #[test]
497  fn should_encode_llen_req_example() {
498    let expected = "*2\r\n$4\r\nLLEN\r\n$6\r\nmylist\r\n";
499    let input = BytesFrame::Array(vec![
500      BytesFrame::BulkString("LLEN".into()),
501      BytesFrame::BulkString("mylist".into()),
502    ]);
503
504    encode_and_verify_empty(&input, expected);
505    encode_and_verify_non_empty(&input, expected);
506  }
507
508  #[test]
509  fn should_encode_incr_req_example() {
510    let expected = "*2\r\n$4\r\nINCR\r\n$5\r\nmykey\r\n";
511    let input = BytesFrame::Array(vec![
512      BytesFrame::BulkString("INCR".into()),
513      BytesFrame::BulkString("mykey".into()),
514    ]);
515
516    encode_and_verify_empty(&input, expected);
517    encode_and_verify_non_empty(&input, expected);
518  }
519
520  #[test]
521  fn should_encode_bitcount_req_example() {
522    let expected = "*2\r\n$8\r\nBITCOUNT\r\n$5\r\nmykey\r\n";
523    let input = BytesFrame::Array(vec![
524      BytesFrame::BulkString("BITCOUNT".into()),
525      BytesFrame::BulkString("mykey".into()),
526    ]);
527
528    encode_and_verify_empty(&input, expected);
529    encode_and_verify_non_empty(&input, expected);
530  }
531
532  #[test]
533  fn should_encode_array_bulk_string_test() {
534    let expected = "*3\r\n$5\r\nWATCH\r\n$6\r\nWIBBLE\r\n$9\r\nfooBARbaz\r\n";
535    let input = BytesFrame::Array(vec![
536      BytesFrame::BulkString("WATCH".into()),
537      BytesFrame::BulkString("WIBBLE".into()),
538      BytesFrame::BulkString("fooBARbaz".into()),
539    ]);
540
541    encode_and_verify_empty(&input, expected);
542    encode_and_verify_non_empty(&input, expected);
543  }
544
545  #[test]
546  fn should_encode_array_null_test() {
547    let expected = "*3\r\n$4\r\nHSET\r\n$3\r\nfoo\r\n$-1\r\n";
548    let input = BytesFrame::Array(vec![
549      BytesFrame::BulkString("HSET".into()),
550      BytesFrame::BulkString("foo".into()),
551      BytesFrame::Null,
552    ]);
553
554    encode_and_verify_empty(&input, expected);
555    encode_and_verify_non_empty(&input, expected);
556  }
557
558  #[test]
559  fn should_encode_buf_llen_req_example() {
560    let expected = "*2\r\n$4\r\nLLEN\r\n$6\r\nmylist\r\n";
561    let input = BytesFrame::Array(vec![
562      BytesFrame::BulkString("LLEN".into()),
563      BytesFrame::BulkString("mylist".into()),
564    ]);
565
566    encode_buf_and_verify_empty(&input, expected);
567  }
568
569  #[test]
570  fn should_encode_buf_incr_req_example() {
571    let expected = "*2\r\n$4\r\nINCR\r\n$5\r\nmykey\r\n";
572    let input = BytesFrame::Array(vec![
573      BytesFrame::BulkString("INCR".into()),
574      BytesFrame::BulkString("mykey".into()),
575    ]);
576
577    encode_buf_and_verify_empty(&input, expected);
578  }
579
580  #[test]
581  fn should_encode_buf_bitcount_req_example() {
582    let expected = "*2\r\n$8\r\nBITCOUNT\r\n$5\r\nmykey\r\n";
583    let input = BytesFrame::Array(vec![
584      BytesFrame::BulkString("BITCOUNT".into()),
585      BytesFrame::BulkString("mykey".into()),
586    ]);
587
588    encode_buf_and_verify_empty(&input, expected);
589  }
590
591  #[test]
592  fn should_encode_buf_array_bulk_string_test() {
593    let expected = "*3\r\n$5\r\nWATCH\r\n$6\r\nWIBBLE\r\n$9\r\nfooBARbaz\r\n";
594    let input = BytesFrame::Array(vec![
595      BytesFrame::BulkString("WATCH".into()),
596      BytesFrame::BulkString("WIBBLE".into()),
597      BytesFrame::BulkString("fooBARbaz".into()),
598    ]);
599
600    encode_buf_and_verify_empty(&input, expected);
601  }
602
603  #[test]
604  fn should_encode_buf_array_null_test() {
605    let expected = "*3\r\n$4\r\nHSET\r\n$3\r\nfoo\r\n$-1\r\n";
606    let input = BytesFrame::Array(vec![
607      BytesFrame::BulkString("HSET".into()),
608      BytesFrame::BulkString("foo".into()),
609      BytesFrame::Null,
610    ]);
611
612    encode_buf_and_verify_empty(&input, expected);
613  }
614
615  #[test]
616  fn should_encode_moved_error() {
617    let expected = "-MOVED 3999 127.0.0.1:6381\r\n";
618    let input = BytesFrame::Error("MOVED 3999 127.0.0.1:6381".into());
619
620    encode_and_verify_empty(&input, expected);
621    encode_and_verify_non_empty(&input, expected);
622  }
623
624  #[test]
625  fn should_encode_ask_error() {
626    let expected = "-ASK 3999 127.0.0.1:6381\r\n";
627    let input = BytesFrame::Error("ASK 3999 127.0.0.1:6381".into());
628
629    encode_and_verify_empty(&input, expected);
630    encode_and_verify_non_empty(&input, expected);
631  }
632
633  #[test]
634  fn should_encode_error() {
635    let expected = "-WRONGTYPE Operation against a key holding the wrong kind of value\r\n";
636    let input = BytesFrame::Error("WRONGTYPE Operation against a key holding the wrong kind of value".into());
637
638    encode_and_verify_empty(&input, expected);
639    encode_and_verify_non_empty(&input, expected);
640  }
641
642  #[test]
643  fn should_encode_simplestring() {
644    let expected = "+OK\r\n";
645    let input = BytesFrame::SimpleString("OK".into());
646
647    encode_and_verify_empty(&input, expected);
648    encode_and_verify_non_empty(&input, expected);
649  }
650
651  #[test]
652  fn should_encode_integer() {
653    let i1_expected = ":1000\r\n";
654    let i1_input = BytesFrame::Integer(1000);
655
656    encode_and_verify_empty(&i1_input, i1_expected);
657    encode_and_verify_non_empty(&i1_input, i1_expected);
658  }
659
660  #[test]
661  fn should_encode_negative_integer() {
662    let i2_expected = ":-1000\r\n";
663    let i2_input = BytesFrame::Integer(-1000);
664
665    encode_and_verify_empty(&i2_input, i2_expected);
666    encode_and_verify_non_empty(&i2_input, i2_expected);
667  }
668
669  #[test]
670  fn should_encode_integer_as_bulkstring() {
671    let i1_expected = "$4\r\n1000\r\n";
672    let i1_input = BytesFrame::Integer(1000);
673
674    let mut buf = BytesMut::new();
675    let len = extend_encode(&mut buf, &i1_input, true).unwrap();
676    assert_eq!(buf, i1_expected.as_bytes(), "empty buf contents match");
677    assert_eq!(len, i1_expected.as_bytes().len(), "empty expected len is correct");
678  }
679
680  #[test]
681  fn should_encode_negative_integer_as_bulkstring() {
682    let i2_expected = "$5\r\n-1000\r\n";
683    let i2_input = BytesFrame::Integer(-1000);
684
685    let mut buf = BytesMut::new();
686    let len = extend_encode(&mut buf, &i2_input, true).unwrap();
687    assert_eq!(buf, i2_expected.as_bytes(), "empty buf contents match");
688    assert_eq!(len, i2_expected.as_bytes().len(), "empty expected len is correct");
689
690    // test base10 overflow with `-` prefixes in the length prefix calculation
691    let i2_expected = "$10\r\n-999999999\r\n";
692    let i2_input = BytesFrame::Integer(-999999999);
693
694    let mut buf = BytesMut::new();
695    let len = extend_encode(&mut buf, &i2_input, true).unwrap();
696    assert_eq!(buf, i2_expected.as_bytes(), "empty buf contents match");
697    assert_eq!(len, i2_expected.as_bytes().len(), "empty expected len is correct");
698  }
699}