Skip to main content

mcmc_rs/
lib.rs

1//! Minimal Rust client for Memcached
2//!
3//! This crate provides working with memcached server.
4//! All methods implemented.
5//! Available TCP/Unix/UDP/TLS connections.
6//!
7//! - [Connection] is a Enum that represents a
8//!   connection to memcached server.
9//! - [Pipeline] is a structure that represents a
10//!   pipeline of memcached commands.
11//! - [WatchStream] is a structure that represents a
12//!   stream of watch events.
13//! - [ClientCrc32] is a structure that represents a
14//!   Cluster connections with ModN hashing.
15//! - [ClientHashRing] is a structure that represents a
16//!   Cluster connections with Ring hashing.
17//! - [ClientRendezvous] is a structure that represents a
18//!   Cluster connections with Rendezvous hashing.
19//!
20//! # Examples
21//!
22//! ```
23//! use smol::{block_on, io};
24//!
25//! use mcmc_rs::Connection;
26//!
27//! fn main() -> io::Result<()> {
28//!     block_on(async {
29//!         let mut conn = Connection::default().await?;
30//!         conn.set(b"key", 0, 0, false, b"value").await?;
31//!         let item = conn.get(b"key").await?.unwrap();
32//!         println!("{item:#?}");
33//!         Ok(())
34//!     })
35//! }
36//! ```
37
38use std::collections::HashMap;
39use std::io::Write;
40
41use async_native_tls::{Certificate, TlsConnector, TlsStream};
42use crc32fast::hash as crc32;
43use deadpool::managed;
44use hashring::HashRing;
45use hrw_hash::HrwNodes;
46
47#[cfg(all(feature = "smol-runtime", feature = "tokio-runtime"))]
48compile_error!(
49    "feature \"smol-runtime\" and feature \"tokio-runtime\" cannot be enabled at the same time"
50);
51#[cfg(feature = "smol-runtime")]
52mod rt {
53    pub use smol::fs;
54    pub use smol::io::{self, BufReader, Cursor};
55    pub use smol::net::{TcpStream, UdpSocket, unix::UnixStream};
56    pub use smol::prelude::*;
57}
58#[cfg(feature = "tokio-runtime")]
59mod rt {
60    pub use std::io::Cursor;
61    pub use tokio::fs;
62    pub use tokio::io::{
63        self, AsyncBufRead, AsyncBufReadExt, AsyncReadExt, AsyncWrite, AsyncWriteExt, BufReader,
64    };
65    pub use tokio::net::{TcpStream, UdpSocket, UnixStream};
66}
67use rt::*;
68
69pub enum AddrArg<'a> {
70    Tcp(&'a str),
71    Unix(&'a str),
72    Udp(&'a str, &'a str),
73    Tls(&'a str, u16, &'a str),
74}
75
76pub struct Manager<'a>(AddrArg<'a>);
77impl<'a> Manager<'a> {
78    /// # Example
79    ///
80    /// ```
81    /// use mcmc_rs::{AddrArg, Manager, Pool};
82    /// # use smol::{io, block_on};
83    /// #
84    /// # block_on(async {
85    /// for a in [
86    ///     AddrArg::Tcp("127.0.0.1:11211"),
87    ///     AddrArg::Unix("/tmp/memcached0.sock"),
88    ///     AddrArg::Udp("127.0.0.1:0", "127.0.0.1:11214"),
89    ///     AddrArg::Tls("localhost", 11216, "cert.pem"),
90    /// ] {
91    ///     let mgr = Manager::new(a);
92    ///     let pool = Pool::builder(mgr).build().unwrap();
93    ///     let mut conn = pool.get().await.unwrap();
94    ///     let result = conn.version().await?;
95    ///     assert!(result.chars().any(|x| x.is_numeric()));
96    /// }
97    /// #     Ok::<(), io::Error>(())
98    /// # }).unwrap()
99    /// ```
100    pub fn new(addr: AddrArg<'a>) -> Self {
101        Self(addr)
102    }
103}
104
105impl<'a> managed::Manager for Manager<'a> {
106    type Type = Connection;
107    type Error = io::Error;
108
109    async fn create(&self) -> Result<Connection, io::Error> {
110        match self.0 {
111            AddrArg::Tcp(addr) => Connection::tcp_connect(addr).await,
112            AddrArg::Unix(addr) => Connection::unix_connect(addr).await,
113            AddrArg::Udp(bind_addr, connect_addr) => {
114                Connection::udp_connect(bind_addr, connect_addr).await
115            }
116            AddrArg::Tls(hostname, port, ca_path) => {
117                Connection::tls_connect(hostname, port, ca_path).await
118            }
119        }
120    }
121
122    async fn recycle(
123        &self,
124        conn: &mut Connection,
125        _: &managed::Metrics,
126    ) -> managed::RecycleResult<io::Error> {
127        match conn.version().await {
128            Ok(_) => Ok(()),
129            Err(e) => Err(e.into()),
130        }
131    }
132}
133
134pub type Pool<'a> = managed::Pool<Manager<'a>>;
135
136pub enum StatsArg {
137    Settings,
138    Items,
139    Sizes,
140    Slabs,
141    Conns,
142}
143
144pub enum SlabsAutomoveArg {
145    Zero,
146    One,
147    Two,
148}
149
150pub enum LruCrawlerArg {
151    Enable,
152    Disable,
153}
154
155pub enum LruCrawlerCrawlArg<'a> {
156    Classids(&'a [usize]),
157    All,
158}
159
160pub enum LruCrawlerMetadumpArg<'a> {
161    Classids(&'a [usize]),
162    All,
163    Hash,
164}
165
166pub enum LruCrawlerMgdumpArg<'a> {
167    Classids(&'a [usize]),
168    All,
169    Hash,
170}
171
172pub enum WatchArg {
173    Fetchers,
174    Mutations,
175    Evictions,
176    Connevents,
177    Proxyreqs,
178    Proxyevents,
179    Proxyuser,
180    Deletions,
181}
182
183pub enum LruMode {
184    Flat,
185    Segmented,
186}
187
188pub enum LruArg {
189    Tune {
190        percent_hot: u8,
191        percent_warm: u8,
192        max_hot_factor: f32,
193        max_warm_factor: f32,
194    },
195    Mode(LruMode),
196    TempTtl(i64),
197}
198
199#[derive(Debug, PartialEq)]
200pub struct Item {
201    pub key: String,
202    pub flags: u32,
203    pub cas_unique: Option<u64>,
204    pub data_block: Vec<u8>,
205}
206
207#[derive(Debug, PartialEq)]
208pub enum PipelineResponse {
209    Bool(bool),
210    OptionItem(Option<Item>),
211    VecItem(Vec<Item>),
212    String(String),
213    OptionString(Option<String>),
214    VecString(Vec<String>),
215    Unit(()),
216    Value(Option<u64>),
217    HashMap(HashMap<String, String>),
218    MetaGet(MgItem),
219    MetaSet(MsItem),
220    MetaDelete(MdItem),
221    MetaArithmetic(MaItem),
222}
223
224pub enum MsMode {
225    Add,
226    Append,
227    Prepend,
228    Replace,
229    Set,
230}
231
232pub enum MaMode {
233    Incr,
234    Decr,
235}
236
237pub enum MsFlag {
238    Base64Key,
239    ReturnCas,
240    CompareCas(u64),
241    NewCas(u64),
242    SetFlags(u32),
243    Invalidate,
244    ReturnKey,
245    Opaque(String),
246    ReturnSize,
247    Ttl(i64),
248    Mode(MsMode),
249    Autovivify(i64),
250}
251
252pub enum MgFlag {
253    Base64Key,
254    ReturnCas,
255    CheckCas(u64),
256    ReturnFlags,
257    ReturnHit,
258    ReturnKey,
259    ReturnLastAccess,
260    Opaque(String),
261    ReturnSize,
262    ReturnTtl,
263    UnBump,
264    ReturnValue,
265    NewCas(u64),
266    Autovivify(i64),
267    RecacheTtl(i64),
268    UpdateTtl(i64),
269}
270
271pub enum MdFlag {
272    Base64Key,
273    CompareCas(u64),
274    NewCas(u64),
275    Invalidate,
276    ReturnKey,
277    Opaque(String),
278    UpdateTtl(i64),
279    LeaveKey,
280}
281
282pub enum MaFlag {
283    Base64Key,
284    CompareCas(u64),
285    NewCas(u64),
286    AutoCreate(i64),
287    InitValue(u64),
288    DeltaApply(u64),
289    UpdateTtl(i64),
290    Mode(MaMode),
291    Opaque(String),
292    ReturnTtl,
293    ReturnCas,
294    ReturnValue,
295    ReturnKey,
296}
297
298#[derive(Debug, PartialEq)]
299pub struct MgItem {
300    pub success: bool,
301    pub base64_key: bool,
302    pub cas: Option<u64>,
303    pub flags: Option<u32>,
304    pub hit: Option<u8>,
305    pub key: Option<String>,
306    pub last_access_ttl: Option<i64>,
307    pub opaque: Option<String>,
308    pub size: Option<usize>,
309    pub ttl: Option<i64>,
310    pub data_block: Option<Vec<u8>>,
311    pub won_recache: bool,
312    pub stale: bool,
313    pub already_win: bool,
314}
315
316#[derive(Debug, PartialEq)]
317pub struct MsItem {
318    pub success: bool,
319    pub cas: Option<u64>,
320    pub key: Option<String>,
321    pub opaque: Option<String>,
322    pub size: Option<usize>,
323    pub base64_key: bool,
324}
325
326#[derive(Debug, PartialEq)]
327pub struct MdItem {
328    pub success: bool,
329    pub key: Option<String>,
330    pub opaque: Option<String>,
331    pub base64_key: bool,
332}
333
334#[derive(Debug, PartialEq)]
335pub struct MaItem {
336    pub success: bool,
337    pub opaque: Option<String>,
338    pub ttl: Option<i64>,
339    pub cas: Option<u64>,
340    pub number: Option<u64>,
341    pub key: Option<String>,
342    pub base64_key: bool,
343}
344
345async fn parse_storage_rp<S: AsyncBufRead + AsyncWrite + Unpin>(
346    s: &mut S,
347    noreply: bool,
348) -> io::Result<bool> {
349    if noreply {
350        return Ok(true);
351    }
352    let mut line = String::new();
353    s.read_line(&mut line).await?;
354    match line.as_str() {
355        "STORED\r\n" => Ok(true),
356        "NOT_STORED\r\n" | "EXISTS\r\n" | "NOT_FOUND\r\n" => Ok(false),
357        _ => Err(io::Error::other(line)),
358    }
359}
360
361async fn parse_retrieval_rp<S: AsyncBufRead + AsyncWrite + Unpin>(
362    s: &mut S,
363) -> io::Result<Vec<Item>> {
364    let mut line = String::new();
365    s.read_line(&mut line).await?;
366    let mut items = Vec::new();
367    while line.starts_with("VALUE") {
368        let mut split = line.split(' ');
369        split.next();
370        let (key, flags, bytes, cas_unique) = (
371            split.next().unwrap().to_string(),
372            split.next().unwrap().parse().unwrap(),
373            split.next().unwrap().trim_end().parse().unwrap(),
374            split.next().map(|x| x.trim_end().parse().unwrap()),
375        );
376        let mut data_block = vec![0; bytes + 2];
377        s.read_exact(&mut data_block).await?;
378        data_block.truncate(bytes);
379        items.push(Item {
380            key,
381            flags,
382            cas_unique,
383            data_block,
384        });
385        line.clear();
386        s.read_line(&mut line).await?;
387    }
388    if line == "END\r\n" {
389        Ok(items)
390    } else {
391        Err(io::Error::other(line))
392    }
393}
394
395async fn parse_version_rp<S: AsyncBufRead + AsyncWrite + Unpin>(s: &mut S) -> io::Result<String> {
396    let mut line = String::new();
397    let n = s.read_line(&mut line).await?;
398    if line.starts_with("VERSION") {
399        Ok(line[8..n - 2].to_string())
400    } else {
401        Err(io::Error::other(line))
402    }
403}
404
405async fn parse_ok_rp<S: AsyncBufRead + AsyncWrite + Unpin>(
406    s: &mut S,
407    noreply: bool,
408) -> io::Result<()> {
409    if noreply {
410        return Ok(());
411    }
412    let mut line = String::new();
413    s.read_line(&mut line).await?;
414    if line == "OK\r\n" {
415        Ok(())
416    } else {
417        Err(io::Error::other(line))
418    }
419}
420
421async fn parse_delete_rp<S: AsyncBufRead + AsyncWrite + Unpin>(
422    s: &mut S,
423    noreply: bool,
424) -> io::Result<bool> {
425    if noreply {
426        return Ok(true);
427    }
428    let mut line = String::new();
429    s.read_line(&mut line).await?;
430    match line.as_str() {
431        "DELETED\r\n" => Ok(true),
432        "NOT_FOUND\r\n" => Ok(false),
433        _ => Err(io::Error::other(line)),
434    }
435}
436
437async fn parse_auth_rp<S: AsyncBufRead + AsyncWrite + Unpin>(s: &mut S) -> io::Result<()> {
438    let mut line = String::new();
439    s.read_line(&mut line).await?;
440    match line.as_str() {
441        "STORED\r\n" => Ok(()),
442        _ => Err(io::Error::other(line)),
443    }
444}
445
446async fn parse_incr_decr_rp<S: AsyncBufRead + AsyncWrite + Unpin>(
447    s: &mut S,
448    noreply: bool,
449) -> io::Result<Option<u64>> {
450    if noreply {
451        return Ok(None);
452    }
453    let mut line = String::new();
454    s.read_line(&mut line).await?;
455    if line == "NOT_FOUND\r\n" {
456        return Ok(None);
457    }
458    match line.trim_end().parse() {
459        Ok(v) => Ok(Some(v)),
460        Err(_) => Err(io::Error::other(line)),
461    }
462}
463
464async fn parse_touch_rp<S: AsyncBufRead + AsyncWrite + Unpin>(
465    s: &mut S,
466    noreply: bool,
467) -> io::Result<bool> {
468    if noreply {
469        return Ok(true);
470    }
471    let mut line = String::new();
472    s.read_line(&mut line).await?;
473    if line == "TOUCHED\r\n" {
474        Ok(true)
475    } else if line == "NOT_FOUND\r\n" {
476        Ok(false)
477    } else {
478        Err(io::Error::other(line))
479    }
480}
481
482async fn parse_stats_rp<S: AsyncBufRead + AsyncWrite + Unpin>(
483    s: &mut S,
484) -> io::Result<HashMap<String, String>> {
485    let mut items = HashMap::new();
486    let mut data = String::new();
487    s.read_line(&mut data).await?;
488    while data != "END\r\n" {
489        if data.starts_with("STAT") {
490            let mut split = data.split(' ');
491            split.next();
492            let (k, v) = (
493                split.next().unwrap().to_string(),
494                split.next().unwrap().trim_end().to_string(),
495            );
496            items.insert(k, v);
497            data.clear();
498            s.read_line(&mut data).await?;
499        } else {
500            return Err(io::Error::other(data));
501        }
502    }
503    Ok(items)
504}
505
506async fn parse_lru_crawler_metadump_rp<S: AsyncBufRead + AsyncWrite + Unpin>(
507    s: &mut S,
508) -> io::Result<Vec<String>> {
509    let mut line = String::new();
510    s.read_line(&mut line).await?;
511    let mut items = Vec::new();
512    while line.starts_with("key=") {
513        items.push(line.trim_end().to_string());
514        line.clear();
515        s.read_line(&mut line).await?;
516    }
517    if line == "END\r\n" {
518        Ok(items)
519    } else {
520        Err(io::Error::other(line))
521    }
522}
523
524async fn parse_lru_crawler_mgdump_rp<S: AsyncBufRead + AsyncWrite + Unpin>(
525    s: &mut S,
526) -> io::Result<Vec<String>> {
527    let mut line = String::new();
528    s.read_line(&mut line).await?;
529    let mut items = Vec::new();
530    while line.starts_with("mg ") {
531        let mut split = line.split(' ');
532        split.next();
533        items.push(split.next().unwrap().trim_end().to_string());
534        line.clear();
535        s.read_line(&mut line).await?;
536    }
537    if line == "EN\r\n" {
538        Ok(items)
539    } else {
540        Err(io::Error::other(line))
541    }
542}
543
544async fn parse_mn_rp<S: AsyncBufRead + AsyncWrite + Unpin>(s: &mut S) -> io::Result<()> {
545    let mut line = String::new();
546    s.read_line(&mut line).await?;
547    if line == "MN\r\n" {
548        Ok(())
549    } else {
550        Err(io::Error::other(line))
551    }
552}
553
554async fn parse_me_rp<S: AsyncBufRead + AsyncWrite + Unpin>(
555    s: &mut S,
556) -> io::Result<Option<String>> {
557    let mut line = String::new();
558    let n = s.read_line(&mut line).await?;
559    if line == "EN\r\n" {
560        Ok(None)
561    } else if line.starts_with("ME") {
562        Ok(Some(line[3..n - 2].to_string()))
563    } else {
564        Err(io::Error::other(line))
565    }
566}
567
568async fn parse_mg_rp<S: AsyncBufRead + AsyncWrite + Unpin>(s: &mut S) -> io::Result<MgItem> {
569    let mut line = String::new();
570    s.read_line(&mut line).await?;
571    let success;
572    let (
573        mut base64_key,
574        mut cas,
575        mut flags,
576        mut hit,
577        mut key,
578        mut last_access_ttl,
579        mut opaque,
580        mut size,
581        mut ttl,
582        mut data_block,
583        mut won_recache,
584        mut stale,
585        mut already_win,
586    ) = (
587        false, None, None, None, None, None, None, None, None, None, false, false, false,
588    );
589    let mut split = line.trim_end().split(' ');
590    let data_len = if line.starts_with("VA") {
591        success = true;
592        split.next();
593        Some(split.next().unwrap().parse().unwrap())
594    } else if line.starts_with("HD") {
595        success = true;
596        split.next();
597        None
598    } else if line.starts_with("EN") {
599        success = false;
600        split.next();
601        None
602    } else {
603        return Err(io::Error::other(line));
604    };
605    for flag in split {
606        let f = &flag[1..];
607        match &flag[..1] {
608            "b" => base64_key = true,
609            "c" => cas = Some(f.parse().unwrap()),
610            "f" => flags = Some(f.parse().unwrap()),
611            "h" => hit = Some(f.parse().unwrap()),
612            "k" => key = Some(f.to_string()),
613            "l" => last_access_ttl = Some(f.parse().unwrap()),
614            "O" => opaque = Some(f.to_string()),
615            "s" => size = Some(f.parse().unwrap()),
616            "t" => ttl = Some(f.parse().unwrap()),
617            "W" => won_recache = true,
618            "X" => stale = true,
619            "Z" => already_win = true,
620            other => unreachable!("unexpected mg flag: {other}"),
621        }
622    }
623    if let Some(a) = data_len {
624        let mut buf = vec![0; a + 2];
625        s.read_exact(&mut buf).await?;
626        buf.truncate(a);
627        data_block = Some(buf);
628    }
629    Ok(MgItem {
630        success,
631        base64_key,
632        cas,
633        flags,
634        hit,
635        key,
636        last_access_ttl,
637        opaque,
638        size,
639        ttl,
640        data_block,
641        won_recache,
642        stale,
643        already_win,
644    })
645}
646
647async fn parse_ms_rp<S: AsyncBufRead + AsyncWrite + Unpin>(s: &mut S) -> io::Result<MsItem> {
648    let mut line = String::new();
649    s.read_line(&mut line).await?;
650    let success;
651    let (mut cas, mut key, mut opaque, mut size, mut base64_key) = (None, None, None, None, false);
652    if line.starts_with("HD") {
653        success = true
654    } else if line.starts_with("NS") || line.starts_with("EX") || line.starts_with("NF") {
655        success = false
656    } else {
657        return Err(io::Error::other(line));
658    }
659    let mut split = line.trim_end().split(' ');
660    split.next();
661    for flag in split {
662        let f = &flag[1..];
663        match &flag[..1] {
664            "c" => cas = Some(f.parse().unwrap()),
665            "k" => key = Some(f.to_string()),
666            "O" => opaque = Some(f.to_string()),
667            "s" => size = Some(f.parse().unwrap()),
668            "b" => base64_key = true,
669            other => unreachable!("unexpected ms flag: {other}"),
670        }
671    }
672    Ok(MsItem {
673        success,
674        cas,
675        opaque,
676        key,
677        size,
678        base64_key,
679    })
680}
681
682async fn parse_md_rp<S: AsyncBufRead + AsyncWrite + Unpin>(s: &mut S) -> io::Result<MdItem> {
683    let mut line = String::new();
684    s.read_line(&mut line).await?;
685    let success;
686    let (mut key, mut opaque, mut base64_key) = (None, None, false);
687    if line.starts_with("HD") {
688        success = true
689    } else if line.starts_with("NF") || line.starts_with("EX") {
690        success = false
691    } else {
692        return Err(io::Error::other(line));
693    }
694    let mut split = line.trim_end().split(' ');
695    split.next();
696    for flag in split {
697        let f = &flag[1..];
698        match &flag[..1] {
699            "k" => key = Some(f.to_string()),
700            "O" => opaque = Some(f.to_string()),
701            "b" => base64_key = true,
702            other => unreachable!("unexpected md flag: {other}"),
703        }
704    }
705    Ok(MdItem {
706        success,
707        key,
708        opaque,
709        base64_key,
710    })
711}
712
713async fn parse_ma_rp<S: AsyncBufRead + AsyncWrite + Unpin>(s: &mut S) -> io::Result<MaItem> {
714    let mut line = String::new();
715    s.read_line(&mut line).await?;
716    let success;
717    let (mut opaque, mut ttl, mut cas, mut number, mut key, mut base64_key) =
718        (None, None, None, None, None, false);
719    let mut split = line.trim_end().split(' ');
720    let data_len = if line.starts_with("VA") {
721        split.next();
722        success = true;
723        Some(split.next().unwrap().parse().unwrap())
724    } else if line.starts_with("HD") {
725        split.next();
726        success = true;
727        None
728    } else if line.starts_with("NS") || line.starts_with("EX") || line.starts_with("NF") {
729        split.next();
730        success = false;
731        None
732    } else {
733        return Err(io::Error::other(line));
734    };
735    for flag in split {
736        let f = &flag[1..];
737        match &flag[..1] {
738            "O" => opaque = Some(f.to_string()),
739            "t" => ttl = Some(f.parse().unwrap()),
740            "c" => cas = Some(f.parse().unwrap()),
741            "k" => key = Some(f.to_string()),
742            "b" => base64_key = true,
743            other => unreachable!("unexpected ma flag: {other}"),
744        }
745    }
746    if let Some(a) = data_len {
747        let mut buf = String::with_capacity(a + 2);
748        s.read_line(&mut buf).await?;
749        buf.truncate(a);
750        number = Some(buf.parse().unwrap());
751    }
752    Ok(MaItem {
753        success,
754        opaque,
755        ttl,
756        cas,
757        number,
758        key,
759        base64_key,
760    })
761}
762
763fn build_storage_cmd(
764    command_name: &[u8],
765    key: &[u8],
766    flags: u32,
767    exptime: i64,
768    cas_unique: Option<u64>,
769    noreply: bool,
770    data_block: &[u8],
771) -> Vec<u8> {
772    let mut w = Vec::from(command_name);
773    w.push(b' ');
774    w.extend(key);
775    w.push(b' ');
776    write!(&mut w, "{flags} {exptime} {}", data_block.len()).unwrap();
777    if let Some(x) = cas_unique {
778        write!(&mut w, " {x}").unwrap()
779    }
780    if noreply {
781        w.extend(b" noreply")
782    }
783    w.extend(b"\r\n");
784    w.extend(data_block);
785    w.extend(b"\r\n");
786    w
787}
788
789fn build_retrieval_cmd(command_name: &[u8], exptime: Option<i64>, keys: &[&[u8]]) -> Vec<u8> {
790    let mut w = Vec::from(command_name);
791    if let Some(x) = exptime {
792        write!(&mut w, " {x}").unwrap()
793    }
794    keys.iter().for_each(|&x| {
795        w.push(b' ');
796        w.extend(x)
797    });
798    w.extend(b"\r\n");
799    w
800}
801
802fn build_version_cmd() -> &'static [u8] {
803    b"version\r\n"
804}
805
806fn build_quit_cmd() -> &'static [u8] {
807    b"quit\r\n"
808}
809
810fn build_shutdown_cmd(graceful: bool) -> &'static [u8] {
811    if graceful {
812        b"shutdown graceful\r\n"
813    } else {
814        b"shutdown\r\n"
815    }
816}
817
818fn build_cache_memlimit_cmd(limit: usize, noreply: bool) -> Vec<u8> {
819    let mut w = Vec::new();
820    write!(
821        &mut w,
822        "cache_memlimit {limit}{}\r\n",
823        if noreply { " noreply" } else { "" }
824    )
825    .unwrap();
826    w
827}
828
829fn build_flush_all_cmd(exptime: Option<i64>, noreply: bool) -> Vec<u8> {
830    let mut w = Vec::from(b"flush_all");
831    if let Some(x) = exptime {
832        write!(&mut w, " {x}").unwrap()
833    }
834    if noreply {
835        w.extend(b" noreply")
836    }
837    w.extend(b"\r\n");
838    w
839}
840
841fn build_delete_cmd(key: &[u8], noreply: bool) -> Vec<u8> {
842    let mut w = Vec::from(b"delete ");
843    w.extend(key);
844    if noreply {
845        w.extend(b" noreply")
846    }
847    w.extend(b"\r\n");
848    w
849}
850
851fn build_auth_cmd(username: &[u8], password: &[u8]) -> Vec<u8> {
852    let mut w = Vec::new();
853    write!(
854        &mut w,
855        "set _ _ _ {}\r\n",
856        username.len() + password.len() + 1
857    )
858    .unwrap();
859    w.extend(username);
860    w.push(b' ');
861    w.extend(password);
862    w.extend(b"\r\n");
863    w
864}
865
866fn build_incr_decr_cmd(command_name: &[u8], key: &[u8], value: u64, noreply: bool) -> Vec<u8> {
867    let mut w = Vec::from(command_name);
868    w.push(b' ');
869    w.extend(key);
870    write!(
871        &mut w,
872        " {value}{}\r\n",
873        if noreply { " noreply" } else { "" }
874    )
875    .unwrap();
876    w
877}
878
879fn build_touch_cmd(key: &[u8], exptime: i64, noreply: bool) -> Vec<u8> {
880    let mut w = Vec::from(b"touch ");
881    w.extend(key);
882    write!(
883        &mut w,
884        " {exptime}{}\r\n",
885        if noreply { " noreply" } else { "" }
886    )
887    .unwrap();
888    w
889}
890
891fn build_stats_cmd(arg: Option<StatsArg>) -> &'static [u8] {
892    match arg {
893        Some(a) => match a {
894            StatsArg::Settings => b"stats settings\r\n",
895            StatsArg::Items => b"stats items\r\n",
896            StatsArg::Sizes => b"stats sizes\r\n",
897            StatsArg::Slabs => b"stats slabs\r\n",
898            StatsArg::Conns => b"stats conns\r\n",
899        },
900        None => b"stats\r\n",
901    }
902}
903
904fn build_slabs_automove_cmd(arg: SlabsAutomoveArg) -> &'static [u8] {
905    match arg {
906        SlabsAutomoveArg::Zero => b"slabs automove 0\r\n",
907        SlabsAutomoveArg::One => b"slabs automove 1\r\n",
908        SlabsAutomoveArg::Two => b"slabs automove 2\r\n",
909    }
910}
911
912fn build_lru_crawler_cmd(arg: LruCrawlerArg) -> &'static [u8] {
913    match arg {
914        LruCrawlerArg::Enable => b"lru_crawler enable\r\n",
915        LruCrawlerArg::Disable => b"lru_crawler disable\r\n",
916    }
917}
918
919fn build_lru_clawler_sleep_cmd(microseconds: usize) -> Vec<u8> {
920    let mut w = Vec::new();
921    write!(&mut w, "lru_crawler sleep {microseconds}\r\n").unwrap();
922    w
923}
924
925fn build_lru_crawler_tocrawl_cmd(arg: u32) -> Vec<u8> {
926    let mut w = Vec::new();
927    write!(&mut w, "lru_crawler tocrawl {arg}\r\n").unwrap();
928    w
929}
930
931fn build_lru_clawler_crawl_cmd(arg: LruCrawlerCrawlArg) -> Vec<u8> {
932    let mut w = Vec::from(b"lru_crawler crawl ");
933    match arg {
934        LruCrawlerCrawlArg::Classids(ids) => ids.iter().enumerate().for_each(|(index, id)| {
935            if index == 0 {
936                write!(&mut w, "{}", id).unwrap()
937            } else {
938                write!(&mut w, ",{}", id).unwrap()
939            }
940        }),
941        LruCrawlerCrawlArg::All => w.extend(b"all"),
942    }
943    w.extend(b"\r\n");
944    w
945}
946
947fn build_slabs_reassign_cmd(source_class: isize, dest_class: isize) -> Vec<u8> {
948    let mut w = Vec::new();
949    write!(&mut w, "slabs reassign {source_class} {dest_class}\r\n").unwrap();
950    w
951}
952
953fn build_lru_clawler_metadump_cmd(arg: LruCrawlerMetadumpArg) -> Vec<u8> {
954    let mut w = Vec::from(b"lru_crawler metadump ");
955    match arg {
956        LruCrawlerMetadumpArg::Classids(ids) => ids.iter().enumerate().for_each(|(index, id)| {
957            if index == 0 {
958                write!(&mut w, "{}", id).unwrap()
959            } else {
960                write!(&mut w, ",{}", id).unwrap()
961            }
962        }),
963        LruCrawlerMetadumpArg::All => w.extend(b"all"),
964        LruCrawlerMetadumpArg::Hash => w.extend(b"hash"),
965    }
966    w.extend(b"\r\n");
967    w
968}
969
970fn build_lru_clawler_mgdump_cmd(arg: LruCrawlerMgdumpArg) -> Vec<u8> {
971    let mut w = Vec::from(b"lru_crawler mgdump ");
972    match arg {
973        LruCrawlerMgdumpArg::Classids(ids) => ids.iter().enumerate().for_each(|(index, id)| {
974            if index == 0 {
975                write!(&mut w, "{}", id).unwrap()
976            } else {
977                write!(&mut w, ",{}", id).unwrap()
978            }
979        }),
980        LruCrawlerMgdumpArg::All => w.extend(b"all"),
981        LruCrawlerMgdumpArg::Hash => w.extend(b"hash"),
982    }
983    w.extend(b"\r\n");
984    w
985}
986
987fn build_mn_cmd() -> &'static [u8] {
988    b"mn\r\n"
989}
990
991fn build_me_cmd(key: &[u8]) -> Vec<u8> {
992    let mut w = Vec::from(b"me ");
993    w.extend(key);
994    w.extend(b"\r\n");
995    w
996}
997
998fn build_watch_cmd(arg: &[WatchArg]) -> Vec<u8> {
999    let mut w = Vec::from(b"watch");
1000    arg.iter().for_each(|a| {
1001        w.extend(match a {
1002            WatchArg::Fetchers => b" fetchers".as_slice(),
1003            WatchArg::Mutations => b" mutations",
1004            WatchArg::Evictions => b" evictions",
1005            WatchArg::Connevents => b" connevents",
1006            WatchArg::Proxyreqs => b" proxyreqs",
1007            WatchArg::Proxyevents => b" proxyevents",
1008            WatchArg::Proxyuser => b" proxyuser",
1009            WatchArg::Deletions => b" deletions",
1010        })
1011    });
1012    w.extend(b"\r\n");
1013    w
1014}
1015
1016fn build_mc_cmd(
1017    command_name: &[u8],
1018    key: &[u8],
1019    flags: &[u8],
1020    data_block: Option<&[u8]>,
1021) -> Vec<u8> {
1022    let mut w = Vec::from(command_name);
1023    w.push(b' ');
1024    w.extend(key);
1025    if let Some(x) = data_block {
1026        write!(&mut w, " {}", x.len()).unwrap();
1027        w.extend(flags);
1028        w.extend(b"\r\n");
1029        w.extend(x);
1030        w.extend(b"\r\n");
1031    } else {
1032        w.extend(flags);
1033        w.extend(b"\r\n");
1034    }
1035    w
1036}
1037
1038fn build_ms_flags(flags: &[MsFlag]) -> Vec<u8> {
1039    let mut w = Vec::new();
1040    flags.iter().for_each(|x| match x {
1041        MsFlag::Base64Key => w.extend(b" b"),
1042        MsFlag::ReturnCas => w.extend(b" c"),
1043        MsFlag::CompareCas(token) => write!(&mut w, " C{token}").unwrap(),
1044        MsFlag::NewCas(token) => write!(&mut w, " E{token}").unwrap(),
1045        MsFlag::SetFlags(token) => write!(&mut w, " F{token}").unwrap(),
1046        MsFlag::Invalidate => w.extend(b" I"),
1047        MsFlag::ReturnKey => w.extend(b" k"),
1048        MsFlag::Opaque(token) => write!(&mut w, " O{token}").unwrap(),
1049        MsFlag::ReturnSize => w.extend(b" s"),
1050        MsFlag::Ttl(token) => write!(&mut w, " T{token}").unwrap(),
1051        MsFlag::Mode(token) => match token {
1052            MsMode::Add => w.extend(b" ME"),
1053            MsMode::Append => w.extend(b" MA"),
1054            MsMode::Prepend => w.extend(b" MP"),
1055            MsMode::Replace => w.extend(b" MR"),
1056            MsMode::Set => w.extend(b" MS"),
1057        },
1058        MsFlag::Autovivify(token) => write!(&mut w, " N{token}").unwrap(),
1059    });
1060    w
1061}
1062
1063fn build_mg_flags(flags: &[MgFlag]) -> Vec<u8> {
1064    let mut w = Vec::new();
1065    flags.iter().for_each(|x| match x {
1066        MgFlag::Base64Key => w.extend(b" b"),
1067        MgFlag::ReturnCas => w.extend(b" c"),
1068        MgFlag::CheckCas(token) => write!(&mut w, " C{token}").unwrap(),
1069        MgFlag::ReturnFlags => w.extend(b" f"),
1070        MgFlag::ReturnHit => w.extend(b" h"),
1071        MgFlag::ReturnKey => w.extend(b" k"),
1072        MgFlag::ReturnLastAccess => w.extend(b" l"),
1073        MgFlag::Opaque(token) => write!(&mut w, " O{token}").unwrap(),
1074        MgFlag::ReturnSize => w.extend(b" s"),
1075        MgFlag::ReturnTtl => w.extend(b" t"),
1076        MgFlag::UnBump => w.extend(b" u"),
1077        MgFlag::ReturnValue => w.extend(b" v"),
1078        MgFlag::NewCas(token) => write!(&mut w, " E{token}").unwrap(),
1079        MgFlag::Autovivify(token) => write!(&mut w, " N{token}").unwrap(),
1080        MgFlag::RecacheTtl(token) => write!(&mut w, " R{token}").unwrap(),
1081        MgFlag::UpdateTtl(token) => write!(&mut w, " T{token}").unwrap(),
1082    });
1083    w
1084}
1085
1086fn build_md_flags(flags: &[MdFlag]) -> Vec<u8> {
1087    let mut w = Vec::new();
1088    flags.iter().for_each(|x| match x {
1089        MdFlag::Base64Key => w.extend(b" b"),
1090        MdFlag::CompareCas(token) => write!(&mut w, " C{token}").unwrap(),
1091        MdFlag::NewCas(token) => write!(&mut w, " E{token}").unwrap(),
1092        MdFlag::Invalidate => w.extend(b" I"),
1093        MdFlag::ReturnKey => w.extend(b" k"),
1094        MdFlag::Opaque(token) => write!(&mut w, " O{token}").unwrap(),
1095        MdFlag::UpdateTtl(token) => write!(&mut w, " T{token}").unwrap(),
1096        MdFlag::LeaveKey => w.extend(b" x"),
1097    });
1098    w
1099}
1100
1101fn build_ma_flags(flags: &[MaFlag]) -> Vec<u8> {
1102    let mut w = Vec::new();
1103    flags.iter().for_each(|x| match x {
1104        MaFlag::Base64Key => w.extend(b" b"),
1105        MaFlag::CompareCas(token) => write!(&mut w, " C{token}").unwrap(),
1106        MaFlag::NewCas(token) => write!(&mut w, " E{token}").unwrap(),
1107        MaFlag::AutoCreate(token) => write!(&mut w, " N{token}").unwrap(),
1108        MaFlag::InitValue(token) => write!(&mut w, " J{token}").unwrap(),
1109        MaFlag::DeltaApply(token) => write!(&mut w, " D{token}").unwrap(),
1110        MaFlag::UpdateTtl(token) => write!(&mut w, " T{token}").unwrap(),
1111        MaFlag::Mode(token) => match token {
1112            MaMode::Incr => w.extend(b" M+"),
1113            MaMode::Decr => w.extend(b" M-"),
1114        },
1115        MaFlag::Opaque(token) => write!(&mut w, " O{token}").unwrap(),
1116        MaFlag::ReturnTtl => w.extend(b" t"),
1117        MaFlag::ReturnCas => w.extend(b" c"),
1118        MaFlag::ReturnValue => w.extend(b" v"),
1119        MaFlag::ReturnKey => w.extend(b" k"),
1120    });
1121    w
1122}
1123
1124fn build_lru_cmd(arg: LruArg) -> Vec<u8> {
1125    let mut w = Vec::new();
1126    match arg {
1127        LruArg::Tune {
1128            percent_hot,
1129            percent_warm,
1130            max_hot_factor,
1131            max_warm_factor,
1132        } => write!(
1133            &mut w,
1134            "lru tune {percent_hot} {percent_warm} {max_hot_factor} {max_warm_factor}\r\n"
1135        )
1136        .unwrap(),
1137        LruArg::Mode(mode) => match mode {
1138            LruMode::Flat => w.extend(b"lru mode flat\r\n"),
1139            LruMode::Segmented => w.extend(b"lru mode segmented\r\n"),
1140        },
1141        LruArg::TempTtl(ttl) => write!(&mut w, "lru temp_ttl {ttl}\r\n").unwrap(),
1142    }
1143    w
1144}
1145
1146async fn udp_send_cmd(s: &mut UdpSocket, r: &mut u16, cmd: &[u8]) -> io::Result<()> {
1147    *r = r.wrapping_add(1);
1148    let mut msg = Vec::from(r.to_be_bytes());
1149    msg.extend([0, 0, 0, 1, 0, 0]);
1150    msg.extend(cmd);
1151    s.send(&msg).await?;
1152    Ok(())
1153}
1154
1155async fn udp_recv_rp(s: &mut UdpSocket, r: &u16) -> io::Result<Vec<u8>> {
1156    let mut count_datagrams = 0;
1157    let mut result = HashMap::new();
1158    loop {
1159        let mut buf = [0; 1400];
1160        let n = s.recv(&mut buf).await?;
1161        if n < 8 {
1162            return Err(io::Error::other("Invalid UDP header"));
1163        }
1164        let request_id = u16::from_be_bytes([buf[0], buf[1]]);
1165        let sequence_number = u16::from_be_bytes([buf[2], buf[3]]);
1166        let total_number_datagrams = u16::from_be_bytes([buf[4], buf[5]]);
1167        if *r != request_id {
1168            continue;
1169        }
1170        count_datagrams += 1;
1171        result.insert(sequence_number, buf[8..n].to_vec());
1172        if total_number_datagrams == count_datagrams {
1173            break;
1174        }
1175    }
1176    Ok((0..count_datagrams)
1177        .flat_map(|x| result.remove(&x).unwrap())
1178        .collect())
1179}
1180
1181async fn version_cmd_udp(s: &mut UdpSocket, r: &mut u16) -> io::Result<String> {
1182    udp_send_cmd(s, r, build_version_cmd()).await?;
1183    parse_version_rp(&mut Cursor::new(udp_recv_rp(s, r).await?)).await
1184}
1185
1186pub async fn version_cmd<S: AsyncBufRead + AsyncWrite + Unpin>(s: &mut S) -> io::Result<String> {
1187    s.write_all(build_version_cmd()).await?;
1188    s.flush().await?;
1189    parse_version_rp(s).await
1190}
1191
1192async fn quit_cmd_udp(s: &mut UdpSocket, r: &mut u16) -> io::Result<()> {
1193    udp_send_cmd(s, r, build_quit_cmd()).await
1194}
1195
1196async fn quit_cmd<S: AsyncBufRead + AsyncWrite + Unpin>(s: &mut S) -> io::Result<()> {
1197    s.write_all(build_quit_cmd()).await?;
1198    s.flush().await
1199}
1200
1201async fn shutdown_cmd_udp(s: &mut UdpSocket, r: &mut u16, graceful: bool) -> io::Result<()> {
1202    udp_send_cmd(s, r, build_shutdown_cmd(graceful)).await
1203}
1204
1205async fn shutdown_cmd<S: AsyncBufRead + AsyncWrite + Unpin>(
1206    s: &mut S,
1207    graceful: bool,
1208) -> io::Result<()> {
1209    s.write_all(build_shutdown_cmd(graceful)).await?;
1210    s.flush().await
1211}
1212
1213async fn cache_memlimit_cmd_udp(
1214    s: &mut UdpSocket,
1215    r: &mut u16,
1216    limit: usize,
1217    noreply: bool,
1218) -> io::Result<()> {
1219    udp_send_cmd(s, r, &build_cache_memlimit_cmd(limit, noreply)).await?;
1220    if noreply {
1221        Ok(())
1222    } else {
1223        parse_ok_rp(&mut Cursor::new(udp_recv_rp(s, r).await?), noreply).await
1224    }
1225}
1226
1227async fn cache_memlimit_cmd<S: AsyncBufRead + AsyncWrite + Unpin>(
1228    s: &mut S,
1229    limit: usize,
1230    noreply: bool,
1231) -> io::Result<()> {
1232    s.write_all(&build_cache_memlimit_cmd(limit, noreply))
1233        .await?;
1234    s.flush().await?;
1235    parse_ok_rp(s, noreply).await
1236}
1237
1238async fn flush_all_cmd_udp(
1239    s: &mut UdpSocket,
1240    r: &mut u16,
1241    exptime: Option<i64>,
1242    noreply: bool,
1243) -> io::Result<()> {
1244    udp_send_cmd(s, r, &build_flush_all_cmd(exptime, noreply)).await?;
1245    if noreply {
1246        Ok(())
1247    } else {
1248        parse_ok_rp(&mut Cursor::new(udp_recv_rp(s, r).await?), noreply).await
1249    }
1250}
1251
1252async fn flush_all_cmd<S: AsyncBufRead + AsyncWrite + Unpin>(
1253    s: &mut S,
1254    exptime: Option<i64>,
1255    noreply: bool,
1256) -> io::Result<()> {
1257    s.write_all(&build_flush_all_cmd(exptime, noreply)).await?;
1258    s.flush().await?;
1259    parse_ok_rp(s, noreply).await
1260}
1261
1262async fn storage_cmd_udp(
1263    s: &mut UdpSocket,
1264    r: &mut u16,
1265    command_name: &[u8],
1266    key: &[u8],
1267    flags: u32,
1268    exptime: i64,
1269    cas_unique: Option<u64>,
1270    noreply: bool,
1271    data_block: &[u8],
1272) -> io::Result<bool> {
1273    udp_send_cmd(
1274        s,
1275        r,
1276        &build_storage_cmd(
1277            command_name,
1278            key,
1279            flags,
1280            exptime,
1281            cas_unique,
1282            noreply,
1283            data_block,
1284        ),
1285    )
1286    .await?;
1287    if noreply {
1288        Ok(true)
1289    } else {
1290        parse_storage_rp(&mut Cursor::new(udp_recv_rp(s, r).await?), noreply).await
1291    }
1292}
1293
1294pub async fn storage_cmd<S: AsyncBufRead + AsyncWrite + Unpin>(
1295    s: &mut S,
1296    command_name: &[u8],
1297    key: &[u8],
1298    flags: u32,
1299    exptime: i64,
1300    cas_unique: Option<u64>,
1301    noreply: bool,
1302    data_block: &[u8],
1303) -> io::Result<bool> {
1304    s.write_all(&build_storage_cmd(
1305        command_name,
1306        key,
1307        flags,
1308        exptime,
1309        cas_unique,
1310        noreply,
1311        data_block,
1312    ))
1313    .await?;
1314    s.flush().await?;
1315    parse_storage_rp(s, noreply).await
1316}
1317
1318async fn delete_cmd_udp(
1319    s: &mut UdpSocket,
1320    r: &mut u16,
1321    key: &[u8],
1322    noreply: bool,
1323) -> io::Result<bool> {
1324    udp_send_cmd(s, r, &build_delete_cmd(key, noreply)).await?;
1325    if noreply {
1326        Ok(true)
1327    } else {
1328        parse_delete_rp(&mut Cursor::new(udp_recv_rp(s, r).await?), noreply).await
1329    }
1330}
1331
1332async fn delete_cmd<S: AsyncBufRead + AsyncWrite + Unpin>(
1333    s: &mut S,
1334    key: &[u8],
1335    noreply: bool,
1336) -> io::Result<bool> {
1337    s.write_all(&build_delete_cmd(key, noreply)).await?;
1338    s.flush().await?;
1339    parse_delete_rp(s, noreply).await
1340}
1341
1342async fn auth_cmd<S: AsyncBufRead + AsyncWrite + Unpin>(
1343    s: &mut S,
1344    username: &[u8],
1345    password: &[u8],
1346) -> io::Result<()> {
1347    s.write_all(&build_auth_cmd(username, password)).await?;
1348    s.flush().await?;
1349    parse_auth_rp(s).await
1350}
1351
1352async fn incr_decr_cmd_udp(
1353    s: &mut UdpSocket,
1354    r: &mut u16,
1355    command_name: &[u8],
1356    key: &[u8],
1357    value: u64,
1358    noreply: bool,
1359) -> io::Result<Option<u64>> {
1360    udp_send_cmd(
1361        s,
1362        r,
1363        &build_incr_decr_cmd(command_name, key, value, noreply),
1364    )
1365    .await?;
1366    if noreply {
1367        Ok(None)
1368    } else {
1369        parse_incr_decr_rp(&mut Cursor::new(udp_recv_rp(s, r).await?), noreply).await
1370    }
1371}
1372
1373pub async fn incr_decr_cmd<S: AsyncBufRead + AsyncWrite + Unpin>(
1374    s: &mut S,
1375    command_name: &[u8],
1376    key: &[u8],
1377    value: u64,
1378    noreply: bool,
1379) -> io::Result<Option<u64>> {
1380    s.write_all(&build_incr_decr_cmd(command_name, key, value, noreply))
1381        .await?;
1382    s.flush().await?;
1383    parse_incr_decr_rp(s, noreply).await
1384}
1385
1386async fn touch_cmd_udp(
1387    s: &mut UdpSocket,
1388    r: &mut u16,
1389    key: &[u8],
1390    exptime: i64,
1391    noreply: bool,
1392) -> io::Result<bool> {
1393    udp_send_cmd(s, r, &build_touch_cmd(key, exptime, noreply)).await?;
1394    if noreply {
1395        Ok(true)
1396    } else {
1397        parse_touch_rp(&mut Cursor::new(udp_recv_rp(s, r).await?), noreply).await
1398    }
1399}
1400
1401async fn touch_cmd<S: AsyncBufRead + AsyncWrite + Unpin>(
1402    s: &mut S,
1403    key: &[u8],
1404    exptime: i64,
1405    noreply: bool,
1406) -> io::Result<bool> {
1407    s.write_all(&build_touch_cmd(key, exptime, noreply)).await?;
1408    s.flush().await?;
1409    parse_touch_rp(s, noreply).await
1410}
1411
1412async fn retrieval_cmd_udp(
1413    s: &mut UdpSocket,
1414    r: &mut u16,
1415    command_name: &[u8],
1416    exptime: Option<i64>,
1417    keys: &[&[u8]],
1418) -> io::Result<Vec<Item>> {
1419    udp_send_cmd(s, r, &build_retrieval_cmd(command_name, exptime, keys)).await?;
1420    parse_retrieval_rp(&mut Cursor::new(udp_recv_rp(s, r).await?)).await
1421}
1422
1423pub async fn retrieval_cmd<S: AsyncBufRead + AsyncWrite + Unpin>(
1424    s: &mut S,
1425    command_name: &[u8],
1426    exptime: Option<i64>,
1427    keys: &[&[u8]],
1428) -> io::Result<Vec<Item>> {
1429    s.write_all(&build_retrieval_cmd(command_name, exptime, keys))
1430        .await?;
1431    s.flush().await?;
1432    parse_retrieval_rp(s).await
1433}
1434
1435async fn stats_cmd_udp(
1436    s: &mut UdpSocket,
1437    r: &mut u16,
1438    arg: Option<StatsArg>,
1439) -> io::Result<HashMap<String, String>> {
1440    udp_send_cmd(s, r, build_stats_cmd(arg)).await?;
1441    parse_stats_rp(&mut Cursor::new(udp_recv_rp(s, r).await?)).await
1442}
1443
1444async fn stats_cmd<S: AsyncBufRead + AsyncWrite + Unpin>(
1445    s: &mut S,
1446    arg: Option<StatsArg>,
1447) -> io::Result<HashMap<String, String>> {
1448    s.write_all(build_stats_cmd(arg)).await?;
1449    s.flush().await?;
1450    parse_stats_rp(s).await
1451}
1452
1453async fn slabs_automove_cmd_udp(
1454    s: &mut UdpSocket,
1455    r: &mut u16,
1456    arg: SlabsAutomoveArg,
1457) -> io::Result<()> {
1458    udp_send_cmd(s, r, build_slabs_automove_cmd(arg)).await?;
1459    parse_ok_rp(&mut Cursor::new(udp_recv_rp(s, r).await?), false).await
1460}
1461
1462async fn slabs_automove_cmd<S: AsyncBufRead + AsyncWrite + Unpin>(
1463    s: &mut S,
1464    arg: SlabsAutomoveArg,
1465) -> io::Result<()> {
1466    s.write_all(build_slabs_automove_cmd(arg)).await?;
1467    s.flush().await?;
1468    parse_ok_rp(s, false).await
1469}
1470
1471async fn lru_crawler_cmd_udp(s: &mut UdpSocket, r: &mut u16, arg: LruCrawlerArg) -> io::Result<()> {
1472    udp_send_cmd(s, r, build_lru_crawler_cmd(arg)).await?;
1473    parse_ok_rp(&mut Cursor::new(udp_recv_rp(s, r).await?), false).await
1474}
1475
1476async fn lru_crawler_cmd<S: AsyncBufRead + AsyncWrite + Unpin>(
1477    s: &mut S,
1478    arg: LruCrawlerArg,
1479) -> io::Result<()> {
1480    s.write_all(build_lru_crawler_cmd(arg)).await?;
1481    s.flush().await?;
1482    parse_ok_rp(s, false).await
1483}
1484
1485async fn lru_crawler_sleep_cmd_udp(
1486    s: &mut UdpSocket,
1487    r: &mut u16,
1488    microseconds: usize,
1489) -> io::Result<()> {
1490    udp_send_cmd(s, r, &build_lru_clawler_sleep_cmd(microseconds)).await?;
1491    parse_ok_rp(&mut Cursor::new(udp_recv_rp(s, r).await?), false).await
1492}
1493
1494async fn lru_crawler_sleep_cmd<S: AsyncBufRead + AsyncWrite + Unpin>(
1495    s: &mut S,
1496    microseconds: usize,
1497) -> io::Result<()> {
1498    s.write_all(&build_lru_clawler_sleep_cmd(microseconds))
1499        .await?;
1500    s.flush().await?;
1501    parse_ok_rp(s, false).await
1502}
1503
1504async fn lru_crawler_tocrawl_cmd_udp(s: &mut UdpSocket, r: &mut u16, arg: u32) -> io::Result<()> {
1505    udp_send_cmd(s, r, &build_lru_crawler_tocrawl_cmd(arg)).await?;
1506    parse_ok_rp(&mut Cursor::new(udp_recv_rp(s, r).await?), false).await
1507}
1508
1509async fn lru_crawler_tocrawl_cmd<S: AsyncBufRead + AsyncWrite + Unpin>(
1510    s: &mut S,
1511    arg: u32,
1512) -> io::Result<()> {
1513    s.write_all(&build_lru_crawler_tocrawl_cmd(arg)).await?;
1514    s.flush().await?;
1515    parse_ok_rp(s, false).await
1516}
1517
1518async fn lru_crawler_crawl_cmd_udp(
1519    s: &mut UdpSocket,
1520    r: &mut u16,
1521    arg: LruCrawlerCrawlArg<'_>,
1522) -> io::Result<()> {
1523    udp_send_cmd(s, r, &build_lru_clawler_crawl_cmd(arg)).await?;
1524    parse_ok_rp(&mut Cursor::new(udp_recv_rp(s, r).await?), false).await
1525}
1526
1527async fn lru_crawler_crawl_cmd<S: AsyncBufRead + AsyncWrite + Unpin>(
1528    s: &mut S,
1529    arg: LruCrawlerCrawlArg<'_>,
1530) -> io::Result<()> {
1531    s.write_all(&build_lru_clawler_crawl_cmd(arg)).await?;
1532    s.flush().await?;
1533    parse_ok_rp(s, false).await
1534}
1535
1536async fn slabs_reassign_cmd_udp(
1537    s: &mut UdpSocket,
1538    r: &mut u16,
1539    source_class: isize,
1540    dest_class: isize,
1541) -> io::Result<()> {
1542    udp_send_cmd(s, r, &build_slabs_reassign_cmd(source_class, dest_class)).await?;
1543    parse_ok_rp(&mut Cursor::new(udp_recv_rp(s, r).await?), false).await
1544}
1545
1546async fn slabs_reassign_cmd<S: AsyncBufRead + AsyncWrite + Unpin>(
1547    s: &mut S,
1548    source_class: isize,
1549    dest_class: isize,
1550) -> io::Result<()> {
1551    s.write_all(&build_slabs_reassign_cmd(source_class, dest_class))
1552        .await?;
1553    s.flush().await?;
1554    parse_ok_rp(s, false).await
1555}
1556
1557async fn lru_crawler_metadump_cmd<S: AsyncBufRead + AsyncWrite + Unpin>(
1558    s: &mut S,
1559    arg: LruCrawlerMetadumpArg<'_>,
1560) -> io::Result<Vec<String>> {
1561    s.write_all(&build_lru_clawler_metadump_cmd(arg)).await?;
1562    s.flush().await?;
1563    parse_lru_crawler_metadump_rp(s).await
1564}
1565
1566async fn lru_crawler_mgdump_cmd<S: AsyncBufRead + AsyncWrite + Unpin>(
1567    s: &mut S,
1568    arg: LruCrawlerMgdumpArg<'_>,
1569) -> io::Result<Vec<String>> {
1570    s.write_all(&build_lru_clawler_mgdump_cmd(arg)).await?;
1571    s.flush().await?;
1572    parse_lru_crawler_mgdump_rp(s).await
1573}
1574
1575async fn mn_cmd_udp(s: &mut UdpSocket, r: &mut u16) -> io::Result<()> {
1576    udp_send_cmd(s, r, build_mn_cmd()).await?;
1577    parse_mn_rp(&mut Cursor::new(udp_recv_rp(s, r).await?)).await
1578}
1579
1580async fn mn_cmd<S: AsyncBufRead + AsyncWrite + Unpin>(s: &mut S) -> io::Result<()> {
1581    s.write_all(build_mn_cmd()).await?;
1582    s.flush().await?;
1583    parse_mn_rp(s).await
1584}
1585
1586async fn me_cmd_udp(s: &mut UdpSocket, r: &mut u16, key: &[u8]) -> io::Result<Option<String>> {
1587    udp_send_cmd(s, r, &build_me_cmd(key)).await?;
1588    parse_me_rp(&mut Cursor::new(udp_recv_rp(s, r).await?)).await
1589}
1590
1591async fn me_cmd<S: AsyncBufRead + AsyncWrite + Unpin>(
1592    s: &mut S,
1593    key: &[u8],
1594) -> io::Result<Option<String>> {
1595    s.write_all(&build_me_cmd(key)).await?;
1596    s.flush().await?;
1597    parse_me_rp(s).await
1598}
1599
1600async fn execute_cmd<S: AsyncBufRead + AsyncWrite + Unpin>(
1601    s: &mut S,
1602    cmds: &[Vec<u8>],
1603) -> io::Result<Vec<PipelineResponse>> {
1604    s.write_all(&cmds.concat()).await?;
1605    s.flush().await?;
1606    let mut result = Vec::new();
1607    for cmd in cmds {
1608        if cmd.starts_with(b"gets ")
1609            || cmd.starts_with(b"get ")
1610            || cmd.starts_with(b"gats ")
1611            || cmd.starts_with(b"gat ")
1612        {
1613            if (cmd.starts_with(b"gat") && cmd.iter().filter(|x| x == &&b' ').count() == 2)
1614                || (cmd.starts_with(b"get") && cmd.iter().filter(|x| x == &&b' ').count() == 1)
1615            {
1616                result.push(PipelineResponse::OptionItem(
1617                    parse_retrieval_rp(s).await?.pop(),
1618                ))
1619            } else {
1620                result.push(PipelineResponse::VecItem(parse_retrieval_rp(s).await?))
1621            }
1622        } else if cmd.starts_with(b"set _ _ _ ") {
1623            result.push(PipelineResponse::Unit(parse_auth_rp(s).await?))
1624        } else if cmd.starts_with(b"set ")
1625            || cmd.starts_with(b"add ")
1626            || cmd.starts_with(b"replace ")
1627            || cmd.starts_with(b"append ")
1628            || cmd.starts_with(b"prepend ")
1629            || cmd.starts_with(b"cas ")
1630        {
1631            let mut split = cmd.split(|x| x == &b'\r');
1632            let n = split.next().unwrap();
1633            result.push(PipelineResponse::Bool(
1634                parse_storage_rp(s, n.ends_with(b"noreply")).await?,
1635            ))
1636        } else if cmd == build_version_cmd() {
1637            result.push(PipelineResponse::String(parse_version_rp(s).await?))
1638        } else if cmd.starts_with(b"delete ") {
1639            result.push(PipelineResponse::Bool(
1640                parse_delete_rp(s, cmd.ends_with(b"noreply\r\n")).await?,
1641            ))
1642        } else if cmd.starts_with(b"incr ") || cmd.starts_with(b"decr ") {
1643            result.push(PipelineResponse::Value(
1644                parse_incr_decr_rp(s, cmd.ends_with(b"noreply\r\n")).await?,
1645            ))
1646        } else if cmd.starts_with(b"touch ") {
1647            result.push(PipelineResponse::Bool(
1648                parse_touch_rp(s, cmd.ends_with(b"noreply\r\n")).await?,
1649            ))
1650        } else if cmd == build_quit_cmd() || cmd.starts_with(b"shutdown") {
1651            result.push(PipelineResponse::Unit(()))
1652        } else if cmd.starts_with(b"flush_all") || cmd.starts_with(b"cache_memlimit ") {
1653            result.push(PipelineResponse::Unit(
1654                parse_ok_rp(s, cmd.ends_with(b"noreply\r\n")).await?,
1655            ))
1656        } else if cmd.starts_with(b"slabs automove ")
1657            || cmd.starts_with(b"slabs reassign ")
1658            || cmd.starts_with(b"lru_crawler sleep ")
1659            || cmd.starts_with(b"lru_crawler crawl ")
1660            || cmd.starts_with(b"lru_crawler tocrawl ")
1661            || cmd == build_lru_crawler_cmd(LruCrawlerArg::Enable)
1662            || cmd == build_lru_crawler_cmd(LruCrawlerArg::Disable)
1663        {
1664            result.push(PipelineResponse::Unit(parse_ok_rp(s, false).await?))
1665        } else if cmd == build_mn_cmd() {
1666            result.push(PipelineResponse::Unit(parse_mn_rp(s).await?))
1667        } else if cmd.starts_with(b"stats") {
1668            result.push(PipelineResponse::HashMap(parse_stats_rp(s).await?))
1669        } else if cmd.starts_with(b"lru_crawler metadump ") {
1670            result.push(PipelineResponse::VecString(
1671                parse_lru_crawler_metadump_rp(s).await?,
1672            ))
1673        } else if cmd.starts_with(b"lru_crawler mgdump ") {
1674            result.push(PipelineResponse::VecString(
1675                parse_lru_crawler_mgdump_rp(s).await?,
1676            ))
1677        } else if cmd.starts_with(b"mg ") {
1678            result.push(PipelineResponse::MetaGet(parse_mg_rp(s).await?))
1679        } else if cmd.starts_with(b"ms ") {
1680            result.push(PipelineResponse::MetaSet(parse_ms_rp(s).await?))
1681        } else if cmd.starts_with(b"md ") {
1682            result.push(PipelineResponse::MetaDelete(parse_md_rp(s).await?))
1683        } else if cmd.starts_with(b"ma ") {
1684            result.push(PipelineResponse::MetaArithmetic(parse_ma_rp(s).await?))
1685        } else if cmd.starts_with(b"lru ") {
1686            result.push(PipelineResponse::Unit(parse_ok_rp(s, false).await?))
1687        } else {
1688            assert!(cmd.starts_with(b"me "));
1689            result.push(PipelineResponse::OptionString(parse_me_rp(s).await?))
1690        }
1691    }
1692    Ok(result)
1693}
1694
1695async fn watch_cmd<S: AsyncBufRead + AsyncWrite + Unpin>(
1696    s: &mut S,
1697    arg: &[WatchArg],
1698) -> io::Result<()> {
1699    s.write_all(&build_watch_cmd(arg)).await?;
1700    s.flush().await?;
1701    parse_ok_rp(s, false).await
1702}
1703
1704async fn ms_cmd_udp(
1705    s: &mut UdpSocket,
1706    r: &mut u16,
1707    key: &[u8],
1708    flags: &[MsFlag],
1709    data_block: &[u8],
1710) -> io::Result<MsItem> {
1711    udp_send_cmd(
1712        s,
1713        r,
1714        &build_mc_cmd(b"ms", key, &build_ms_flags(flags), Some(data_block)),
1715    )
1716    .await?;
1717    parse_ms_rp(&mut Cursor::new(udp_recv_rp(s, r).await?)).await
1718}
1719
1720async fn ms_cmd<S: AsyncBufRead + AsyncWrite + Unpin>(
1721    s: &mut S,
1722    key: &[u8],
1723    flags: &[MsFlag],
1724    data_block: &[u8],
1725) -> io::Result<MsItem> {
1726    s.write_all(&build_mc_cmd(
1727        b"ms",
1728        key,
1729        &build_ms_flags(flags),
1730        Some(data_block),
1731    ))
1732    .await?;
1733    s.flush().await?;
1734    parse_ms_rp(s).await
1735}
1736
1737async fn mg_cmd_udp(
1738    s: &mut UdpSocket,
1739    r: &mut u16,
1740    key: &[u8],
1741    flags: &[MgFlag],
1742) -> io::Result<MgItem> {
1743    udp_send_cmd(
1744        s,
1745        r,
1746        &build_mc_cmd(b"mg", key, &build_mg_flags(flags), None),
1747    )
1748    .await?;
1749    parse_mg_rp(&mut Cursor::new(udp_recv_rp(s, r).await?)).await
1750}
1751
1752async fn mg_cmd<S: AsyncBufRead + AsyncWrite + Unpin>(
1753    s: &mut S,
1754    key: &[u8],
1755    flags: &[MgFlag],
1756) -> io::Result<MgItem> {
1757    s.write_all(&build_mc_cmd(b"mg", key, &build_mg_flags(flags), None))
1758        .await?;
1759    s.flush().await?;
1760    parse_mg_rp(s).await
1761}
1762
1763async fn md_cmd_udp(
1764    s: &mut UdpSocket,
1765    r: &mut u16,
1766    key: &[u8],
1767    flags: &[MdFlag],
1768) -> io::Result<MdItem> {
1769    udp_send_cmd(
1770        s,
1771        r,
1772        &build_mc_cmd(b"md", key, &build_md_flags(flags), None),
1773    )
1774    .await?;
1775    parse_md_rp(&mut Cursor::new(udp_recv_rp(s, r).await?)).await
1776}
1777
1778async fn md_cmd<S: AsyncBufRead + AsyncWrite + Unpin>(
1779    s: &mut S,
1780    key: &[u8],
1781    flags: &[MdFlag],
1782) -> io::Result<MdItem> {
1783    s.write_all(&build_mc_cmd(b"md", key, &build_md_flags(flags), None))
1784        .await?;
1785    s.flush().await?;
1786    parse_md_rp(s).await
1787}
1788
1789async fn ma_cmd_udp(
1790    s: &mut UdpSocket,
1791    r: &mut u16,
1792    key: &[u8],
1793    flags: &[MaFlag],
1794) -> io::Result<MaItem> {
1795    udp_send_cmd(
1796        s,
1797        r,
1798        &build_mc_cmd(b"ma", key, &build_ma_flags(flags), None),
1799    )
1800    .await?;
1801    parse_ma_rp(&mut Cursor::new(udp_recv_rp(s, r).await?)).await
1802}
1803
1804async fn ma_cmd<S: AsyncBufRead + AsyncWrite + Unpin>(
1805    s: &mut S,
1806    key: &[u8],
1807    flags: &[MaFlag],
1808) -> io::Result<MaItem> {
1809    s.write_all(&build_mc_cmd(b"ma", key, &build_ma_flags(flags), None))
1810        .await?;
1811    s.flush().await?;
1812    parse_ma_rp(s).await
1813}
1814
1815async fn lru_cmd_udp(s: &mut UdpSocket, r: &mut u16, arg: LruArg) -> io::Result<()> {
1816    udp_send_cmd(s, r, &build_lru_cmd(arg)).await?;
1817    parse_ok_rp(&mut Cursor::new(udp_recv_rp(s, r).await?), false).await
1818}
1819
1820async fn lru_cmd<S: AsyncBufRead + AsyncWrite + Unpin>(s: &mut S, arg: LruArg) -> io::Result<()> {
1821    s.write_all(&build_lru_cmd(arg)).await?;
1822    s.flush().await?;
1823    parse_ok_rp(s, false).await
1824}
1825
1826pub enum Connection {
1827    Tcp(BufReader<TcpStream>),
1828    Unix(BufReader<UnixStream>),
1829    Udp(UdpSocket, u16),
1830    Tls(BufReader<TlsStream<TcpStream>>),
1831}
1832impl Connection {
1833    /// # Example
1834    ///
1835    /// ```
1836    /// # use mcmc_rs::Connection;
1837    /// # use smol::{io, block_on};
1838    /// #
1839    /// # block_on(async {
1840    /// let mut conn = Connection::default().await?;
1841    /// #     Ok::<(), io::Error>(())
1842    /// # }).unwrap()
1843    /// ```
1844    pub async fn default() -> io::Result<Self> {
1845        Ok(Connection::Tcp(BufReader::new(
1846            TcpStream::connect("127.0.0.1:11211").await?,
1847        )))
1848    }
1849
1850    /// # Example
1851    ///
1852    /// ```
1853    /// # use mcmc_rs::Connection;
1854    /// # use smol::{io, block_on};
1855    /// #
1856    /// # block_on(async {
1857    /// let mut conn = Connection::tcp_connect("127.0.0.1:11211").await?;
1858    /// #     Ok::<(), io::Error>(())
1859    /// # }).unwrap()
1860    /// ```
1861    pub async fn tcp_connect(addr: &str) -> io::Result<Self> {
1862        Ok(Connection::Tcp(BufReader::new(
1863            TcpStream::connect(addr).await?,
1864        )))
1865    }
1866
1867    /// # Example
1868    ///
1869    /// ```
1870    /// # use mcmc_rs::Connection;
1871    /// # use smol::{io, block_on};
1872    /// #
1873    /// # block_on(async {
1874    /// let mut conn = Connection::unix_connect("/tmp/memcached0.sock").await?;
1875    /// #     Ok::<(), io::Error>(())
1876    /// # }).unwrap()
1877    /// ```
1878    pub async fn unix_connect(path: &str) -> io::Result<Self> {
1879        Ok(Connection::Unix(BufReader::new(
1880            UnixStream::connect(path).await?,
1881        )))
1882    }
1883
1884    /// # Example
1885    ///
1886    /// ```
1887    /// # use mcmc_rs::Connection;
1888    /// # use smol::{io, block_on};
1889    /// #
1890    /// # block_on(async {
1891    /// let mut conn = Connection::udp_connect("127.0.0.1:0", "127.0.0.1:11214").await?;
1892    /// #     Ok::<(), io::Error>(())
1893    /// # }).unwrap()
1894    pub async fn udp_connect(bind_addr: &str, connect_addr: &str) -> io::Result<Self> {
1895        let s = UdpSocket::bind(bind_addr).await?;
1896        s.connect(connect_addr).await?;
1897        Ok(Connection::Udp(s, 0))
1898    }
1899
1900    /// # Example
1901    ///
1902    /// ```
1903    /// # use mcmc_rs::Connection;
1904    /// # use smol::{io, block_on};
1905    /// #
1906    /// # block_on(async {
1907    /// let mut conn = Connection::tls_connect("localhost", 11216, "cert.pem").await?;
1908    /// #     Ok::<(), io::Error>(())
1909    /// # }).unwrap()
1910    pub async fn tls_connect(hostname: &str, port: u16, ca_path: &str) -> io::Result<Self> {
1911        let cert = fs::read(ca_path).await?;
1912        let tcp_stream = TcpStream::connect(format!("{hostname}:{port}")).await?;
1913        let connector =
1914            TlsConnector::new().add_root_certificate(Certificate::from_pem(&cert).unwrap());
1915        Ok(Connection::Tls(BufReader::new(
1916            connector.connect(hostname, tcp_stream).await.unwrap(),
1917        )))
1918    }
1919
1920    /// # Example
1921    ///
1922    /// ```
1923    /// # use mcmc_rs::Connection;
1924    /// # use smol::{io, block_on};
1925    /// #
1926    /// # block_on(async {
1927    /// for mut c in [
1928    ///     Connection::default().await?,
1929    ///     Connection::unix_connect("/tmp/memcached0.sock").await?,
1930    ///     Connection::udp_connect("127.0.0.1:0", "127.0.0.1:11214").await?,
1931    ///     Connection::tls_connect("localhost", 11216, "cert.pem").await?,
1932    /// ] {
1933    ///     let result = c.version().await?;
1934    ///     assert!(result.chars().any(|x| x.is_numeric()));
1935    /// }
1936    /// #     Ok::<(), io::Error>(())
1937    /// # }).unwrap()
1938    /// ```
1939    pub async fn version(&mut self) -> io::Result<String> {
1940        match self {
1941            Connection::Tcp(s) => version_cmd(s).await,
1942            Connection::Unix(s) => version_cmd(s).await,
1943            Connection::Udp(s, r) => version_cmd_udp(s, r).await,
1944            Connection::Tls(s) => version_cmd(s).await,
1945        }
1946    }
1947
1948    /// # Example
1949    ///
1950    /// ```
1951    /// # use mcmc_rs::Connection;
1952    /// # use smol::{io, block_on};
1953    /// #
1954    /// # block_on(async {
1955    /// for mut c in [
1956    ///     Connection::default().await?,
1957    ///     Connection::unix_connect("/tmp/memcached0.sock").await?,
1958    ///     Connection::udp_connect("127.0.0.1:0", "127.0.0.1:11214").await?,
1959    ///     Connection::tls_connect("localhost", 11216, "cert.pem").await?,
1960    /// ] {
1961    ///     c.quit().await?;
1962    /// }
1963    /// #     Ok::<(), io::Error>(())
1964    /// # }).unwrap()
1965    /// ```
1966    pub async fn quit(mut self) -> io::Result<()> {
1967        match &mut self {
1968            Connection::Tcp(s) => quit_cmd(s).await,
1969            Connection::Unix(s) => quit_cmd(s).await,
1970            Connection::Udp(s, r) => quit_cmd_udp(s, r).await,
1971            Connection::Tls(s) => quit_cmd(s).await,
1972        }
1973    }
1974
1975    /// # Example
1976    ///
1977    /// ```
1978    /// # use mcmc_rs::Connection;
1979    /// # use smol::{io, block_on};
1980    /// #
1981    /// # block_on(async {
1982    /// for mut c in [
1983    ///     Connection::tcp_connect("127.0.0.1:11213").await?,
1984    ///     Connection::unix_connect("/tmp/memcached1.sock").await?,
1985    ///     Connection::udp_connect("127.0.0.1:0", "127.0.0.1:11215").await?,
1986    ///     Connection::tls_connect("localhost", 11217, "cert.pem").await?,
1987    /// ] {
1988    ///     c.shutdown(true).await?;
1989    /// }
1990    /// #     Ok::<(), io::Error>(())
1991    /// # }).unwrap()
1992    /// ```
1993    pub async fn shutdown(mut self, graceful: bool) -> io::Result<()> {
1994        match &mut self {
1995            Connection::Tcp(s) => shutdown_cmd(s, graceful).await,
1996            Connection::Unix(s) => shutdown_cmd(s, graceful).await,
1997            Connection::Udp(s, r) => shutdown_cmd_udp(s, r, graceful).await,
1998            Connection::Tls(s) => shutdown_cmd(s, graceful).await,
1999        }
2000    }
2001
2002    /// # Example
2003    ///
2004    /// ```
2005    /// # use mcmc_rs::Connection;
2006    /// # use smol::{io, block_on};
2007    /// #
2008    /// # block_on(async {
2009    /// for mut c in [
2010    ///     Connection::default().await?,
2011    ///     Connection::unix_connect("/tmp/memcached0.sock").await?,
2012    ///     Connection::udp_connect("127.0.0.1:0", "127.0.0.1:11214").await?,
2013    ///     Connection::tls_connect("localhost", 11216, "cert.pem").await?,
2014    /// ] {
2015    ///     c.cache_memlimit(10, true).await?;
2016    /// }
2017    /// #     Ok::<(), io::Error>(())
2018    /// # }).unwrap()
2019    /// ```
2020    pub async fn cache_memlimit(&mut self, limit: usize, noreply: bool) -> io::Result<()> {
2021        match self {
2022            Connection::Tcp(s) => cache_memlimit_cmd(s, limit, noreply).await,
2023            Connection::Unix(s) => cache_memlimit_cmd(s, limit, noreply).await,
2024            Connection::Udp(s, r) => cache_memlimit_cmd_udp(s, r, limit, noreply).await,
2025            Connection::Tls(s) => cache_memlimit_cmd(s, limit, noreply).await,
2026        }
2027    }
2028
2029    /// # Example
2030    ///
2031    /// ```
2032    /// # use mcmc_rs::Connection;
2033    /// # use smol::{io, block_on};
2034    /// #
2035    /// # block_on(async {
2036    /// for mut c in [
2037    ///     Connection::default().await?,
2038    ///     Connection::unix_connect("/tmp/memcached0.sock").await?,
2039    ///     Connection::udp_connect("127.0.0.1:0", "127.0.0.1:11214").await?,
2040    ///     Connection::tls_connect("localhost", 11216, "cert.pem").await?,
2041    /// ] {
2042    ///     c.flush_all(Some(999), true).await?;
2043    /// }
2044    /// #     Ok::<(), io::Error>(())
2045    /// # }).unwrap()
2046    /// ```
2047    pub async fn flush_all(&mut self, exptime: Option<i64>, noreply: bool) -> io::Result<()> {
2048        match self {
2049            Connection::Tcp(s) => flush_all_cmd(s, exptime, noreply).await,
2050            Connection::Unix(s) => flush_all_cmd(s, exptime, noreply).await,
2051            Connection::Udp(s, r) => flush_all_cmd_udp(s, r, exptime, noreply).await,
2052            Connection::Tls(s) => flush_all_cmd(s, exptime, noreply).await,
2053        }
2054    }
2055
2056    /// # Example
2057    ///
2058    /// ```
2059    /// # use mcmc_rs::Connection;
2060    /// # use smol::{io, block_on};
2061    /// #
2062    /// # block_on(async {
2063    /// for mut c in [
2064    ///     Connection::default().await?,
2065    ///     Connection::unix_connect("/tmp/memcached0.sock").await?,
2066    ///     Connection::udp_connect("127.0.0.1:0", "127.0.0.1:11214").await?,
2067    ///     Connection::tls_connect("localhost", 11216, "cert.pem").await?,
2068    /// ] {
2069    ///     let result = c.set(b"key", 0, -1, true, b"value").await?;
2070    ///     assert!(result);
2071    /// }
2072    /// #     Ok::<(), io::Error>(())
2073    /// # }).unwrap()
2074    /// ```
2075    pub async fn set(
2076        &mut self,
2077        key: impl AsRef<[u8]>,
2078        flags: u32,
2079        exptime: i64,
2080        noreply: bool,
2081        data_block: impl AsRef<[u8]>,
2082    ) -> io::Result<bool> {
2083        match self {
2084            Connection::Tcp(s) => {
2085                storage_cmd(
2086                    s,
2087                    b"set",
2088                    key.as_ref(),
2089                    flags,
2090                    exptime,
2091                    None,
2092                    noreply,
2093                    data_block.as_ref(),
2094                )
2095                .await
2096            }
2097            Connection::Unix(s) => {
2098                storage_cmd(
2099                    s,
2100                    b"set",
2101                    key.as_ref(),
2102                    flags,
2103                    exptime,
2104                    None,
2105                    noreply,
2106                    data_block.as_ref(),
2107                )
2108                .await
2109            }
2110            Connection::Udp(s, r) => {
2111                storage_cmd_udp(
2112                    s,
2113                    r,
2114                    b"set",
2115                    key.as_ref(),
2116                    flags,
2117                    exptime,
2118                    None,
2119                    noreply,
2120                    data_block.as_ref(),
2121                )
2122                .await
2123            }
2124            Connection::Tls(s) => {
2125                storage_cmd(
2126                    s,
2127                    b"set",
2128                    key.as_ref(),
2129                    flags,
2130                    exptime,
2131                    None,
2132                    noreply,
2133                    data_block.as_ref(),
2134                )
2135                .await
2136            }
2137        }
2138    }
2139
2140    /// # Example
2141    ///
2142    /// ```
2143    /// # use mcmc_rs::Connection;
2144    /// # use smol::{io, block_on};
2145    /// #
2146    /// # block_on(async {
2147    /// for mut c in [
2148    ///     Connection::default().await?,
2149    ///     Connection::unix_connect("/tmp/memcached0.sock").await?,
2150    ///     Connection::udp_connect("127.0.0.1:0", "127.0.0.1:11214").await?,
2151    ///     Connection::tls_connect("localhost", 11216, "cert.pem").await?,
2152    /// ] {
2153    ///     let result = c.add(b"key", 0, -1, true, b"value").await?;
2154    ///     assert!(result);
2155    /// }
2156    /// #     Ok::<(), io::Error>(())
2157    /// # }).unwrap()
2158    /// ```
2159    pub async fn add(
2160        &mut self,
2161        key: impl AsRef<[u8]>,
2162        flags: u32,
2163        exptime: i64,
2164        noreply: bool,
2165        data_block: impl AsRef<[u8]>,
2166    ) -> io::Result<bool> {
2167        match self {
2168            Connection::Tcp(s) => {
2169                storage_cmd(
2170                    s,
2171                    b"add",
2172                    key.as_ref(),
2173                    flags,
2174                    exptime,
2175                    None,
2176                    noreply,
2177                    data_block.as_ref(),
2178                )
2179                .await
2180            }
2181            Connection::Unix(s) => {
2182                storage_cmd(
2183                    s,
2184                    b"add",
2185                    key.as_ref(),
2186                    flags,
2187                    exptime,
2188                    None,
2189                    noreply,
2190                    data_block.as_ref(),
2191                )
2192                .await
2193            }
2194            Connection::Udp(s, r) => {
2195                storage_cmd_udp(
2196                    s,
2197                    r,
2198                    b"add",
2199                    key.as_ref(),
2200                    flags,
2201                    exptime,
2202                    None,
2203                    noreply,
2204                    data_block.as_ref(),
2205                )
2206                .await
2207            }
2208            Connection::Tls(s) => {
2209                storage_cmd(
2210                    s,
2211                    b"add",
2212                    key.as_ref(),
2213                    flags,
2214                    exptime,
2215                    None,
2216                    noreply,
2217                    data_block.as_ref(),
2218                )
2219                .await
2220            }
2221        }
2222    }
2223
2224    /// # Example
2225    ///
2226    /// ```
2227    /// # use mcmc_rs::Connection;
2228    /// # use smol::{io, block_on};
2229    /// #
2230    /// # block_on(async {
2231    /// for mut c in [
2232    ///     Connection::default().await?,
2233    ///     Connection::unix_connect("/tmp/memcached0.sock").await?,
2234    ///     Connection::udp_connect("127.0.0.1:0", "127.0.0.1:11214").await?,
2235    ///     Connection::tls_connect("localhost", 11216, "cert.pem").await?,
2236    /// ] {
2237    ///     let result = c.replace(b"key", 0, -1, true, b"value").await?;
2238    ///     assert!(result);
2239    /// }
2240    /// #     Ok::<(), io::Error>(())
2241    /// # }).unwrap()
2242    /// ```
2243    pub async fn replace(
2244        &mut self,
2245        key: impl AsRef<[u8]>,
2246        flags: u32,
2247        exptime: i64,
2248        noreply: bool,
2249        data_block: impl AsRef<[u8]>,
2250    ) -> io::Result<bool> {
2251        match self {
2252            Connection::Tcp(s) => {
2253                storage_cmd(
2254                    s,
2255                    b"replace",
2256                    key.as_ref(),
2257                    flags,
2258                    exptime,
2259                    None,
2260                    noreply,
2261                    data_block.as_ref(),
2262                )
2263                .await
2264            }
2265            Connection::Unix(s) => {
2266                storage_cmd(
2267                    s,
2268                    b"replace",
2269                    key.as_ref(),
2270                    flags,
2271                    exptime,
2272                    None,
2273                    noreply,
2274                    data_block.as_ref(),
2275                )
2276                .await
2277            }
2278            Connection::Udp(s, r) => {
2279                storage_cmd_udp(
2280                    s,
2281                    r,
2282                    b"replace",
2283                    key.as_ref(),
2284                    flags,
2285                    exptime,
2286                    None,
2287                    noreply,
2288                    data_block.as_ref(),
2289                )
2290                .await
2291            }
2292            Connection::Tls(s) => {
2293                storage_cmd(
2294                    s,
2295                    b"replace",
2296                    key.as_ref(),
2297                    flags,
2298                    exptime,
2299                    None,
2300                    noreply,
2301                    data_block.as_ref(),
2302                )
2303                .await
2304            }
2305        }
2306    }
2307
2308    /// # Example
2309    ///
2310    /// ```
2311    /// # use mcmc_rs::Connection;
2312    /// # use smol::{io, block_on};
2313    /// #
2314    /// # block_on(async {
2315    /// for mut c in [
2316    ///     Connection::default().await?,
2317    ///     Connection::unix_connect("/tmp/memcached0.sock").await?,
2318    ///     Connection::udp_connect("127.0.0.1:0", "127.0.0.1:11214").await?,
2319    ///     Connection::tls_connect("localhost", 11216, "cert.pem").await?,
2320    /// ] {
2321    ///     let result = c.append(b"key", 0, -1, true, b"value").await?;
2322    ///     assert!(result);
2323    /// }
2324    /// #     Ok::<(), io::Error>(())
2325    /// # }).unwrap()
2326    /// ```
2327    pub async fn append(
2328        &mut self,
2329        key: impl AsRef<[u8]>,
2330        flags: u32,
2331        exptime: i64,
2332        noreply: bool,
2333        data_block: impl AsRef<[u8]>,
2334    ) -> io::Result<bool> {
2335        match self {
2336            Connection::Tcp(s) => {
2337                storage_cmd(
2338                    s,
2339                    b"append",
2340                    key.as_ref(),
2341                    flags,
2342                    exptime,
2343                    None,
2344                    noreply,
2345                    data_block.as_ref(),
2346                )
2347                .await
2348            }
2349            Connection::Unix(s) => {
2350                storage_cmd(
2351                    s,
2352                    b"append",
2353                    key.as_ref(),
2354                    flags,
2355                    exptime,
2356                    None,
2357                    noreply,
2358                    data_block.as_ref(),
2359                )
2360                .await
2361            }
2362            Connection::Udp(s, r) => {
2363                storage_cmd_udp(
2364                    s,
2365                    r,
2366                    b"append",
2367                    key.as_ref(),
2368                    flags,
2369                    exptime,
2370                    None,
2371                    noreply,
2372                    data_block.as_ref(),
2373                )
2374                .await
2375            }
2376            Connection::Tls(s) => {
2377                storage_cmd(
2378                    s,
2379                    b"append",
2380                    key.as_ref(),
2381                    flags,
2382                    exptime,
2383                    None,
2384                    noreply,
2385                    data_block.as_ref(),
2386                )
2387                .await
2388            }
2389        }
2390    }
2391
2392    /// # Example
2393    ///
2394    /// ```
2395    /// # use mcmc_rs::Connection;
2396    /// # use smol::{io, block_on};
2397    /// #
2398    /// # block_on(async {
2399    /// for mut c in [
2400    ///     Connection::default().await?,
2401    ///     Connection::unix_connect("/tmp/memcached0.sock").await?,
2402    ///     Connection::udp_connect("127.0.0.1:0", "127.0.0.1:11214").await?,
2403    ///     Connection::tls_connect("localhost", 11216, "cert.pem").await?,
2404    /// ] {
2405    ///     let result = c.prepend(b"key", 0, -1, true, b"value").await?;
2406    ///     assert!(result);
2407    /// }
2408    /// #     Ok::<(), io::Error>(())
2409    /// # }).unwrap()
2410    /// ```
2411    pub async fn prepend(
2412        &mut self,
2413        key: impl AsRef<[u8]>,
2414        flags: u32,
2415        exptime: i64,
2416        noreply: bool,
2417        data_block: impl AsRef<[u8]>,
2418    ) -> io::Result<bool> {
2419        match self {
2420            Connection::Tcp(s) => {
2421                storage_cmd(
2422                    s,
2423                    b"prepend",
2424                    key.as_ref(),
2425                    flags,
2426                    exptime,
2427                    None,
2428                    noreply,
2429                    data_block.as_ref(),
2430                )
2431                .await
2432            }
2433            Connection::Unix(s) => {
2434                storage_cmd(
2435                    s,
2436                    b"prepend",
2437                    key.as_ref(),
2438                    flags,
2439                    exptime,
2440                    None,
2441                    noreply,
2442                    data_block.as_ref(),
2443                )
2444                .await
2445            }
2446            Connection::Udp(s, r) => {
2447                storage_cmd_udp(
2448                    s,
2449                    r,
2450                    b"prepend",
2451                    key.as_ref(),
2452                    flags,
2453                    exptime,
2454                    None,
2455                    noreply,
2456                    data_block.as_ref(),
2457                )
2458                .await
2459            }
2460            Connection::Tls(s) => {
2461                storage_cmd(
2462                    s,
2463                    b"prepend",
2464                    key.as_ref(),
2465                    flags,
2466                    exptime,
2467                    None,
2468                    noreply,
2469                    data_block.as_ref(),
2470                )
2471                .await
2472            }
2473        }
2474    }
2475
2476    /// # Example
2477    ///
2478    /// ```
2479    /// # use mcmc_rs::Connection;
2480    /// # use smol::{io, block_on};
2481    /// #
2482    /// # block_on(async {
2483    /// for mut c in [
2484    ///     Connection::default().await?,
2485    ///     Connection::unix_connect("/tmp/memcached0.sock").await?,
2486    ///     Connection::udp_connect("127.0.0.1:0", "127.0.0.1:11214").await?,
2487    ///     Connection::tls_connect("localhost", 11216, "cert.pem").await?,
2488    /// ] {
2489    ///     let result = c.cas(b"key", 0, -1, 0, true, b"value").await?;
2490    ///     assert!(result);
2491    /// }
2492    /// #     Ok::<(), io::Error>(())
2493    /// # }).unwrap()
2494    /// ```
2495    pub async fn cas(
2496        &mut self,
2497        key: impl AsRef<[u8]>,
2498        flags: u32,
2499        exptime: i64,
2500        cas_unique: u64,
2501        noreply: bool,
2502        data_block: impl AsRef<[u8]>,
2503    ) -> io::Result<bool> {
2504        match self {
2505            Connection::Tcp(s) => {
2506                storage_cmd(
2507                    s,
2508                    b"cas",
2509                    key.as_ref(),
2510                    flags,
2511                    exptime,
2512                    Some(cas_unique),
2513                    noreply,
2514                    data_block.as_ref(),
2515                )
2516                .await
2517            }
2518            Connection::Unix(s) => {
2519                storage_cmd(
2520                    s,
2521                    b"cas",
2522                    key.as_ref(),
2523                    flags,
2524                    exptime,
2525                    Some(cas_unique),
2526                    noreply,
2527                    data_block.as_ref(),
2528                )
2529                .await
2530            }
2531            Connection::Udp(s, r) => {
2532                storage_cmd_udp(
2533                    s,
2534                    r,
2535                    b"cas",
2536                    key.as_ref(),
2537                    flags,
2538                    exptime,
2539                    Some(cas_unique),
2540                    noreply,
2541                    data_block.as_ref(),
2542                )
2543                .await
2544            }
2545            Connection::Tls(s) => {
2546                storage_cmd(
2547                    s,
2548                    b"cas",
2549                    key.as_ref(),
2550                    flags,
2551                    exptime,
2552                    Some(cas_unique),
2553                    noreply,
2554                    data_block.as_ref(),
2555                )
2556                .await
2557            }
2558        }
2559    }
2560
2561    /// # Example
2562    ///
2563    /// ```
2564    /// # use mcmc_rs::Connection;
2565    /// # use smol::{io, block_on};
2566    /// #
2567    /// # block_on(async {
2568    /// for mut c in [
2569    ///     Connection::tcp_connect("127.0.0.1:11212").await?,
2570    ///     Connection::unix_connect("/tmp/memcached2.sock").await?,
2571    ///     Connection::tls_connect("localhost", 11218, "cert.pem").await?,
2572    /// ] {
2573    ///     c.auth(b"a", b"a").await?;
2574    /// }
2575    /// #     Ok::<(), io::Error>(())
2576    /// # }).unwrap()
2577    /// ```
2578    pub async fn auth(
2579        &mut self,
2580        username: impl AsRef<[u8]>,
2581        password: impl AsRef<[u8]>,
2582    ) -> io::Result<()> {
2583        match self {
2584            Connection::Tcp(s) => auth_cmd(s, username.as_ref(), password.as_ref()).await,
2585            Connection::Unix(s) => auth_cmd(s, username.as_ref(), password.as_ref()).await,
2586            Connection::Udp(_s, _r) => {
2587                unreachable!("Cannot enable UDP while using binary SASL authentication.")
2588            }
2589            Connection::Tls(s) => auth_cmd(s, username.as_ref(), password.as_ref()).await,
2590        }
2591    }
2592
2593    /// # Example
2594    ///
2595    /// ```
2596    /// # use mcmc_rs::Connection;
2597    /// # use smol::{io, block_on};
2598    /// #
2599    /// # block_on(async {
2600    /// for mut c in [
2601    ///     Connection::default().await?,
2602    ///     Connection::unix_connect("/tmp/memcached0.sock").await?,
2603    ///     Connection::udp_connect("127.0.0.1:0", "127.0.0.1:11214").await?,
2604    ///     Connection::tls_connect("localhost", 11216, "cert.pem").await?,
2605    /// ] {
2606    ///     let result = c.delete(b"key", true).await?;
2607    ///     assert!(result);
2608    /// }
2609    /// #     Ok::<(), io::Error>(())
2610    /// # }).unwrap()
2611    /// ```
2612    pub async fn delete(&mut self, key: impl AsRef<[u8]>, noreply: bool) -> io::Result<bool> {
2613        match self {
2614            Connection::Tcp(s) => delete_cmd(s, key.as_ref(), noreply).await,
2615            Connection::Unix(s) => delete_cmd(s, key.as_ref(), noreply).await,
2616            Connection::Udp(s, r) => delete_cmd_udp(s, r, key.as_ref(), noreply).await,
2617            Connection::Tls(s) => delete_cmd(s, key.as_ref(), noreply).await,
2618        }
2619    }
2620
2621    /// # Example
2622    ///
2623    /// ```
2624    /// # use mcmc_rs::Connection;
2625    /// # use smol::{io, block_on};
2626    /// #
2627    /// # block_on(async {
2628    /// for mut c in [
2629    ///     Connection::default().await?,
2630    ///     Connection::unix_connect("/tmp/memcached0.sock").await?,
2631    ///     Connection::udp_connect("127.0.0.1:0", "127.0.0.1:11214").await?,
2632    ///     Connection::tls_connect("localhost", 11216, "cert.pem").await?,
2633    /// ] {
2634    ///     let result = c.incr(b"key", 1, true).await?;
2635    ///     assert!(result.is_none());
2636    /// }
2637    /// #     Ok::<(), io::Error>(())
2638    /// # }).unwrap()
2639    /// ```
2640    pub async fn incr(
2641        &mut self,
2642        key: impl AsRef<[u8]>,
2643        value: u64,
2644        noreply: bool,
2645    ) -> io::Result<Option<u64>> {
2646        match self {
2647            Connection::Tcp(s) => incr_decr_cmd(s, b"incr", key.as_ref(), value, noreply).await,
2648            Connection::Unix(s) => incr_decr_cmd(s, b"incr", key.as_ref(), value, noreply).await,
2649            Connection::Udp(s, r) => {
2650                incr_decr_cmd_udp(s, r, b"incr", key.as_ref(), value, noreply).await
2651            }
2652            Connection::Tls(s) => incr_decr_cmd(s, b"incr", key.as_ref(), value, noreply).await,
2653        }
2654    }
2655
2656    /// # Example
2657    ///
2658    /// ```
2659    /// # use mcmc_rs::Connection;
2660    /// # use smol::{io, block_on};
2661    /// #
2662    /// # block_on(async {
2663    /// for mut c in [
2664    ///     Connection::default().await?,
2665    ///     Connection::unix_connect("/tmp/memcached0.sock").await?,
2666    ///     Connection::udp_connect("127.0.0.1:0", "127.0.0.1:11214").await?,
2667    ///     Connection::tls_connect("localhost", 11216, "cert.pem").await?,
2668    /// ] {
2669    ///     let result = c.decr(b"key", 1, true).await?;
2670    ///     assert!(result.is_none());
2671    /// }
2672    /// #     Ok::<(), io::Error>(())
2673    /// # }).unwrap()
2674    /// ```
2675    pub async fn decr(
2676        &mut self,
2677        key: impl AsRef<[u8]>,
2678        value: u64,
2679        noreply: bool,
2680    ) -> io::Result<Option<u64>> {
2681        match self {
2682            Connection::Tcp(s) => incr_decr_cmd(s, b"decr", key.as_ref(), value, noreply).await,
2683            Connection::Unix(s) => incr_decr_cmd(s, b"decr", key.as_ref(), value, noreply).await,
2684            Connection::Udp(s, r) => {
2685                incr_decr_cmd_udp(s, r, b"decr", key.as_ref(), value, noreply).await
2686            }
2687            Connection::Tls(s) => incr_decr_cmd(s, b"decr", key.as_ref(), value, noreply).await,
2688        }
2689    }
2690
2691    /// # Example
2692    ///
2693    /// ```
2694    /// # use mcmc_rs::Connection;
2695    /// # use smol::{io, block_on};
2696    /// #
2697    /// # block_on(async {
2698    /// for mut c in [
2699    ///     Connection::default().await?,
2700    ///     Connection::unix_connect("/tmp/memcached0.sock").await?,
2701    ///     Connection::udp_connect("127.0.0.1:0", "127.0.0.1:11214").await?,
2702    ///     Connection::tls_connect("localhost", 11216, "cert.pem").await?,
2703    /// ] {
2704    ///     let result = c.touch(b"key", -1, true).await?;
2705    ///     assert!(result);
2706    /// }
2707    /// #     Ok::<(), io::Error>(())
2708    /// # }).unwrap()
2709    /// ```
2710    pub async fn touch(
2711        &mut self,
2712        key: impl AsRef<[u8]>,
2713        exptime: i64,
2714        noreply: bool,
2715    ) -> io::Result<bool> {
2716        match self {
2717            Connection::Tcp(s) => touch_cmd(s, key.as_ref(), exptime, noreply).await,
2718            Connection::Unix(s) => touch_cmd(s, key.as_ref(), exptime, noreply).await,
2719            Connection::Udp(s, r) => touch_cmd_udp(s, r, key.as_ref(), exptime, noreply).await,
2720            Connection::Tls(s) => touch_cmd(s, key.as_ref(), exptime, noreply).await,
2721        }
2722    }
2723
2724    /// # Example
2725    ///
2726    /// ```
2727    /// # use mcmc_rs::Connection;
2728    /// # use smol::{io, block_on};
2729    /// #
2730    /// # block_on(async {
2731    /// for mut c in [
2732    ///     Connection::default().await?,
2733    ///     Connection::unix_connect("/tmp/memcached0.sock").await?,
2734    ///     Connection::udp_connect("127.0.0.1:0", "127.0.0.1:11214").await?,
2735    ///     Connection::tls_connect("localhost", 11216, "cert.pem").await?,
2736    /// ] {
2737    ///     assert!(c.set(b"k1", 0, 0, false, b"v1").await?);
2738    ///     let result = c.get(b"k1").await?;
2739    ///     assert_eq!(result.unwrap().key, "k1");
2740    /// }
2741    /// #     Ok::<(), io::Error>(())
2742    /// # }).unwrap()
2743    /// ```
2744    pub async fn get(&mut self, key: impl AsRef<[u8]>) -> io::Result<Option<Item>> {
2745        match self {
2746            Connection::Tcp(s) => Ok(retrieval_cmd(s, b"get", None, &[key.as_ref()]).await?.pop()),
2747            Connection::Unix(s) => Ok(retrieval_cmd(s, b"get", None, &[key.as_ref()]).await?.pop()),
2748            Connection::Udp(s, r) => Ok(retrieval_cmd_udp(s, r, b"get", None, &[key.as_ref()])
2749                .await?
2750                .pop()),
2751            Connection::Tls(s) => Ok(retrieval_cmd(s, b"get", None, &[key.as_ref()]).await?.pop()),
2752        }
2753    }
2754
2755    /// # Example
2756    ///
2757    /// ```
2758    /// # use mcmc_rs::Connection;
2759    /// # use smol::{io, block_on};
2760    /// #
2761    /// # block_on(async {
2762    /// for mut c in [
2763    ///     Connection::default().await?,
2764    ///     Connection::unix_connect("/tmp/memcached0.sock").await?,
2765    ///     Connection::udp_connect("127.0.0.1:0", "127.0.0.1:11214").await?,
2766    ///     Connection::tls_connect("localhost", 11216, "cert.pem").await?,
2767    /// ] {
2768    ///     assert!(c.set(b"k2", 0, 0, false, b"v2").await?);
2769    ///     let result = c.gets(b"k2").await?;
2770    ///     assert_eq!(result.unwrap().key, "k2");
2771    /// }
2772    /// #     Ok::<(), io::Error>(())
2773    /// # }).unwrap()
2774    /// ```
2775    pub async fn gets(&mut self, key: impl AsRef<[u8]>) -> io::Result<Option<Item>> {
2776        match self {
2777            Connection::Tcp(s) => Ok(retrieval_cmd(s, b"gets", None, &[key.as_ref()])
2778                .await?
2779                .pop()),
2780            Connection::Unix(s) => Ok(retrieval_cmd(s, b"gets", None, &[key.as_ref()])
2781                .await?
2782                .pop()),
2783            Connection::Udp(s, r) => Ok(retrieval_cmd_udp(s, r, b"gets", None, &[key.as_ref()])
2784                .await?
2785                .pop()),
2786            Connection::Tls(s) => Ok(retrieval_cmd(s, b"gets", None, &[key.as_ref()])
2787                .await?
2788                .pop()),
2789        }
2790    }
2791
2792    /// # Example
2793    ///
2794    /// ```
2795    /// # use mcmc_rs::Connection;
2796    /// # use smol::{io, block_on};
2797    /// #
2798    /// # block_on(async {
2799    /// for mut c in [
2800    ///     Connection::default().await?,
2801    ///     Connection::unix_connect("/tmp/memcached0.sock").await?,
2802    ///     Connection::udp_connect("127.0.0.1:0", "127.0.0.1:11214").await?,
2803    ///     Connection::tls_connect("localhost", 11216, "cert.pem").await?,
2804    /// ] {
2805    ///     assert!(c.set(b"k3", 0, 0, false, b"v3").await?);
2806    ///     let result = c.gat(0, b"k3").await?;
2807    ///     assert_eq!(result.unwrap().key, "k3");
2808    /// }
2809    /// #     Ok::<(), io::Error>(())
2810    /// # }).unwrap()
2811    /// ```
2812    pub async fn gat(&mut self, exptime: i64, key: impl AsRef<[u8]>) -> io::Result<Option<Item>> {
2813        match self {
2814            Connection::Tcp(s) => Ok(retrieval_cmd(s, b"gat", Some(exptime), &[key.as_ref()])
2815                .await?
2816                .pop()),
2817            Connection::Unix(s) => Ok(retrieval_cmd(s, b"gat", Some(exptime), &[key.as_ref()])
2818                .await?
2819                .pop()),
2820            Connection::Udp(s, r) => {
2821                Ok(
2822                    retrieval_cmd_udp(s, r, b"gat", Some(exptime), &[key.as_ref()])
2823                        .await?
2824                        .pop(),
2825                )
2826            }
2827            Connection::Tls(s) => Ok(retrieval_cmd(s, b"gat", Some(exptime), &[key.as_ref()])
2828                .await?
2829                .pop()),
2830        }
2831    }
2832
2833    /// # Example
2834    ///
2835    /// ```
2836    /// # use mcmc_rs::Connection;
2837    /// # use smol::{io, block_on};
2838    /// #
2839    /// # block_on(async {
2840    /// for mut c in [
2841    ///     Connection::default().await?,
2842    ///     Connection::unix_connect("/tmp/memcached0.sock").await?,
2843    ///     Connection::udp_connect("127.0.0.1:0", "127.0.0.1:11214").await?,
2844    ///     Connection::tls_connect("localhost", 11216, "cert.pem").await?,
2845    /// ] {
2846    ///     assert!(c.set(b"k4", 0, 0, false, b"v4").await?);
2847    ///     let result = c.gats(0, b"k4").await?;
2848    ///     assert_eq!(result.unwrap().key, "k4");
2849    /// }
2850    /// #     Ok::<(), io::Error>(())
2851    /// # }).unwrap()
2852    /// ```
2853    pub async fn gats(&mut self, exptime: i64, key: impl AsRef<[u8]>) -> io::Result<Option<Item>> {
2854        match self {
2855            Connection::Tcp(s) => Ok(retrieval_cmd(s, b"gats", Some(exptime), &[key.as_ref()])
2856                .await?
2857                .pop()),
2858            Connection::Unix(s) => Ok(retrieval_cmd(s, b"gats", Some(exptime), &[key.as_ref()])
2859                .await?
2860                .pop()),
2861            Connection::Udp(s, r) => {
2862                Ok(
2863                    retrieval_cmd_udp(s, r, b"gats", Some(exptime), &[key.as_ref()])
2864                        .await?
2865                        .pop(),
2866                )
2867            }
2868            Connection::Tls(s) => Ok(retrieval_cmd(s, b"gats", Some(exptime), &[key.as_ref()])
2869                .await?
2870                .pop()),
2871        }
2872    }
2873
2874    /// # Example
2875    ///
2876    /// ```
2877    /// # use mcmc_rs::Connection;
2878    /// # use smol::{io, block_on};
2879    /// #
2880    /// # block_on(async {
2881    /// for mut c in [
2882    ///     Connection::default().await?,
2883    ///     Connection::unix_connect("/tmp/memcached0.sock").await?,
2884    ///     Connection::udp_connect("127.0.0.1:0", "127.0.0.1:11214").await?,
2885    ///     Connection::tls_connect("localhost", 11216, "cert.pem").await?,
2886    /// ] {
2887    ///     assert!(c.set(b"k8", 0, 0, false, b"v8").await?);
2888    ///     let result = c.get_multi(&[b"k8"]).await?;
2889    ///     assert_eq!(result[0].key, "k8");
2890    /// }
2891    /// #     Ok::<(), io::Error>(())
2892    /// # }).unwrap()
2893    /// ```
2894    pub async fn get_multi(&mut self, keys: &[impl AsRef<[u8]>]) -> io::Result<Vec<Item>> {
2895        match self {
2896            Connection::Tcp(s) => {
2897                retrieval_cmd(
2898                    s,
2899                    b"get",
2900                    None,
2901                    &keys.iter().map(|x| x.as_ref()).collect::<Vec<&[u8]>>(),
2902                )
2903                .await
2904            }
2905            Connection::Unix(s) => {
2906                retrieval_cmd(
2907                    s,
2908                    b"get",
2909                    None,
2910                    &keys.iter().map(|x| x.as_ref()).collect::<Vec<&[u8]>>(),
2911                )
2912                .await
2913            }
2914            Connection::Udp(s, r) => {
2915                retrieval_cmd_udp(
2916                    s,
2917                    r,
2918                    b"get",
2919                    None,
2920                    &keys.iter().map(|x| x.as_ref()).collect::<Vec<&[u8]>>(),
2921                )
2922                .await
2923            }
2924            Connection::Tls(s) => {
2925                retrieval_cmd(
2926                    s,
2927                    b"get",
2928                    None,
2929                    &keys.iter().map(|x| x.as_ref()).collect::<Vec<&[u8]>>(),
2930                )
2931                .await
2932            }
2933        }
2934    }
2935
2936    /// # Example
2937    ///
2938    /// ```
2939    /// # use mcmc_rs::Connection;
2940    /// # use smol::{io, block_on};
2941    /// #
2942    /// # block_on(async {
2943    /// for mut c in [
2944    ///     Connection::default().await?,
2945    ///     Connection::unix_connect("/tmp/memcached0.sock").await?,
2946    ///     Connection::udp_connect("127.0.0.1:0", "127.0.0.1:11214").await?,
2947    ///     Connection::tls_connect("localhost", 11216, "cert.pem").await?,
2948    /// ] {
2949    ///     assert!(c.set(b"k7", 0, 0, false, b"v7").await?);
2950    ///     let result = c.gets_multi(&[b"k7"]).await?;
2951    ///     assert_eq!(result[0].key, "k7");
2952    /// }
2953    /// #     Ok::<(), io::Error>(())
2954    /// # }).unwrap()
2955    /// ```
2956    pub async fn gets_multi(&mut self, keys: &[impl AsRef<[u8]>]) -> io::Result<Vec<Item>> {
2957        match self {
2958            Connection::Tcp(s) => {
2959                retrieval_cmd(
2960                    s,
2961                    b"gets",
2962                    None,
2963                    &keys.iter().map(|x| x.as_ref()).collect::<Vec<&[u8]>>(),
2964                )
2965                .await
2966            }
2967            Connection::Unix(s) => {
2968                retrieval_cmd(
2969                    s,
2970                    b"gets",
2971                    None,
2972                    &keys.iter().map(|x| x.as_ref()).collect::<Vec<&[u8]>>(),
2973                )
2974                .await
2975            }
2976            Connection::Udp(s, r) => {
2977                retrieval_cmd_udp(
2978                    s,
2979                    r,
2980                    b"gets",
2981                    None,
2982                    &keys.iter().map(|x| x.as_ref()).collect::<Vec<&[u8]>>(),
2983                )
2984                .await
2985            }
2986            Connection::Tls(s) => {
2987                retrieval_cmd(
2988                    s,
2989                    b"gets",
2990                    None,
2991                    &keys.iter().map(|x| x.as_ref()).collect::<Vec<&[u8]>>(),
2992                )
2993                .await
2994            }
2995        }
2996    }
2997
2998    /// # Example
2999    ///
3000    /// ```
3001    /// # use mcmc_rs::Connection;
3002    /// # use smol::{io, block_on};
3003    /// #
3004    /// # block_on(async {
3005    /// for mut c in [
3006    ///     Connection::default().await?,
3007    ///     Connection::unix_connect("/tmp/memcached0.sock").await?,
3008    ///     Connection::udp_connect("127.0.0.1:0", "127.0.0.1:11214").await?,
3009    ///     Connection::tls_connect("localhost", 11216, "cert.pem").await?,
3010    /// ] {
3011    ///     assert!(c.set(b"k6", 0, 0, false, b"v6").await?);
3012    ///     let result = c.gat_multi(0, &[b"k6"]).await?;
3013    ///     assert_eq!(result[0].key, "k6");
3014    /// }
3015    /// #     Ok::<(), io::Error>(())
3016    /// # }).unwrap()
3017    /// ```
3018    pub async fn gat_multi(
3019        &mut self,
3020        exptime: i64,
3021        keys: &[impl AsRef<[u8]>],
3022    ) -> io::Result<Vec<Item>> {
3023        match self {
3024            Connection::Tcp(s) => {
3025                retrieval_cmd(
3026                    s,
3027                    b"gat",
3028                    Some(exptime),
3029                    &keys.iter().map(|x| x.as_ref()).collect::<Vec<&[u8]>>(),
3030                )
3031                .await
3032            }
3033            Connection::Unix(s) => {
3034                retrieval_cmd(
3035                    s,
3036                    b"gat",
3037                    Some(exptime),
3038                    &keys.iter().map(|x| x.as_ref()).collect::<Vec<&[u8]>>(),
3039                )
3040                .await
3041            }
3042            Connection::Udp(s, r) => {
3043                retrieval_cmd_udp(
3044                    s,
3045                    r,
3046                    b"gat",
3047                    Some(exptime),
3048                    &keys.iter().map(|x| x.as_ref()).collect::<Vec<&[u8]>>(),
3049                )
3050                .await
3051            }
3052            Connection::Tls(s) => {
3053                retrieval_cmd(
3054                    s,
3055                    b"gat",
3056                    Some(exptime),
3057                    &keys.iter().map(|x| x.as_ref()).collect::<Vec<&[u8]>>(),
3058                )
3059                .await
3060            }
3061        }
3062    }
3063
3064    /// # Example
3065    ///
3066    /// ```
3067    /// # use mcmc_rs::Connection;
3068    /// # use smol::{io, block_on};
3069    /// #
3070    /// # block_on(async {
3071    /// for mut c in [
3072    ///     Connection::default().await?,
3073    ///     Connection::unix_connect("/tmp/memcached0.sock").await?,
3074    ///     Connection::udp_connect("127.0.0.1:0", "127.0.0.1:11214").await?,
3075    ///     Connection::tls_connect("localhost", 11216, "cert.pem").await?,
3076    /// ] {
3077    ///     assert!(c.set(b"k5", 0, 0, false, b"v5").await?);
3078    ///     let result = c.gats_multi(0, &[b"k5"]).await?;
3079    ///     assert_eq!(result[0].key, "k5");
3080    /// }
3081    /// #     Ok::<(), io::Error>(())
3082    /// # }).unwrap()
3083    /// ```
3084    pub async fn gats_multi(
3085        &mut self,
3086        exptime: i64,
3087        keys: &[impl AsRef<[u8]>],
3088    ) -> io::Result<Vec<Item>> {
3089        match self {
3090            Connection::Tcp(s) => {
3091                retrieval_cmd(
3092                    s,
3093                    b"gats",
3094                    Some(exptime),
3095                    &keys.iter().map(|x| x.as_ref()).collect::<Vec<&[u8]>>(),
3096                )
3097                .await
3098            }
3099            Connection::Unix(s) => {
3100                retrieval_cmd(
3101                    s,
3102                    b"gats",
3103                    Some(exptime),
3104                    &keys.iter().map(|x| x.as_ref()).collect::<Vec<&[u8]>>(),
3105                )
3106                .await
3107            }
3108            Connection::Udp(s, r) => {
3109                retrieval_cmd_udp(
3110                    s,
3111                    r,
3112                    b"gats",
3113                    Some(exptime),
3114                    &keys.iter().map(|x| x.as_ref()).collect::<Vec<&[u8]>>(),
3115                )
3116                .await
3117            }
3118            Connection::Tls(s) => {
3119                retrieval_cmd(
3120                    s,
3121                    b"gats",
3122                    Some(exptime),
3123                    &keys.iter().map(|x| x.as_ref()).collect::<Vec<&[u8]>>(),
3124                )
3125                .await
3126            }
3127        }
3128    }
3129
3130    /// # Example
3131    ///
3132    /// ```
3133    /// # use mcmc_rs::Connection;
3134    /// # use smol::{io, block_on};
3135    /// #
3136    /// # block_on(async {
3137    /// for mut c in [
3138    ///     Connection::default().await?,
3139    ///     Connection::unix_connect("/tmp/memcached0.sock").await?,
3140    ///     Connection::udp_connect("127.0.0.1:0", "127.0.0.1:11214").await?,
3141    ///     Connection::tls_connect("localhost", 11216, "cert.pem").await?,
3142    /// ] {
3143    ///     let result = c.stats(None).await?;
3144    ///     assert!(result.len() > 0);
3145    /// }
3146    /// #     Ok::<(), io::Error>(())
3147    /// # }).unwrap()
3148    /// ```
3149    pub async fn stats(&mut self, arg: Option<StatsArg>) -> io::Result<HashMap<String, String>> {
3150        match self {
3151            Connection::Tcp(s) => stats_cmd(s, arg).await,
3152            Connection::Unix(s) => stats_cmd(s, arg).await,
3153            Connection::Udp(s, r) => stats_cmd_udp(s, r, arg).await,
3154            Connection::Tls(s) => stats_cmd(s, arg).await,
3155        }
3156    }
3157
3158    /// # Example
3159    ///
3160    /// ```
3161    /// # use mcmc_rs::{Connection, SlabsAutomoveArg};
3162    /// # use smol::{io, block_on};
3163    /// #
3164    /// # block_on(async {
3165    /// for mut c in [
3166    ///     Connection::default().await?,
3167    ///     Connection::unix_connect("/tmp/memcached0.sock").await?,
3168    ///     Connection::udp_connect("127.0.0.1:0", "127.0.0.1:11214").await?,
3169    ///     Connection::tls_connect("localhost", 11216, "cert.pem").await?,
3170    /// ] {
3171    ///     c.slabs_automove(SlabsAutomoveArg::Zero).await?;
3172    /// }
3173    /// #     Ok::<(), io::Error>(())
3174    /// # }).unwrap()
3175    /// ```
3176    pub async fn slabs_automove(&mut self, arg: SlabsAutomoveArg) -> io::Result<()> {
3177        match self {
3178            Connection::Tcp(s) => slabs_automove_cmd(s, arg).await,
3179            Connection::Unix(s) => slabs_automove_cmd(s, arg).await,
3180            Connection::Udp(s, r) => slabs_automove_cmd_udp(s, r, arg).await,
3181            Connection::Tls(s) => slabs_automove_cmd(s, arg).await,
3182        }
3183    }
3184
3185    /// # Example
3186    ///
3187    /// ```
3188    /// # use mcmc_rs::{Connection, LruCrawlerArg};
3189    /// # use smol::{io, block_on};
3190    /// #
3191    /// # block_on(async {
3192    /// for mut c in [
3193    ///     Connection::default().await?,
3194    ///     Connection::unix_connect("/tmp/memcached0.sock").await?,
3195    ///     Connection::udp_connect("127.0.0.1:0", "127.0.0.1:11214").await?,
3196    ///     Connection::tls_connect("localhost", 11216, "cert.pem").await?,
3197    /// ] {
3198    ///     let result = c.lru_crawler(LruCrawlerArg::Enable).await;
3199    ///     assert!(result.is_err());
3200    /// }
3201    /// #     Ok::<(), io::Error>(())
3202    /// # }).unwrap()
3203    /// ```
3204    pub async fn lru_crawler(&mut self, arg: LruCrawlerArg) -> io::Result<()> {
3205        match self {
3206            Connection::Tcp(s) => lru_crawler_cmd(s, arg).await,
3207            Connection::Unix(s) => lru_crawler_cmd(s, arg).await,
3208            Connection::Udp(s, r) => lru_crawler_cmd_udp(s, r, arg).await,
3209            Connection::Tls(s) => lru_crawler_cmd(s, arg).await,
3210        }
3211    }
3212
3213    /// # Example
3214    ///
3215    /// ```
3216    /// # use mcmc_rs::Connection;
3217    /// # use smol::{io, block_on};
3218    /// #
3219    /// # block_on(async {
3220    /// for mut c in [
3221    ///     Connection::default().await?,
3222    ///     Connection::unix_connect("/tmp/memcached0.sock").await?,
3223    ///     Connection::udp_connect("127.0.0.1:0", "127.0.0.1:11214").await?,
3224    ///     Connection::tls_connect("localhost", 11216, "cert.pem").await?,
3225    /// ] {
3226    ///     c.lru_crawler_sleep(1_000_000).await?;
3227    /// }
3228    /// #     Ok::<(), io::Error>(())
3229    /// # }).unwrap()
3230    /// ```
3231    pub async fn lru_crawler_sleep(&mut self, microseconds: usize) -> io::Result<()> {
3232        match self {
3233            Connection::Tcp(s) => lru_crawler_sleep_cmd(s, microseconds).await,
3234            Connection::Unix(s) => lru_crawler_sleep_cmd(s, microseconds).await,
3235            Connection::Udp(s, r) => lru_crawler_sleep_cmd_udp(s, r, microseconds).await,
3236            Connection::Tls(s) => lru_crawler_sleep_cmd(s, microseconds).await,
3237        }
3238    }
3239
3240    /// # Example
3241    ///
3242    /// ```
3243    /// # use mcmc_rs::Connection;
3244    /// # use smol::{io, block_on};
3245    /// #
3246    /// # block_on(async {
3247    /// for mut c in [
3248    ///     Connection::default().await?,
3249    ///     Connection::unix_connect("/tmp/memcached0.sock").await?,
3250    ///     Connection::udp_connect("127.0.0.1:0", "127.0.0.1:11214").await?,
3251    ///     Connection::tls_connect("localhost", 11216, "cert.pem").await?,
3252    /// ] {
3253    ///     c.lru_crawler_tocrawl(0).await?;
3254    /// }
3255    /// #     Ok::<(), io::Error>(())
3256    /// # }).unwrap()
3257    /// ```
3258    pub async fn lru_crawler_tocrawl(&mut self, arg: u32) -> io::Result<()> {
3259        match self {
3260            Connection::Tcp(s) => lru_crawler_tocrawl_cmd(s, arg).await,
3261            Connection::Unix(s) => lru_crawler_tocrawl_cmd(s, arg).await,
3262            Connection::Udp(s, r) => lru_crawler_tocrawl_cmd_udp(s, r, arg).await,
3263            Connection::Tls(s) => lru_crawler_tocrawl_cmd(s, arg).await,
3264        }
3265    }
3266
3267    /// # Example
3268    ///
3269    /// ```
3270    /// # use mcmc_rs::{Connection, LruCrawlerCrawlArg};
3271    /// # use smol::{io, block_on};
3272    /// #
3273    /// # block_on(async {
3274    /// for mut c in [
3275    ///     Connection::default().await?,
3276    ///     Connection::unix_connect("/tmp/memcached0.sock").await?,
3277    ///     Connection::udp_connect("127.0.0.1:0", "127.0.0.1:11214").await?,
3278    ///     Connection::tls_connect("localhost", 11216, "cert.pem").await?,
3279    /// ] {
3280    ///     c.lru_crawler_crawl(LruCrawlerCrawlArg::All).await?;
3281    /// }
3282    /// #     Ok::<(), io::Error>(())
3283    /// # }).unwrap()
3284    /// ```
3285    pub async fn lru_crawler_crawl(&mut self, arg: LruCrawlerCrawlArg<'_>) -> io::Result<()> {
3286        match self {
3287            Connection::Tcp(s) => lru_crawler_crawl_cmd(s, arg).await,
3288            Connection::Unix(s) => lru_crawler_crawl_cmd(s, arg).await,
3289            Connection::Udp(s, r) => lru_crawler_crawl_cmd_udp(s, r, arg).await,
3290            Connection::Tls(s) => lru_crawler_crawl_cmd(s, arg).await,
3291        }
3292    }
3293
3294    /// # Example
3295    ///
3296    /// ```
3297    /// # use mcmc_rs::Connection;
3298    /// # use smol::{io, block_on};
3299    /// #
3300    /// # block_on(async {
3301    /// for mut c in [
3302    ///     Connection::default().await?,
3303    ///     Connection::unix_connect("/tmp/memcached0.sock").await?,
3304    ///     Connection::udp_connect("127.0.0.1:0", "127.0.0.1:11214").await?,
3305    ///     Connection::tls_connect("localhost", 11216, "cert.pem").await?,
3306    /// ] {
3307    ///     let result = c.slabs_reassign(1, 2).await;
3308    ///     assert!(result.is_err());
3309    /// }
3310    /// #     Ok::<(), io::Error>(())
3311    /// # }).unwrap()
3312    /// ```
3313    pub async fn slabs_reassign(
3314        &mut self,
3315        source_class: isize,
3316        dest_class: isize,
3317    ) -> io::Result<()> {
3318        match self {
3319            Connection::Tcp(s) => slabs_reassign_cmd(s, source_class, dest_class).await,
3320            Connection::Unix(s) => slabs_reassign_cmd(s, source_class, dest_class).await,
3321            Connection::Udp(s, r) => slabs_reassign_cmd_udp(s, r, source_class, dest_class).await,
3322            Connection::Tls(s) => slabs_reassign_cmd(s, source_class, dest_class).await,
3323        }
3324    }
3325
3326    /// # Example
3327    ///
3328    /// ```
3329    /// # use mcmc_rs::{Connection, LruCrawlerMetadumpArg};
3330    /// # use smol::{io, block_on};
3331    /// #
3332    /// # block_on(async {
3333    /// for mut c in [
3334    ///     Connection::default().await?,
3335    ///     Connection::unix_connect("/tmp/memcached0.sock").await?,
3336    ///     Connection::tls_connect("localhost", 11216, "cert.pem").await?,
3337    /// ] {
3338    ///     let result = c
3339    ///         .lru_crawler_metadump(LruCrawlerMetadumpArg::Classids(&[2]))
3340    ///         .await?;
3341    ///     assert!(result.is_empty());
3342    /// }
3343    /// #     Ok::<(), io::Error>(())
3344    /// # }).unwrap()
3345    /// ```
3346    pub async fn lru_crawler_metadump(
3347        &mut self,
3348        arg: LruCrawlerMetadumpArg<'_>,
3349    ) -> io::Result<Vec<String>> {
3350        match self {
3351            Connection::Tcp(s) => lru_crawler_metadump_cmd(s, arg).await,
3352            Connection::Unix(s) => lru_crawler_metadump_cmd(s, arg).await,
3353            Connection::Udp(_s, _r) => unreachable!("this command not work with udp connection!"),
3354            Connection::Tls(s) => lru_crawler_metadump_cmd(s, arg).await,
3355        }
3356    }
3357
3358    /// # Example
3359    ///
3360    /// ```
3361    /// # use mcmc_rs::{Connection, LruCrawlerMgdumpArg};
3362    /// # use smol::{io, block_on};
3363    /// #
3364    /// # block_on(async {
3365    /// for mut c in [
3366    ///     Connection::default().await?,
3367    ///     Connection::unix_connect("/tmp/memcached0.sock").await?,
3368    ///     Connection::tls_connect("localhost", 11216, "cert.pem").await?,
3369    /// ] {
3370    ///     let result = c
3371    ///         .lru_crawler_mgdump(LruCrawlerMgdumpArg::Classids(&[2]))
3372    ///         .await?;
3373    ///     assert!(result.is_empty());
3374    /// }
3375    /// #     Ok::<(), io::Error>(())
3376    /// # }).unwrap()
3377    /// ```
3378    pub async fn lru_crawler_mgdump(
3379        &mut self,
3380        arg: LruCrawlerMgdumpArg<'_>,
3381    ) -> io::Result<Vec<String>> {
3382        match self {
3383            Connection::Tcp(s) => lru_crawler_mgdump_cmd(s, arg).await,
3384            Connection::Unix(s) => lru_crawler_mgdump_cmd(s, arg).await,
3385            Connection::Udp(_s, _r) => unreachable!("this command not work with udp connection!"),
3386            Connection::Tls(s) => lru_crawler_mgdump_cmd(s, arg).await,
3387        }
3388    }
3389
3390    /// # Example
3391    ///
3392    /// ```
3393    /// # use mcmc_rs::Connection;
3394    /// # use smol::{io, block_on};
3395    /// #
3396    /// # block_on(async {
3397    /// for mut c in [
3398    ///     Connection::default().await?,
3399    ///     Connection::unix_connect("/tmp/memcached0.sock").await?,
3400    ///     Connection::udp_connect("127.0.0.1:0", "127.0.0.1:11214").await?,
3401    ///     Connection::tls_connect("localhost", 11216, "cert.pem").await?,
3402    /// ] {
3403    ///     c.mn().await?;
3404    /// }
3405    /// #     Ok::<(), io::Error>(())
3406    /// # }).unwrap()
3407    /// ```
3408    pub async fn mn(&mut self) -> io::Result<()> {
3409        match self {
3410            Connection::Tcp(s) => mn_cmd(s).await,
3411            Connection::Unix(s) => mn_cmd(s).await,
3412            Connection::Udp(s, r) => mn_cmd_udp(s, r).await,
3413            Connection::Tls(s) => mn_cmd(s).await,
3414        }
3415    }
3416
3417    /// # Example
3418    ///
3419    /// ```
3420    /// # use mcmc_rs::{Connection, LruCrawlerCrawlArg};
3421    /// # use smol::{io, block_on};
3422    /// #
3423    /// # block_on(async {
3424    /// for mut c in [
3425    ///     Connection::default().await?,
3426    ///     Connection::unix_connect("/tmp/memcached0.sock").await?,
3427    ///     Connection::udp_connect("127.0.0.1:0", "127.0.0.1:11214").await?,
3428    ///     Connection::tls_connect("localhost", 11216, "cert.pem").await?,
3429    /// ] {
3430    ///     c.set(b"k9", 0, 0, false, b"v9").await?;
3431    ///     assert!(c.me(b"k9").await?.is_some());
3432    /// }
3433    /// #     Ok::<(), io::Error>(())
3434    /// # }).unwrap()
3435    /// ```
3436    pub async fn me(&mut self, key: impl AsRef<[u8]>) -> io::Result<Option<String>> {
3437        match self {
3438            Connection::Tcp(s) => me_cmd(s, key.as_ref()).await,
3439            Connection::Unix(s) => me_cmd(s, key.as_ref()).await,
3440            Connection::Udp(s, r) => me_cmd_udp(s, r, key.as_ref()).await,
3441            Connection::Tls(s) => me_cmd(s, key.as_ref()).await,
3442        }
3443    }
3444
3445    /// # Example
3446    ///
3447    /// ```
3448    /// # use mcmc_rs::{Connection, WatchArg};
3449    /// # use smol::{io, block_on};
3450    /// #
3451    /// # block_on(async {
3452    /// for mut c in [
3453    ///     Connection::default().await?,
3454    ///     Connection::unix_connect("/tmp/memcached0.sock").await?,
3455    ///     Connection::tls_connect("localhost", 11216, "cert.pem").await?,
3456    /// ] {
3457    ///     assert!(c.watch(&[WatchArg::Fetchers]).await.is_ok())
3458    /// }
3459    /// #     Ok::<(), io::Error>(())
3460    /// # }).unwrap()
3461    /// ```
3462    pub async fn watch(mut self, arg: &[WatchArg]) -> io::Result<WatchStream> {
3463        match &mut self {
3464            Connection::Tcp(s) => watch_cmd(s, arg).await?,
3465            Connection::Unix(s) => watch_cmd(s, arg).await?,
3466            Connection::Udp(_s, _r) => unreachable!("this command not work with udp!"),
3467            Connection::Tls(s) => watch_cmd(s, arg).await?,
3468        };
3469        Ok(WatchStream(self))
3470    }
3471
3472    pub fn pipeline(&mut self) -> Pipeline<'_> {
3473        Pipeline::new(self)
3474    }
3475
3476    /// # Example
3477    ///
3478    /// ```
3479    /// # use mcmc_rs::{Connection, MgFlag, MgItem};
3480    /// # use smol::{io, block_on};
3481    /// #
3482    /// # block_on(async {
3483    /// for mut c in [
3484    ///     Connection::default().await?,
3485    ///     Connection::unix_connect("/tmp/memcached0.sock").await?,
3486    ///     Connection::udp_connect("127.0.0.1:0", "127.0.0.1:11214").await?,
3487    ///     Connection::tls_connect("localhost", 11216, "cert.pem").await?,
3488    /// ] {
3489    ///     let result = c
3490    ///         .mg(
3491    ///             b"44OG44K544OI",
3492    ///             &[
3493    ///                 MgFlag::Base64Key,
3494    ///                 MgFlag::ReturnCas,
3495    ///                 MgFlag::CheckCas(99),
3496    ///                 MgFlag::ReturnFlags,
3497    ///                 MgFlag::ReturnHit,
3498    ///                 MgFlag::ReturnKey,
3499    ///                 MgFlag::ReturnLastAccess,
3500    ///                 MgFlag::Opaque("opaque".to_string()),
3501    ///                 MgFlag::ReturnSize,
3502    ///                 MgFlag::ReturnTtl,
3503    ///                 MgFlag::UnBump,
3504    ///                 MgFlag::ReturnValue,
3505    ///                 MgFlag::NewCas(0),
3506    ///                 MgFlag::Autovivify(-1),
3507    ///                 MgFlag::RecacheTtl(-1),
3508    ///                 MgFlag::UpdateTtl(-1),
3509    ///             ],
3510    ///         )
3511    ///         .await?;
3512    ///     assert_eq!(
3513    ///         result,
3514    ///         MgItem {
3515    ///             success: true,
3516    ///             base64_key: false,
3517    ///             cas: Some(0),
3518    ///             flags: Some(0),
3519    ///             hit: Some(0),
3520    ///             key: Some("テスト".to_string()),
3521    ///             last_access_ttl: Some(0),
3522    ///             opaque: Some("opaque".to_string()),
3523    ///             size: Some(0),
3524    ///             ttl: Some(-1),
3525    ///             data_block: Some(vec![]),
3526    ///             already_win: false,
3527    ///             won_recache: true,
3528    ///             stale: false,
3529    ///         }
3530    ///     );
3531    /// }
3532    /// #     Ok::<(), io::Error>(())
3533    /// # }).unwrap()
3534    /// ```
3535    pub async fn mg(&mut self, key: impl AsRef<[u8]>, flags: &[MgFlag]) -> io::Result<MgItem> {
3536        match self {
3537            Connection::Tcp(s) => mg_cmd(s, key.as_ref(), flags).await,
3538            Connection::Unix(s) => mg_cmd(s, key.as_ref(), flags).await,
3539            Connection::Udp(s, r) => mg_cmd_udp(s, r, key.as_ref(), flags).await,
3540            Connection::Tls(s) => mg_cmd(s, key.as_ref(), flags).await,
3541        }
3542    }
3543
3544    /// # Example
3545    ///
3546    /// ```
3547    /// # use mcmc_rs::{Connection, MsFlag, MsMode, MsItem};
3548    /// # use smol::{io, block_on};
3549    /// #
3550    /// # block_on(async {
3551    /// for mut c in [
3552    ///     Connection::default().await?,
3553    ///     Connection::unix_connect("/tmp/memcached0.sock").await?,
3554    ///     Connection::udp_connect("127.0.0.1:0", "127.0.0.1:11214").await?,
3555    ///     Connection::tls_connect("localhost", 11216, "cert.pem").await?,
3556    /// ] {
3557    ///     let result = c
3558    ///         .ms(
3559    ///             b"44OG44K544OI",
3560    ///             &[
3561    ///                 MsFlag::Base64Key,
3562    ///                 MsFlag::ReturnCas,
3563    ///                 MsFlag::CompareCas(0),
3564    ///                 MsFlag::NewCas(0),
3565    ///                 MsFlag::SetFlags(0),
3566    ///                 MsFlag::Invalidate,
3567    ///                 MsFlag::ReturnKey,
3568    ///                 MsFlag::Opaque("opaque".to_string()),
3569    ///                 MsFlag::ReturnSize,
3570    ///                 MsFlag::Ttl(-1),
3571    ///                 MsFlag::Mode(MsMode::Set),
3572    ///                 MsFlag::Autovivify(0),
3573    ///             ],
3574    ///             b"hi",
3575    ///         )
3576    ///         .await?;
3577    ///     assert_eq!(
3578    ///         result,
3579    ///         MsItem {
3580    ///             success: false,
3581    ///             cas: Some(0),
3582    ///             key: Some("44OG44K544OI".to_string()),
3583    ///             opaque: Some("opaque".to_string()),
3584    ///             size: Some(2),
3585    ///             base64_key: true
3586    ///         }
3587    ///     );
3588    /// }
3589    /// # Ok::<(), io::Error>(())
3590    /// # }).unwrap()
3591    /// ```
3592    pub async fn ms(
3593        &mut self,
3594        key: impl AsRef<[u8]>,
3595        flags: &[MsFlag],
3596        data_block: impl AsRef<[u8]>,
3597    ) -> io::Result<MsItem> {
3598        match self {
3599            Connection::Tcp(s) => ms_cmd(s, key.as_ref(), flags, data_block.as_ref()).await,
3600            Connection::Unix(s) => ms_cmd(s, key.as_ref(), flags, data_block.as_ref()).await,
3601            Connection::Udp(s, r) => {
3602                ms_cmd_udp(s, r, key.as_ref(), flags, data_block.as_ref()).await
3603            }
3604            Connection::Tls(s) => ms_cmd(s, key.as_ref(), flags, data_block.as_ref()).await,
3605        }
3606    }
3607
3608    /// # Example
3609    ///
3610    /// ```
3611    /// # use mcmc_rs::{Connection, MdFlag, MdItem};
3612    /// # use smol::{io, block_on};
3613    /// #
3614    /// # block_on(async {
3615    /// for mut c in [
3616    ///     Connection::default().await?,
3617    ///     Connection::unix_connect("/tmp/memcached0.sock").await?,
3618    ///     Connection::udp_connect("127.0.0.1:0", "127.0.0.1:11214").await?,
3619    ///     Connection::tls_connect("localhost", 11216, "cert.pem").await?,
3620    /// ] {
3621    ///     let result = c
3622    ///         .md(
3623    ///             b"44OG44K544OI",
3624    ///             &[
3625    ///                 MdFlag::Base64Key,
3626    ///                 MdFlag::CompareCas(0),
3627    ///                 MdFlag::NewCas(0),
3628    ///                 MdFlag::Invalidate,
3629    ///                 MdFlag::ReturnKey,
3630    ///                 MdFlag::Opaque("opaque".to_string()),
3631    ///                 MdFlag::UpdateTtl(-1),
3632    ///                 MdFlag::LeaveKey,
3633    ///             ],
3634    ///         )
3635    ///         .await?;
3636    ///     assert_eq!(
3637    ///         result,
3638    ///         MdItem {
3639    ///             success: false,
3640    ///             key: Some("44OG44K544OI".to_string()),
3641    ///             opaque: Some("opaque".to_string()),
3642    ///             base64_key: true
3643    ///         }
3644    ///     );
3645    /// }
3646    /// #     Ok::<(), io::Error>(())
3647    /// # }).unwrap()
3648    /// ```
3649    pub async fn md(&mut self, key: impl AsRef<[u8]>, flags: &[MdFlag]) -> io::Result<MdItem> {
3650        match self {
3651            Connection::Tcp(s) => md_cmd(s, key.as_ref(), flags).await,
3652            Connection::Unix(s) => md_cmd(s, key.as_ref(), flags).await,
3653            Connection::Udp(s, r) => md_cmd_udp(s, r, key.as_ref(), flags).await,
3654            Connection::Tls(s) => md_cmd(s, key.as_ref(), flags).await,
3655        }
3656    }
3657
3658    /// # Example
3659    ///
3660    /// ```
3661    /// # use mcmc_rs::{Connection, MaFlag, MaMode, MaItem};
3662    /// # use smol::{io, block_on};
3663    /// #
3664    /// # block_on(async {
3665    /// for mut c in [
3666    ///     Connection::default().await?,
3667    ///     Connection::unix_connect("/tmp/memcached0.sock").await?,
3668    ///     Connection::udp_connect("127.0.0.1:0", "127.0.0.1:11214").await?,
3669    ///     Connection::tls_connect("localhost", 11216, "cert.pem").await?,
3670    /// ] {
3671    ///     let result = c
3672    ///         .ma(
3673    ///             b"aGk=",
3674    ///             &[
3675    ///                 MaFlag::Base64Key,
3676    ///                 MaFlag::CompareCas(0),
3677    ///                 MaFlag::NewCas(0),
3678    ///                 MaFlag::AutoCreate(0),
3679    ///                 MaFlag::InitValue(0),
3680    ///                 MaFlag::DeltaApply(0),
3681    ///                 MaFlag::UpdateTtl(0),
3682    ///                 MaFlag::Mode(MaMode::Incr),
3683    ///                 MaFlag::Opaque("opaque".to_string()),
3684    ///                 MaFlag::ReturnTtl,
3685    ///                 MaFlag::ReturnCas,
3686    ///                 MaFlag::ReturnValue,
3687    ///                 MaFlag::ReturnKey,
3688    ///             ],
3689    ///         )
3690    ///         .await?;
3691    ///     assert_eq!(
3692    ///         result,
3693    ///         MaItem {
3694    ///             success: true,
3695    ///             opaque: Some("opaque".to_string()),
3696    ///             ttl: Some(-1),
3697    ///             cas: Some(0),
3698    ///             number: Some(0),
3699    ///             key: Some("aGk=".to_string()),
3700    ///             base64_key: true
3701    ///         }
3702    ///     );
3703    /// }
3704    /// #     Ok::<(), io::Error>(())
3705    /// # }).unwrap()
3706    /// ```
3707    pub async fn ma(&mut self, key: impl AsRef<[u8]>, flags: &[MaFlag]) -> io::Result<MaItem> {
3708        match self {
3709            Connection::Tcp(s) => ma_cmd(s, key.as_ref(), flags).await,
3710            Connection::Unix(s) => ma_cmd(s, key.as_ref(), flags).await,
3711            Connection::Udp(s, r) => ma_cmd_udp(s, r, key.as_ref(), flags).await,
3712            Connection::Tls(s) => ma_cmd(s, key.as_ref(), flags).await,
3713        }
3714    }
3715
3716    /// # Example
3717    ///
3718    /// ```
3719    /// use mcmc_rs::{Connection, LruArg, LruMode};
3720    /// # use smol::{io, block_on};
3721    /// #
3722    /// # block_on(async {
3723    /// for mut c in [
3724    ///     Connection::default().await?,
3725    ///     Connection::unix_connect("/tmp/memcached0.sock").await?,
3726    ///     Connection::udp_connect("127.0.0.1:0", "127.0.0.1:11214").await?,
3727    ///     Connection::tls_connect("localhost", 11216, "cert.pem").await?,
3728    /// ] {
3729    ///     assert!(c.lru(LruArg::Mode(LruMode::Flat)).await.is_ok())
3730    /// }
3731    /// # Ok::<(), io::Error>(())
3732    /// # }).unwrap()
3733    /// ```
3734    pub async fn lru(&mut self, arg: LruArg) -> io::Result<()> {
3735        match self {
3736            Connection::Tcp(s) => lru_cmd(s, arg).await,
3737            Connection::Unix(s) => lru_cmd(s, arg).await,
3738            Connection::Udp(s, r) => lru_cmd_udp(s, r, arg).await,
3739            Connection::Tls(s) => lru_cmd(s, arg).await,
3740        }
3741    }
3742}
3743
3744pub struct WatchStream(Connection);
3745impl WatchStream {
3746    /// # Example
3747    ///
3748    /// ```
3749    /// use mcmc_rs::{Connection, WatchArg};
3750    /// # use smol::{io, block_on};
3751    /// #
3752    /// # block_on(async {
3753    ///
3754    /// for (mut c1, mut c2) in [
3755    ///     (Connection::default().await?, Connection::default().await?),
3756    ///     (
3757    ///         Connection::unix_connect("/tmp/memcached0.sock").await?,
3758    ///         Connection::unix_connect("/tmp/memcached0.sock").await?,
3759    ///     ),
3760    ///     (
3761    ///         Connection::tls_connect("localhost", 11216, "cert.pem").await?,
3762    ///         Connection::tls_connect("localhost", 11216, "cert.pem").await?,
3763    ///     ),
3764    /// ] {
3765    ///     let mut w = c1.watch(&[WatchArg::Fetchers]).await?;
3766    ///     c2.get(b"key").await?;
3767    ///     let result = w.message().await?;
3768    ///     assert!(result.is_some())
3769    /// }
3770    /// # Ok::<(), io::Error>(())
3771    /// # }).unwrap()
3772    /// ```
3773    pub async fn message(&mut self) -> io::Result<Option<String>> {
3774        let mut line = String::new();
3775        let n = match &mut self.0 {
3776            Connection::Tcp(s) => s.read_line(&mut line).await?,
3777            Connection::Unix(s) => s.read_line(&mut line).await?,
3778            Connection::Udp(_s, _r) => unreachable!("this command not work with udp connection"),
3779            Connection::Tls(s) => s.read_line(&mut line).await?,
3780        };
3781        if n == 0 {
3782            Ok(None)
3783        } else {
3784            Ok(Some(line.trim_end().to_string()))
3785        }
3786    }
3787}
3788
3789pub struct ClientCrc32(Vec<Connection>);
3790impl ClientCrc32 {
3791    /// # Example
3792    ///
3793    /// ```
3794    /// use mcmc_rs::{ClientCrc32, Connection};
3795    /// # use smol::{io, block_on};
3796    /// #
3797    /// # block_on(async {
3798    /// let mut client = ClientCrc32::new(vec![
3799    ///     Connection::default().await?,
3800    ///     Connection::unix_connect("/tmp/memcached0.sock").await?,
3801    /// ]);
3802    /// # Ok::<(), io::Error>(())
3803    /// # }).unwrap()
3804    /// ```
3805    pub fn new(conns: Vec<Connection>) -> Self {
3806        Self(conns)
3807    }
3808
3809    /// # Example
3810    ///
3811    /// ```
3812    /// use mcmc_rs::{ClientCrc32, Connection};
3813    /// # use smol::{io, block_on};
3814    /// #
3815    /// # block_on(async {
3816    /// let mut client = ClientCrc32::new(vec![
3817    ///     Connection::default().await?,
3818    ///     Connection::unix_connect("/tmp/memcached0.sock").await?,
3819    /// ]);
3820    ///
3821    /// assert!(client.set(b"k7", 0, 0, false, b"v7").await?);
3822    /// assert_eq!(client.get(b"k7").await?.unwrap().key, "k7");
3823    /// # Ok::<(), io::Error>(())
3824    /// # }).unwrap()
3825    /// ```
3826    pub async fn get(&mut self, key: impl AsRef<[u8]>) -> io::Result<Option<Item>> {
3827        let size = self.0.len();
3828        self.0[crc32(key.as_ref()) as usize % size]
3829            .get(key.as_ref())
3830            .await
3831    }
3832
3833    /// # Example
3834    ///
3835    /// ```
3836    /// use mcmc_rs::{ClientCrc32, Connection};
3837    /// # use smol::{io, block_on};
3838    /// #
3839    /// # block_on(async {
3840    /// let mut client = ClientCrc32::new(vec![
3841    ///     Connection::default().await?,
3842    ///     Connection::unix_connect("/tmp/memcached0.sock").await?,
3843    /// ]);
3844    ///
3845    /// assert!(client.set(b"k8", 0, 0, false, b"v8").await?);
3846    /// assert_eq!(client.gets(b"k8").await?.unwrap().key, "k8");
3847    /// # Ok::<(), io::Error>(())
3848    /// # }).unwrap()
3849    /// ```
3850    pub async fn gets(&mut self, key: impl AsRef<[u8]>) -> io::Result<Option<Item>> {
3851        let size = self.0.len();
3852        self.0[crc32(key.as_ref()) as usize % size]
3853            .gets(key.as_ref())
3854            .await
3855    }
3856
3857    /// # Example
3858    ///
3859    /// ```
3860    /// # use mcmc_rs::{Connection, ClientCrc32};
3861    /// # use smol::{io, block_on};
3862    /// #
3863    /// # block_on(async {
3864    /// let mut client = ClientCrc32::new(vec![
3865    ///     Connection::default().await?,
3866    ///     Connection::unix_connect("/tmp/memcached0.sock").await?,
3867    /// ]);
3868    /// assert!(client.set(b"k9", 0, 0, false, b"v9").await?);
3869    /// let result = client.gat(0, b"k9").await?;
3870    /// assert_eq!(result.unwrap().key, "k9");
3871    /// # Ok::<(), io::Error>(())
3872    /// # }).unwrap()
3873    /// ```
3874    pub async fn gat(&mut self, exptime: i64, key: impl AsRef<[u8]>) -> io::Result<Option<Item>> {
3875        let size = self.0.len();
3876        self.0[crc32(key.as_ref()) as usize % size]
3877            .gat(exptime, key.as_ref())
3878            .await
3879    }
3880
3881    /// # Example
3882    ///
3883    /// ```
3884    /// # use mcmc_rs::{Connection, ClientCrc32};
3885    /// # use smol::{io, block_on};
3886    /// #
3887    /// # block_on(async {
3888    /// let mut client = ClientCrc32::new(vec![
3889    ///     Connection::default().await?,
3890    ///     Connection::unix_connect("/tmp/memcached0.sock").await?,
3891    /// ]);
3892    /// assert!(client.set(b"k10", 0, 0, false, b"v10").await?);
3893    /// let result = client.gats(0, b"k10").await?;
3894    /// assert_eq!(result.unwrap().key, "k10");
3895    /// # Ok::<(), io::Error>(())
3896    /// # }).unwrap()
3897    /// ```
3898    pub async fn gats(&mut self, exptime: i64, key: impl AsRef<[u8]>) -> io::Result<Option<Item>> {
3899        let size = self.0.len();
3900        self.0[crc32(key.as_ref()) as usize % size]
3901            .gats(exptime, key.as_ref())
3902            .await
3903    }
3904
3905    /// # Example
3906    ///
3907    /// ```
3908    /// use mcmc_rs::{ClientCrc32, Connection};
3909    /// # use smol::{io, block_on};
3910    /// #
3911    /// # block_on(async {
3912    /// let mut client = ClientCrc32::new(vec![
3913    ///     Connection::default().await?,
3914    ///     Connection::unix_connect("/tmp/memcached0.sock").await?,
3915    /// ]);
3916    ///
3917    /// assert!(client.set(b"key", 0, -1, true, b"value").await?);
3918    /// # Ok::<(), io::Error>(())
3919    /// # }).unwrap()
3920    /// ```
3921    pub async fn set(
3922        &mut self,
3923        key: impl AsRef<[u8]>,
3924        flags: u32,
3925        exptime: i64,
3926        noreply: bool,
3927        data_block: impl AsRef<[u8]>,
3928    ) -> io::Result<bool> {
3929        let size = self.0.len();
3930        self.0[crc32(key.as_ref()) as usize % size]
3931            .set(key.as_ref(), flags, exptime, noreply, data_block.as_ref())
3932            .await
3933    }
3934
3935    /// # Example
3936    ///
3937    /// ```
3938    /// use mcmc_rs::{ClientCrc32, Connection};
3939    /// # use smol::{io, block_on};
3940    /// #
3941    /// # block_on(async {
3942    /// let mut client = ClientCrc32::new(vec![
3943    ///     Connection::default().await?,
3944    ///     Connection::unix_connect("/tmp/memcached0.sock").await?,
3945    /// ]);
3946    ///
3947    /// assert!(client.add(b"key", 0, -1, true, b"value").await?);
3948    /// # Ok::<(), io::Error>(())
3949    /// # }).unwrap()
3950    /// ```
3951    pub async fn add(
3952        &mut self,
3953        key: impl AsRef<[u8]>,
3954        flags: u32,
3955        exptime: i64,
3956        noreply: bool,
3957        data_block: impl AsRef<[u8]>,
3958    ) -> io::Result<bool> {
3959        let size = self.0.len();
3960        self.0[crc32(key.as_ref()) as usize % size]
3961            .add(key.as_ref(), flags, exptime, noreply, data_block.as_ref())
3962            .await
3963    }
3964
3965    /// # Example
3966    ///
3967    /// ```
3968    /// use mcmc_rs::{ClientCrc32, Connection};
3969    /// # use smol::{io, block_on};
3970    /// #
3971    /// # block_on(async {
3972    /// let mut client = ClientCrc32::new(vec![
3973    ///     Connection::default().await?,
3974    ///     Connection::unix_connect("/tmp/memcached0.sock").await?,
3975    /// ]);
3976    ///
3977    /// assert!(client.replace(b"key", 0, -1, true, b"value").await?);
3978    /// # Ok::<(), io::Error>(())
3979    /// # }).unwrap()
3980    /// ```
3981    pub async fn replace(
3982        &mut self,
3983        key: impl AsRef<[u8]>,
3984        flags: u32,
3985        exptime: i64,
3986        noreply: bool,
3987        data_block: impl AsRef<[u8]>,
3988    ) -> io::Result<bool> {
3989        let size = self.0.len();
3990        self.0[crc32(key.as_ref()) as usize % size]
3991            .replace(key.as_ref(), flags, exptime, noreply, data_block.as_ref())
3992            .await
3993    }
3994
3995    /// # Example
3996    ///
3997    /// ```
3998    /// use mcmc_rs::{ClientCrc32, Connection};
3999    /// # use smol::{io, block_on};
4000    /// #
4001    /// # block_on(async {
4002    /// let mut client = ClientCrc32::new(vec![
4003    ///     Connection::default().await?,
4004    ///     Connection::unix_connect("/tmp/memcached0.sock").await?,
4005    /// ]);
4006    ///
4007    /// assert!(client.append(b"key", 0, -1, true, b"value").await?);
4008    /// # Ok::<(), io::Error>(())
4009    /// # }).unwrap()
4010    /// ```
4011    pub async fn append(
4012        &mut self,
4013        key: impl AsRef<[u8]>,
4014        flags: u32,
4015        exptime: i64,
4016        noreply: bool,
4017        data_block: impl AsRef<[u8]>,
4018    ) -> io::Result<bool> {
4019        let size = self.0.len();
4020        self.0[crc32(key.as_ref()) as usize % size]
4021            .append(key.as_ref(), flags, exptime, noreply, data_block.as_ref())
4022            .await
4023    }
4024
4025    /// # Example
4026    ///
4027    /// ```
4028    /// use mcmc_rs::{ClientCrc32, Connection};
4029    /// # use smol::{io, block_on};
4030    /// #
4031    /// # block_on(async {
4032    /// let mut client = ClientCrc32::new(vec![
4033    ///     Connection::default().await?,
4034    ///     Connection::unix_connect("/tmp/memcached0.sock").await?,
4035    /// ]);
4036    ///
4037    /// assert!(client.prepend(b"key", 0, -1, true, b"value").await?);
4038    /// # Ok::<(), io::Error>(())
4039    /// # }).unwrap()
4040    /// ```
4041    pub async fn prepend(
4042        &mut self,
4043        key: impl AsRef<[u8]>,
4044        flags: u32,
4045        exptime: i64,
4046        noreply: bool,
4047        data_block: impl AsRef<[u8]>,
4048    ) -> io::Result<bool> {
4049        let size = self.0.len();
4050        self.0[crc32(key.as_ref()) as usize % size]
4051            .prepend(key.as_ref(), flags, exptime, noreply, data_block.as_ref())
4052            .await
4053    }
4054
4055    /// # Example
4056    ///
4057    /// ```
4058    /// use mcmc_rs::{ClientCrc32, Connection};
4059    /// # use smol::{io, block_on};
4060    /// #
4061    /// # block_on(async {
4062    /// let mut client = ClientCrc32::new(vec![
4063    ///     Connection::default().await?,
4064    ///     Connection::unix_connect("/tmp/memcached0.sock").await?,
4065    /// ]);
4066    ///
4067    /// assert!(client.cas(b"key", 0, -1, 0, true, b"value").await?);
4068    /// # Ok::<(), io::Error>(())
4069    /// # }).unwrap()
4070    /// ```
4071    pub async fn cas(
4072        &mut self,
4073        key: impl AsRef<[u8]>,
4074        flags: u32,
4075        exptime: i64,
4076        cas_unique: u64,
4077        noreply: bool,
4078        data_block: impl AsRef<[u8]>,
4079    ) -> io::Result<bool> {
4080        let size = self.0.len();
4081        self.0[crc32(key.as_ref()) as usize % size]
4082            .cas(
4083                key.as_ref(),
4084                flags,
4085                exptime,
4086                cas_unique,
4087                noreply,
4088                data_block.as_ref(),
4089            )
4090            .await
4091    }
4092
4093    /// # Example
4094    ///
4095    /// ```
4096    /// use mcmc_rs::{ClientCrc32, Connection};
4097    /// # use smol::{io, block_on};
4098    /// #
4099    /// # block_on(async {
4100    /// let mut client = ClientCrc32::new(vec![
4101    ///     Connection::default().await?,
4102    ///     Connection::unix_connect("/tmp/memcached0.sock").await?,
4103    /// ]);
4104    ///
4105    /// assert!(client.delete(b"key", true).await?);
4106    /// # Ok::<(), io::Error>(())
4107    /// # }).unwrap()
4108    /// ```
4109    pub async fn delete(&mut self, key: impl AsRef<[u8]>, noreply: bool) -> io::Result<bool> {
4110        let size = self.0.len();
4111        self.0[crc32(key.as_ref()) as usize % size]
4112            .delete(key.as_ref(), noreply)
4113            .await
4114    }
4115
4116    /// # Example
4117    ///
4118    /// ```
4119    /// use mcmc_rs::{ClientCrc32, Connection};
4120    /// # use smol::{io, block_on};
4121    /// #
4122    /// # block_on(async {
4123    /// let mut client = ClientCrc32::new(vec![
4124    ///     Connection::default().await?,
4125    ///     Connection::unix_connect("/tmp/memcached0.sock").await?,
4126    /// ]);
4127    ///
4128    /// assert!(client.incr(b"key", 1, true).await?.is_none());
4129    /// # Ok::<(), io::Error>(())
4130    /// # }).unwrap()
4131    /// ```
4132    pub async fn incr(
4133        &mut self,
4134        key: impl AsRef<[u8]>,
4135        value: u64,
4136        noreply: bool,
4137    ) -> io::Result<Option<u64>> {
4138        let size = self.0.len();
4139        self.0[crc32(key.as_ref()) as usize % size]
4140            .incr(key.as_ref(), value, noreply)
4141            .await
4142    }
4143
4144    /// # Example
4145    ///
4146    /// ```
4147    /// use mcmc_rs::{ClientCrc32, Connection};
4148    /// # use smol::{io, block_on};
4149    /// #
4150    /// # block_on(async {
4151    /// let mut client = ClientCrc32::new(vec![
4152    ///     Connection::default().await?,
4153    ///     Connection::unix_connect("/tmp/memcached0.sock").await?,
4154    /// ]);
4155    ///
4156    /// assert!(client.decr(b"key", 1, true).await?.is_none());
4157    /// # Ok::<(), io::Error>(())
4158    /// # }).unwrap()
4159    /// ```
4160    pub async fn decr(
4161        &mut self,
4162        key: impl AsRef<[u8]>,
4163        value: u64,
4164        noreply: bool,
4165    ) -> io::Result<Option<u64>> {
4166        let size = self.0.len();
4167        self.0[crc32(key.as_ref()) as usize % size]
4168            .decr(key.as_ref(), value, noreply)
4169            .await
4170    }
4171
4172    /// # Example
4173    ///
4174    /// ```
4175    /// use mcmc_rs::{ClientCrc32, Connection};
4176    /// # use smol::{io, block_on};
4177    /// #
4178    /// # block_on(async {
4179    /// let mut client = ClientCrc32::new(vec![
4180    ///     Connection::default().await?,
4181    ///     Connection::unix_connect("/tmp/memcached0.sock").await?,
4182    /// ]);
4183    ///
4184    /// assert!(client.touch(b"key", -1, true).await?);
4185    /// # Ok::<(), io::Error>(())
4186    /// # }).unwrap()
4187    /// ```
4188    pub async fn touch(
4189        &mut self,
4190        key: impl AsRef<[u8]>,
4191        exptime: i64,
4192        noreply: bool,
4193    ) -> io::Result<bool> {
4194        let size = self.0.len();
4195        self.0[crc32(key.as_ref()) as usize % size]
4196            .touch(key.as_ref(), exptime, noreply)
4197            .await
4198    }
4199
4200    /// # Example
4201    ///
4202    /// ```
4203    /// use mcmc_rs::{ClientCrc32, Connection};
4204    /// # use smol::{io, block_on};
4205    /// #
4206    /// # block_on(async {
4207    /// let mut client = ClientCrc32::new(vec![
4208    ///     Connection::default().await?,
4209    ///     Connection::unix_connect("/tmp/memcached0.sock").await?,
4210    /// ]);
4211    /// assert!(client.set(b"k11", 0, 0, false, b"v11").await?);
4212    /// assert!(client.me(b"k11").await?.is_some());
4213    /// # Ok::<(), io::Error>(())
4214    /// # }).unwrap()
4215    /// ```
4216    pub async fn me(&mut self, key: impl AsRef<[u8]>) -> io::Result<Option<String>> {
4217        let size = self.0.len();
4218        self.0[crc32(key.as_ref()) as usize % size]
4219            .me(key.as_ref())
4220            .await
4221    }
4222
4223    /// # Example
4224    ///
4225    /// ```
4226    /// use mcmc_rs::{ClientCrc32, Connection, MgFlag, MgItem};
4227    /// # use smol::{io, block_on};
4228    /// #
4229    /// # block_on(async {
4230    /// let mut client = ClientCrc32::new(vec![
4231    ///     Connection::default().await?,
4232    ///     Connection::unix_connect("/tmp/memcached0.sock").await?,
4233    /// ]);
4234    /// let result = client
4235    ///     .mg(
4236    ///         b"44OG44K544OI",
4237    ///         &[
4238    ///             MgFlag::Base64Key,
4239    ///             MgFlag::ReturnCas,
4240    ///             MgFlag::ReturnFlags,
4241    ///             MgFlag::ReturnHit,
4242    ///             MgFlag::ReturnKey,
4243    ///             MgFlag::ReturnLastAccess,
4244    ///             MgFlag::Opaque("opaque".to_string()),
4245    ///             MgFlag::ReturnSize,
4246    ///             MgFlag::ReturnTtl,
4247    ///             MgFlag::UnBump,
4248    ///             MgFlag::ReturnValue,
4249    ///             MgFlag::NewCas(0),
4250    ///             MgFlag::Autovivify(-1),
4251    ///             MgFlag::RecacheTtl(-1),
4252    ///             MgFlag::UpdateTtl(-1),
4253    ///         ],
4254    ///     )
4255    ///     .await?;
4256    /// assert_eq!(
4257    ///     result,
4258    ///     MgItem {
4259    ///         success: true,
4260    ///         base64_key: false,
4261    ///         cas: Some(0),
4262    ///         flags: Some(0),
4263    ///         hit: Some(0),
4264    ///         key: Some("テスト".to_string()),
4265    ///         last_access_ttl: Some(0),
4266    ///         opaque: Some("opaque".to_string()),
4267    ///         size: Some(0),
4268    ///         ttl: Some(-1),
4269    ///         data_block: Some(vec![]),
4270    ///         already_win: false,
4271    ///         won_recache: true,
4272    ///         stale: false,
4273    ///     }
4274    /// );
4275    /// # Ok::<(), io::Error>(())
4276    /// # }).unwrap()
4277    /// ```
4278    pub async fn mg(&mut self, key: impl AsRef<[u8]>, flags: &[MgFlag]) -> io::Result<MgItem> {
4279        let size = self.0.len();
4280        self.0[crc32(key.as_ref()) as usize % size]
4281            .mg(key.as_ref(), flags)
4282            .await
4283    }
4284
4285    /// # Example
4286    ///
4287    /// ```
4288    /// use mcmc_rs::{ClientCrc32, Connection, MsFlag, MsItem, MsMode};
4289    /// # use smol::{io, block_on};
4290    /// #
4291    /// # block_on(async {
4292    /// let mut client = ClientCrc32::new(vec![
4293    ///     Connection::default().await?,
4294    ///     Connection::unix_connect("/tmp/memcached0.sock").await?,
4295    /// ]);
4296    /// let result = client
4297    ///     .ms(
4298    ///         b"44OG44K544OI",
4299    ///         &[
4300    ///             MsFlag::Base64Key,
4301    ///             MsFlag::ReturnCas,
4302    ///             MsFlag::CompareCas(0),
4303    ///             MsFlag::NewCas(0),
4304    ///             MsFlag::SetFlags(0),
4305    ///             MsFlag::Invalidate,
4306    ///             MsFlag::ReturnKey,
4307    ///             MsFlag::Opaque("opaque".to_string()),
4308    ///             MsFlag::ReturnSize,
4309    ///             MsFlag::Ttl(-1),
4310    ///             MsFlag::Mode(MsMode::Set),
4311    ///             MsFlag::Autovivify(0),
4312    ///         ],
4313    ///         b"hi",
4314    ///     )
4315    ///     .await?;
4316    /// assert_eq!(
4317    ///     result,
4318    ///     MsItem {
4319    ///         success: false,
4320    ///         cas: Some(0),
4321    ///         key: Some("44OG44K544OI".to_string()),
4322    ///         opaque: Some("opaque".to_string()),
4323    ///         size: Some(2),
4324    ///         base64_key: true
4325    ///     }
4326    /// );
4327    /// # Ok::<(), io::Error>(())
4328    /// # }).unwrap()
4329    /// ```
4330    pub async fn ms(
4331        &mut self,
4332        key: impl AsRef<[u8]>,
4333        flags: &[MsFlag],
4334        data_block: impl AsRef<[u8]>,
4335    ) -> io::Result<MsItem> {
4336        let size = self.0.len();
4337        self.0[crc32(key.as_ref()) as usize % size]
4338            .ms(key.as_ref(), flags, data_block.as_ref())
4339            .await
4340    }
4341
4342    /// # Example
4343    ///
4344    /// ```
4345    /// use mcmc_rs::{ClientCrc32, Connection, MdFlag, MdItem};
4346    /// # use smol::{io, block_on};
4347    /// #
4348    /// # block_on(async {
4349    /// let mut client = ClientCrc32::new(vec![
4350    ///     Connection::default().await?,
4351    ///     Connection::unix_connect("/tmp/memcached0.sock").await?,
4352    /// ]);
4353    /// let result = client
4354    ///     .md(
4355    ///         b"44OG44K544OI",
4356    ///         &[
4357    ///             MdFlag::Base64Key,
4358    ///             MdFlag::CompareCas(0),
4359    ///             MdFlag::NewCas(0),
4360    ///             MdFlag::Invalidate,
4361    ///             MdFlag::ReturnKey,
4362    ///             MdFlag::Opaque("opaque".to_string()),
4363    ///             MdFlag::UpdateTtl(-1),
4364    ///             MdFlag::LeaveKey,
4365    ///         ],
4366    ///     )
4367    ///     .await?;
4368    /// assert_eq!(
4369    ///     result,
4370    ///     MdItem {
4371    ///         success: false,
4372    ///         key: Some("44OG44K544OI".to_string()),
4373    ///         opaque: Some("opaque".to_string()),
4374    ///         base64_key: true
4375    ///     }
4376    /// );
4377    /// # Ok::<(), io::Error>(())
4378    /// # }).unwrap()
4379    /// ```
4380    pub async fn md(&mut self, key: impl AsRef<[u8]>, flags: &[MdFlag]) -> io::Result<MdItem> {
4381        let size = self.0.len();
4382        self.0[crc32(key.as_ref()) as usize % size]
4383            .md(key.as_ref(), flags)
4384            .await
4385    }
4386
4387    /// # Example
4388    ///
4389    /// ```
4390    /// use mcmc_rs::{ClientCrc32, Connection, MaFlag, MaItem, MaMode};
4391    /// # use smol::{io, block_on};
4392    /// #
4393    /// # block_on(async {
4394    /// let mut client = ClientCrc32::new(vec![
4395    ///     Connection::default().await?,
4396    ///     Connection::unix_connect("/tmp/memcached0.sock").await?,
4397    /// ]);
4398    /// let result = client
4399    ///     .ma(
4400    ///         b"aGk=",
4401    ///         &[
4402    ///             MaFlag::Base64Key,
4403    ///             MaFlag::CompareCas(0),
4404    ///             MaFlag::NewCas(0),
4405    ///             MaFlag::AutoCreate(0),
4406    ///             MaFlag::InitValue(0),
4407    ///             MaFlag::DeltaApply(0),
4408    ///             MaFlag::UpdateTtl(0),
4409    ///             MaFlag::Mode(MaMode::Incr),
4410    ///             MaFlag::Opaque("opaque".to_string()),
4411    ///             MaFlag::ReturnTtl,
4412    ///             MaFlag::ReturnCas,
4413    ///             MaFlag::ReturnValue,
4414    ///             MaFlag::ReturnKey,
4415    ///         ],
4416    ///     )
4417    ///     .await?;
4418    /// assert_eq!(
4419    ///     result,
4420    ///     MaItem {
4421    ///         success: true,
4422    ///         opaque: Some("opaque".to_string()),
4423    ///         ttl: Some(-1),
4424    ///         cas: Some(0),
4425    ///         number: Some(0),
4426    ///         key: Some("aGk=".to_string()),
4427    ///         base64_key: true
4428    ///     }
4429    /// );
4430    /// # Ok::<(), io::Error>(())
4431    /// # }).unwrap()
4432    /// ```
4433    pub async fn ma(&mut self, key: impl AsRef<[u8]>, flags: &[MaFlag]) -> io::Result<MaItem> {
4434        let size = self.0.len();
4435        self.0[crc32(key.as_ref()) as usize % size]
4436            .ma(key.as_ref(), flags)
4437            .await
4438    }
4439}
4440
4441pub struct ClientHashRing(Vec<Connection>, HashRing<usize>);
4442impl ClientHashRing {
4443    /// # Example
4444    ///
4445    /// ```
4446    /// use mcmc_rs::{ClientHashRing, Connection};
4447    /// # use smol::{io, block_on};
4448    /// #
4449    /// # block_on(async {
4450    /// let mut client = ClientHashRing::new(vec![
4451    ///     Connection::default().await?,
4452    ///     Connection::unix_connect("/tmp/memcached0.sock").await?,
4453    /// ]);
4454    /// # Ok::<(), io::Error>(())
4455    /// # }).unwrap()
4456    pub fn new(conns: Vec<Connection>) -> Self {
4457        let mut ring = HashRing::new();
4458        ring.batch_add((0..conns.len()).collect());
4459        Self(conns, ring)
4460    }
4461
4462    /// # Example
4463    ///
4464    /// ```
4465    /// use mcmc_rs::{ClientHashRing, Connection};
4466    /// # use smol::{io, block_on};
4467    /// #
4468    /// # block_on(async {
4469    /// let mut client = ClientHashRing::new(vec![
4470    ///     Connection::default().await?,
4471    ///     Connection::unix_connect("/tmp/memcached0.sock").await?,
4472    /// ]);
4473    ///
4474    /// assert!(client.set(b"k7", 0, 0, false, b"v7").await?);
4475    /// assert_eq!(client.get(b"k7").await?.unwrap().key, "k7");
4476    /// # Ok::<(), io::Error>(())
4477    /// # }).unwrap()
4478    /// ```
4479    pub async fn get(&mut self, key: impl AsRef<[u8]>) -> io::Result<Option<Item>> {
4480        let i = *self.1.get(&key.as_ref()).unwrap();
4481        self.0[i].get(key.as_ref()).await
4482    }
4483
4484    /// # Example
4485    ///
4486    /// ```
4487    /// use mcmc_rs::{ClientHashRing, Connection};
4488    /// # use smol::{io, block_on};
4489    /// #
4490    /// # block_on(async {
4491    /// let mut client = ClientHashRing::new(vec![
4492    ///     Connection::default().await?,
4493    ///     Connection::unix_connect("/tmp/memcached0.sock").await?,
4494    /// ]);
4495    ///
4496    /// assert!(client.set(b"k8", 0, 0, false, b"v8").await?);
4497    /// assert_eq!(client.gets(b"k8").await?.unwrap().key, "k8");
4498    /// # Ok::<(), io::Error>(())
4499    /// # }).unwrap()
4500    /// ```
4501    pub async fn gets(&mut self, key: impl AsRef<[u8]>) -> io::Result<Option<Item>> {
4502        let i = *self.1.get(&key.as_ref()).unwrap();
4503        self.0[i].gets(key.as_ref()).await
4504    }
4505
4506    /// # Example
4507    ///
4508    /// ```
4509    /// # use mcmc_rs::{Connection, ClientHashRing};
4510    /// # use smol::{io, block_on};
4511    /// #
4512    /// # block_on(async {
4513    /// let mut client = ClientHashRing::new(vec![
4514    ///     Connection::default().await?,
4515    ///     Connection::unix_connect("/tmp/memcached0.sock").await?,
4516    /// ]);
4517    /// assert!(client.set(b"k9", 0, 0, false, b"v9").await?);
4518    /// let result = client.gat(0, b"k9").await?;
4519    /// assert_eq!(result.unwrap().key, "k9");
4520    /// # Ok::<(), io::Error>(())
4521    /// # }).unwrap()
4522    /// ```
4523    pub async fn gat(&mut self, exptime: i64, key: impl AsRef<[u8]>) -> io::Result<Option<Item>> {
4524        let i = *self.1.get(&key.as_ref()).unwrap();
4525        self.0[i].gat(exptime, key.as_ref()).await
4526    }
4527
4528    /// # Example
4529    ///
4530    /// ```
4531    /// # use mcmc_rs::{Connection, ClientHashRing};
4532    /// # use smol::{io, block_on};
4533    /// #
4534    /// # block_on(async {
4535    /// let mut client = ClientHashRing::new(vec![
4536    ///     Connection::default().await?,
4537    ///     Connection::unix_connect("/tmp/memcached0.sock").await?,
4538    /// ]);
4539    /// assert!(client.set(b"k10", 0, 0, false, b"v10").await?);
4540    /// let result = client.gats(0, b"k10").await?;
4541    /// assert_eq!(result.unwrap().key, "k10");
4542    /// # Ok::<(), io::Error>(())
4543    /// # }).unwrap()
4544    /// ```
4545    pub async fn gats(&mut self, exptime: i64, key: impl AsRef<[u8]>) -> io::Result<Option<Item>> {
4546        let i = *self.1.get(&key.as_ref()).unwrap();
4547        self.0[i].gats(exptime, key.as_ref()).await
4548    }
4549
4550    /// # Example
4551    ///
4552    /// ```
4553    /// use mcmc_rs::{ClientHashRing, Connection};
4554    /// # use smol::{io, block_on};
4555    /// #
4556    /// # block_on(async {
4557    /// let mut client = ClientHashRing::new(vec![
4558    ///     Connection::default().await?,
4559    ///     Connection::unix_connect("/tmp/memcached0.sock").await?,
4560    /// ]);
4561    ///
4562    /// assert!(client.set(b"key", 0, -1, true, b"value").await?);
4563    /// # Ok::<(), io::Error>(())
4564    /// # }).unwrap()
4565    /// ```
4566    pub async fn set(
4567        &mut self,
4568        key: impl AsRef<[u8]>,
4569        flags: u32,
4570        exptime: i64,
4571        noreply: bool,
4572        data_block: impl AsRef<[u8]>,
4573    ) -> io::Result<bool> {
4574        let i = *self.1.get(&key.as_ref()).unwrap();
4575        self.0[i]
4576            .set(key.as_ref(), flags, exptime, noreply, data_block.as_ref())
4577            .await
4578    }
4579
4580    /// # Example
4581    ///
4582    /// ```
4583    /// use mcmc_rs::{ClientHashRing, Connection};
4584    /// # use smol::{io, block_on};
4585    /// #
4586    /// # block_on(async {
4587    /// let mut client = ClientHashRing::new(vec![
4588    ///     Connection::default().await?,
4589    ///     Connection::unix_connect("/tmp/memcached0.sock").await?,
4590    /// ]);
4591    ///
4592    /// assert!(client.add(b"key", 0, -1, true, b"value").await?);
4593    /// # Ok::<(), io::Error>(())
4594    /// # }).unwrap()
4595    /// ```
4596    pub async fn add(
4597        &mut self,
4598        key: impl AsRef<[u8]>,
4599        flags: u32,
4600        exptime: i64,
4601        noreply: bool,
4602        data_block: impl AsRef<[u8]>,
4603    ) -> io::Result<bool> {
4604        let i = *self.1.get(&key.as_ref()).unwrap();
4605        self.0[i]
4606            .add(key.as_ref(), flags, exptime, noreply, data_block.as_ref())
4607            .await
4608    }
4609
4610    /// # Example
4611    ///
4612    /// ```
4613    /// use mcmc_rs::{ClientHashRing, Connection};
4614    /// # use smol::{io, block_on};
4615    /// #
4616    /// # block_on(async {
4617    /// let mut client = ClientHashRing::new(vec![
4618    ///     Connection::default().await?,
4619    ///     Connection::unix_connect("/tmp/memcached0.sock").await?,
4620    /// ]);
4621    ///
4622    /// assert!(client.replace(b"key", 0, -1, true, b"value").await?);
4623    /// # Ok::<(), io::Error>(())
4624    /// # }).unwrap()
4625    /// ```
4626    pub async fn replace(
4627        &mut self,
4628        key: impl AsRef<[u8]>,
4629        flags: u32,
4630        exptime: i64,
4631        noreply: bool,
4632        data_block: impl AsRef<[u8]>,
4633    ) -> io::Result<bool> {
4634        let i = *self.1.get(&key.as_ref()).unwrap();
4635        self.0[i]
4636            .replace(key.as_ref(), flags, exptime, noreply, data_block.as_ref())
4637            .await
4638    }
4639
4640    /// # Example
4641    ///
4642    /// ```
4643    /// use mcmc_rs::{ClientHashRing, Connection};
4644    /// # use smol::{io, block_on};
4645    /// #
4646    /// # block_on(async {
4647    /// let mut client = ClientHashRing::new(vec![
4648    ///     Connection::default().await?,
4649    ///     Connection::unix_connect("/tmp/memcached0.sock").await?,
4650    /// ]);
4651    ///
4652    /// assert!(client.append(b"key", 0, -1, true, b"value").await?);
4653    /// # Ok::<(), io::Error>(())
4654    /// # }).unwrap()
4655    /// ```
4656    pub async fn append(
4657        &mut self,
4658        key: impl AsRef<[u8]>,
4659        flags: u32,
4660        exptime: i64,
4661        noreply: bool,
4662        data_block: impl AsRef<[u8]>,
4663    ) -> io::Result<bool> {
4664        let i = *self.1.get(&key.as_ref()).unwrap();
4665        self.0[i]
4666            .append(key.as_ref(), flags, exptime, noreply, data_block.as_ref())
4667            .await
4668    }
4669
4670    /// # Example
4671    ///
4672    /// ```
4673    /// use mcmc_rs::{ClientHashRing, Connection};
4674    /// # use smol::{io, block_on};
4675    /// #
4676    /// # block_on(async {
4677    /// let mut client = ClientHashRing::new(vec![
4678    ///     Connection::default().await?,
4679    ///     Connection::unix_connect("/tmp/memcached0.sock").await?,
4680    /// ]);
4681    ///
4682    /// assert!(client.prepend(b"key", 0, -1, true, b"value").await?);
4683    /// # Ok::<(), io::Error>(())
4684    /// # }).unwrap()
4685    /// ```
4686    pub async fn prepend(
4687        &mut self,
4688        key: impl AsRef<[u8]>,
4689        flags: u32,
4690        exptime: i64,
4691        noreply: bool,
4692        data_block: impl AsRef<[u8]>,
4693    ) -> io::Result<bool> {
4694        let i = *self.1.get(&key.as_ref()).unwrap();
4695        self.0[i]
4696            .prepend(key.as_ref(), flags, exptime, noreply, data_block.as_ref())
4697            .await
4698    }
4699
4700    /// # Example
4701    ///
4702    /// ```
4703    /// use mcmc_rs::{ClientHashRing, Connection};
4704    /// # use smol::{io, block_on};
4705    /// #
4706    /// # block_on(async {
4707    /// let mut client = ClientHashRing::new(vec![
4708    ///     Connection::default().await?,
4709    ///     Connection::unix_connect("/tmp/memcached0.sock").await?,
4710    /// ]);
4711    ///
4712    /// assert!(client.cas(b"key", 0, -1, 0, true, b"value").await?);
4713    /// # Ok::<(), io::Error>(())
4714    /// # }).unwrap()
4715    /// ```
4716    pub async fn cas(
4717        &mut self,
4718        key: impl AsRef<[u8]>,
4719        flags: u32,
4720        exptime: i64,
4721        cas_unique: u64,
4722        noreply: bool,
4723        data_block: impl AsRef<[u8]>,
4724    ) -> io::Result<bool> {
4725        let i = *self.1.get(&key.as_ref()).unwrap();
4726        self.0[i]
4727            .cas(
4728                key.as_ref(),
4729                flags,
4730                exptime,
4731                cas_unique,
4732                noreply,
4733                data_block.as_ref(),
4734            )
4735            .await
4736    }
4737
4738    /// # Example
4739    ///
4740    /// ```
4741    /// use mcmc_rs::{ClientHashRing, Connection};
4742    /// # use smol::{io, block_on};
4743    /// #
4744    /// # block_on(async {
4745    /// let mut client = ClientHashRing::new(vec![
4746    ///     Connection::default().await?,
4747    ///     Connection::unix_connect("/tmp/memcached0.sock").await?,
4748    /// ]);
4749    ///
4750    /// assert!(client.delete(b"key", true).await?);
4751    /// # Ok::<(), io::Error>(())
4752    /// # }).unwrap()
4753    /// ```
4754    pub async fn delete(&mut self, key: impl AsRef<[u8]>, noreply: bool) -> io::Result<bool> {
4755        let i = *self.1.get(&key.as_ref()).unwrap();
4756        self.0[i].delete(key.as_ref(), noreply).await
4757    }
4758
4759    /// # Example
4760    ///
4761    /// ```
4762    /// use mcmc_rs::{ClientHashRing, Connection};
4763    /// # use smol::{io, block_on};
4764    /// #
4765    /// # block_on(async {
4766    /// let mut client = ClientHashRing::new(vec![
4767    ///     Connection::default().await?,
4768    ///     Connection::unix_connect("/tmp/memcached0.sock").await?,
4769    /// ]);
4770    ///
4771    /// assert!(client.incr(b"key", 1, true).await?.is_none());
4772    /// # Ok::<(), io::Error>(())
4773    /// # }).unwrap()
4774    /// ```
4775    pub async fn incr(
4776        &mut self,
4777        key: impl AsRef<[u8]>,
4778        value: u64,
4779        noreply: bool,
4780    ) -> io::Result<Option<u64>> {
4781        let i = *self.1.get(&key.as_ref()).unwrap();
4782        self.0[i].incr(key.as_ref(), value, noreply).await
4783    }
4784
4785    /// # Example
4786    ///
4787    /// ```
4788    /// use mcmc_rs::{ClientHashRing, Connection};
4789    /// # use smol::{io, block_on};
4790    /// #
4791    /// # block_on(async {
4792    /// let mut client = ClientHashRing::new(vec![
4793    ///     Connection::default().await?,
4794    ///     Connection::unix_connect("/tmp/memcached0.sock").await?,
4795    /// ]);
4796    ///
4797    /// assert!(client.decr(b"key", 1, true).await?.is_none());
4798    /// # Ok::<(), io::Error>(())
4799    /// # }).unwrap()
4800    /// ```
4801    pub async fn decr(
4802        &mut self,
4803        key: impl AsRef<[u8]>,
4804        value: u64,
4805        noreply: bool,
4806    ) -> io::Result<Option<u64>> {
4807        let i = *self.1.get(&key.as_ref()).unwrap();
4808        self.0[i].decr(key.as_ref(), value, noreply).await
4809    }
4810
4811    /// # Example
4812    ///
4813    /// ```
4814    /// use mcmc_rs::{ClientHashRing, Connection};
4815    /// # use smol::{io, block_on};
4816    /// #
4817    /// # block_on(async {
4818    /// let mut client = ClientHashRing::new(vec![
4819    ///     Connection::default().await?,
4820    ///     Connection::unix_connect("/tmp/memcached0.sock").await?,
4821    /// ]);
4822    ///
4823    /// assert!(client.touch(b"key", -1, true).await?);
4824    /// # Ok::<(), io::Error>(())
4825    /// # }).unwrap()
4826    /// ```
4827    pub async fn touch(
4828        &mut self,
4829        key: impl AsRef<[u8]>,
4830        exptime: i64,
4831        noreply: bool,
4832    ) -> io::Result<bool> {
4833        let i = *self.1.get(&key.as_ref()).unwrap();
4834        self.0[i].touch(key.as_ref(), exptime, noreply).await
4835    }
4836
4837    /// # Example
4838    ///
4839    /// ```
4840    /// use mcmc_rs::{ClientHashRing, Connection};
4841    /// # use smol::{io, block_on};
4842    /// #
4843    /// # block_on(async {
4844    /// let mut client = ClientHashRing::new(vec![
4845    ///     Connection::default().await?,
4846    ///     Connection::unix_connect("/tmp/memcached0.sock").await?,
4847    /// ]);
4848    /// assert!(client.set(b"k11", 0, 0, false, b"v11").await?);
4849    /// assert!(client.me(b"k11").await?.is_some());
4850    /// # Ok::<(), io::Error>(())
4851    /// # }).unwrap()
4852    /// ```
4853    pub async fn me(&mut self, key: impl AsRef<[u8]>) -> io::Result<Option<String>> {
4854        let i = *self.1.get(&key.as_ref()).unwrap();
4855        self.0[i].me(key.as_ref()).await
4856    }
4857
4858    /// # Example
4859    ///
4860    /// ```
4861    /// use mcmc_rs::{ClientHashRing, Connection, MgFlag, MgItem};
4862    /// # use smol::{io, block_on};
4863    /// #
4864    /// # block_on(async {
4865    /// let mut client = ClientHashRing::new(vec![
4866    ///     Connection::default().await?,
4867    ///     Connection::unix_connect("/tmp/memcached0.sock").await?,
4868    /// ]);
4869    /// let result = client
4870    ///     .mg(
4871    ///         b"44OG44K544OI",
4872    ///         &[
4873    ///             MgFlag::Base64Key,
4874    ///             MgFlag::ReturnCas,
4875    ///             MgFlag::ReturnFlags,
4876    ///             MgFlag::ReturnHit,
4877    ///             MgFlag::ReturnKey,
4878    ///             MgFlag::ReturnLastAccess,
4879    ///             MgFlag::Opaque("opaque".to_string()),
4880    ///             MgFlag::ReturnSize,
4881    ///             MgFlag::ReturnTtl,
4882    ///             MgFlag::UnBump,
4883    ///             MgFlag::ReturnValue,
4884    ///             MgFlag::NewCas(0),
4885    ///             MgFlag::Autovivify(-1),
4886    ///             MgFlag::RecacheTtl(-1),
4887    ///             MgFlag::UpdateTtl(-1),
4888    ///         ],
4889    ///     )
4890    ///     .await?;
4891    /// assert_eq!(
4892    ///     result,
4893    ///     MgItem {
4894    ///         success: true,
4895    ///         base64_key: false,
4896    ///         cas: Some(0),
4897    ///         flags: Some(0),
4898    ///         hit: Some(0),
4899    ///         key: Some("テスト".to_string()),
4900    ///         last_access_ttl: Some(0),
4901    ///         opaque: Some("opaque".to_string()),
4902    ///         size: Some(0),
4903    ///         ttl: Some(-1),
4904    ///         data_block: Some(vec![]),
4905    ///         already_win: false,
4906    ///         won_recache: true,
4907    ///         stale: false,
4908    ///     }
4909    /// );
4910    /// # Ok::<(), io::Error>(())
4911    /// # }).unwrap()
4912    /// ```
4913    pub async fn mg(&mut self, key: impl AsRef<[u8]>, flags: &[MgFlag]) -> io::Result<MgItem> {
4914        let i = *self.1.get(&key.as_ref()).unwrap();
4915        self.0[i].mg(key.as_ref(), flags).await
4916    }
4917
4918    /// # Example
4919    ///
4920    /// ```
4921    /// use mcmc_rs::{ClientHashRing, Connection, MsFlag, MsItem, MsMode};
4922    /// # use smol::{io, block_on};
4923    /// #
4924    /// # block_on(async {
4925    /// let mut client = ClientHashRing::new(vec![
4926    ///     Connection::default().await?,
4927    ///     Connection::unix_connect("/tmp/memcached0.sock").await?,
4928    /// ]);
4929    /// let result = client
4930    ///     .ms(
4931    ///         b"44OG44K544OI",
4932    ///         &[
4933    ///             MsFlag::Base64Key,
4934    ///             MsFlag::ReturnCas,
4935    ///             MsFlag::CompareCas(0),
4936    ///             MsFlag::NewCas(0),
4937    ///             MsFlag::SetFlags(0),
4938    ///             MsFlag::Invalidate,
4939    ///             MsFlag::ReturnKey,
4940    ///             MsFlag::Opaque("opaque".to_string()),
4941    ///             MsFlag::ReturnSize,
4942    ///             MsFlag::Ttl(-1),
4943    ///             MsFlag::Mode(MsMode::Set),
4944    ///             MsFlag::Autovivify(0),
4945    ///         ],
4946    ///         b"hi",
4947    ///     )
4948    ///     .await?;
4949    /// assert_eq!(
4950    ///     result,
4951    ///     MsItem {
4952    ///         success: false,
4953    ///         cas: Some(0),
4954    ///         key: Some("44OG44K544OI".to_string()),
4955    ///         opaque: Some("opaque".to_string()),
4956    ///         size: Some(2),
4957    ///         base64_key: true
4958    ///     }
4959    /// );
4960    /// # Ok::<(), io::Error>(())
4961    /// # }).unwrap()
4962    /// ```
4963    pub async fn ms(
4964        &mut self,
4965        key: impl AsRef<[u8]>,
4966        flags: &[MsFlag],
4967        data_block: impl AsRef<[u8]>,
4968    ) -> io::Result<MsItem> {
4969        let i = *self.1.get(&key.as_ref()).unwrap();
4970        self.0[i].ms(key.as_ref(), flags, data_block.as_ref()).await
4971    }
4972
4973    /// # Example
4974    ///
4975    /// ```
4976    /// use mcmc_rs::{ClientHashRing, Connection, MdFlag, MdItem};
4977    /// # use smol::{io, block_on};
4978    /// #
4979    /// # block_on(async {
4980    /// let mut client = ClientHashRing::new(vec![
4981    ///     Connection::default().await?,
4982    ///     Connection::unix_connect("/tmp/memcached0.sock").await?,
4983    /// ]);
4984    /// let result = client
4985    ///     .md(
4986    ///         b"44OG44K544OI",
4987    ///         &[
4988    ///             MdFlag::Base64Key,
4989    ///             MdFlag::CompareCas(0),
4990    ///             MdFlag::NewCas(0),
4991    ///             MdFlag::Invalidate,
4992    ///             MdFlag::ReturnKey,
4993    ///             MdFlag::Opaque("opaque".to_string()),
4994    ///             MdFlag::UpdateTtl(-1),
4995    ///             MdFlag::LeaveKey,
4996    ///         ],
4997    ///     )
4998    ///     .await?;
4999    /// assert_eq!(
5000    ///     result,
5001    ///     MdItem {
5002    ///         success: false,
5003    ///         key: Some("44OG44K544OI".to_string()),
5004    ///         opaque: Some("opaque".to_string()),
5005    ///         base64_key: true
5006    ///     }
5007    /// );
5008    /// # Ok::<(), io::Error>(())
5009    /// # }).unwrap()
5010    /// ```
5011    pub async fn md(&mut self, key: impl AsRef<[u8]>, flags: &[MdFlag]) -> io::Result<MdItem> {
5012        let i = *self.1.get(&key.as_ref()).unwrap();
5013        self.0[i].md(key.as_ref(), flags).await
5014    }
5015
5016    /// # Example
5017    ///
5018    /// ```
5019    /// use mcmc_rs::{ClientHashRing, Connection, MaFlag, MaItem, MaMode};
5020    /// # use smol::{io, block_on};
5021    /// #
5022    /// # block_on(async {
5023    /// let mut client = ClientHashRing::new(vec![
5024    ///     Connection::default().await?,
5025    ///     Connection::unix_connect("/tmp/memcached0.sock").await?,
5026    /// ]);
5027    /// let result = client
5028    ///     .ma(
5029    ///         b"aGk=",
5030    ///         &[
5031    ///             MaFlag::Base64Key,
5032    ///             MaFlag::CompareCas(0),
5033    ///             MaFlag::NewCas(0),
5034    ///             MaFlag::AutoCreate(0),
5035    ///             MaFlag::InitValue(0),
5036    ///             MaFlag::DeltaApply(0),
5037    ///             MaFlag::UpdateTtl(0),
5038    ///             MaFlag::Mode(MaMode::Incr),
5039    ///             MaFlag::Opaque("opaque".to_string()),
5040    ///             MaFlag::ReturnTtl,
5041    ///             MaFlag::ReturnCas,
5042    ///             MaFlag::ReturnValue,
5043    ///             MaFlag::ReturnKey,
5044    ///         ],
5045    ///     )
5046    ///     .await?;
5047    /// assert_eq!(
5048    ///     result,
5049    ///     MaItem {
5050    ///         success: true,
5051    ///         opaque: Some("opaque".to_string()),
5052    ///         ttl: Some(-1),
5053    ///         cas: Some(0),
5054    ///         number: Some(0),
5055    ///         key: Some("aGk=".to_string()),
5056    ///         base64_key: true
5057    ///     }
5058    /// );
5059    /// # Ok::<(), io::Error>(())
5060    /// # }).unwrap()
5061    /// ```
5062    pub async fn ma(&mut self, key: impl AsRef<[u8]>, flags: &[MaFlag]) -> io::Result<MaItem> {
5063        let i = *self.1.get(&key.as_ref()).unwrap();
5064        self.0[i].ma(key.as_ref(), flags).await
5065    }
5066}
5067
5068pub struct ClientRendezvous(Vec<Connection>, HrwNodes<usize>);
5069impl ClientRendezvous {
5070    /// # Example
5071    ///
5072    /// ```
5073    /// use mcmc_rs::{ClientRendezvous, Connection};
5074    /// # use smol::{io, block_on};
5075    /// #
5076    /// # block_on(async {
5077    /// let mut client = ClientRendezvous::new(vec![
5078    ///     Connection::default().await?,
5079    ///     Connection::unix_connect("/tmp/memcached0.sock").await?,
5080    /// ]);
5081    /// # Ok::<(), io::Error>(())
5082    /// # }).unwrap()
5083    pub fn new(conns: Vec<Connection>) -> Self {
5084        let hrw = HrwNodes::new(0..conns.len());
5085        Self(conns, hrw)
5086    }
5087
5088    /// # Example
5089    ///
5090    /// ```
5091    /// use mcmc_rs::{ClientRendezvous, Connection};
5092    /// # use smol::{io, block_on};
5093    /// #
5094    /// # block_on(async {
5095    /// let mut client = ClientRendezvous::new(vec![
5096    ///     Connection::default().await?,
5097    ///     Connection::unix_connect("/tmp/memcached0.sock").await?,
5098    /// ]);
5099    ///
5100    /// assert!(client.set(b"k7", 0, 0, false, b"v7").await?);
5101    /// assert_eq!(client.get(b"k7").await?.unwrap().key, "k7");
5102    /// # Ok::<(), io::Error>(())
5103    /// # }).unwrap()
5104    /// ```
5105    pub async fn get(&mut self, key: impl AsRef<[u8]>) -> io::Result<Option<Item>> {
5106        let i = *self.1.sorted(&key.as_ref()).next().unwrap();
5107        self.0[i].get(key.as_ref()).await
5108    }
5109
5110    /// # Example
5111    ///
5112    /// ```
5113    /// use mcmc_rs::{ClientRendezvous, Connection};
5114    /// # use smol::{io, block_on};
5115    /// #
5116    /// # block_on(async {
5117    /// let mut client = ClientRendezvous::new(vec![
5118    ///     Connection::default().await?,
5119    ///     Connection::unix_connect("/tmp/memcached0.sock").await?,
5120    /// ]);
5121    ///
5122    /// assert!(client.set(b"k8", 0, 0, false, b"v8").await?);
5123    /// assert_eq!(client.gets(b"k8").await?.unwrap().key, "k8");
5124    /// # Ok::<(), io::Error>(())
5125    /// # }).unwrap()
5126    /// ```
5127    pub async fn gets(&mut self, key: impl AsRef<[u8]>) -> io::Result<Option<Item>> {
5128        let i = *self.1.sorted(&key.as_ref()).next().unwrap();
5129        self.0[i].gets(key.as_ref()).await
5130    }
5131
5132    /// # Example
5133    ///
5134    /// ```
5135    /// # use mcmc_rs::{Connection, ClientRendezvous};
5136    /// # use smol::{io, block_on};
5137    /// #
5138    /// # block_on(async {
5139    /// let mut client = ClientRendezvous::new(vec![
5140    ///     Connection::default().await?,
5141    ///     Connection::unix_connect("/tmp/memcached0.sock").await?,
5142    /// ]);
5143    /// assert!(client.set(b"k9", 0, 0, false, b"v9").await?);
5144    /// let result = client.gat(0, b"k9").await?;
5145    /// assert_eq!(result.unwrap().key, "k9");
5146    /// # Ok::<(), io::Error>(())
5147    /// # }).unwrap()
5148    /// ```
5149    pub async fn gat(&mut self, exptime: i64, key: impl AsRef<[u8]>) -> io::Result<Option<Item>> {
5150        let i = *self.1.sorted(&key.as_ref()).next().unwrap();
5151        self.0[i].gat(exptime, key.as_ref()).await
5152    }
5153
5154    /// # Example
5155    ///
5156    /// ```
5157    /// # use mcmc_rs::{Connection, ClientRendezvous};
5158    /// # use smol::{io, block_on};
5159    /// #
5160    /// # block_on(async {
5161    /// let mut client = ClientRendezvous::new(vec![
5162    ///     Connection::default().await?,
5163    ///     Connection::unix_connect("/tmp/memcached0.sock").await?,
5164    /// ]);
5165    /// assert!(client.set(b"k10", 0, 0, false, b"v10").await?);
5166    /// let result = client.gats(0, b"k10").await?;
5167    /// assert_eq!(result.unwrap().key, "k10");
5168    /// # Ok::<(), io::Error>(())
5169    /// # }).unwrap()
5170    /// ```
5171    pub async fn gats(&mut self, exptime: i64, key: impl AsRef<[u8]>) -> io::Result<Option<Item>> {
5172        let i = *self.1.sorted(&key.as_ref()).next().unwrap();
5173        self.0[i].gats(exptime, key.as_ref()).await
5174    }
5175
5176    /// # Example
5177    ///
5178    /// ```
5179    /// use mcmc_rs::{ClientRendezvous, Connection};
5180    /// # use smol::{io, block_on};
5181    /// #
5182    /// # block_on(async {
5183    /// let mut client = ClientRendezvous::new(vec![
5184    ///     Connection::default().await?,
5185    ///     Connection::unix_connect("/tmp/memcached0.sock").await?,
5186    /// ]);
5187    ///
5188    /// assert!(client.set(b"key", 0, -1, true, b"value").await?);
5189    /// # Ok::<(), io::Error>(())
5190    /// # }).unwrap()
5191    /// ```
5192    pub async fn set(
5193        &mut self,
5194        key: impl AsRef<[u8]>,
5195        flags: u32,
5196        exptime: i64,
5197        noreply: bool,
5198        data_block: impl AsRef<[u8]>,
5199    ) -> io::Result<bool> {
5200        let i = *self.1.sorted(&key.as_ref()).next().unwrap();
5201        self.0[i]
5202            .set(key.as_ref(), flags, exptime, noreply, data_block.as_ref())
5203            .await
5204    }
5205
5206    /// # Example
5207    ///
5208    /// ```
5209    /// use mcmc_rs::{ClientRendezvous, Connection};
5210    /// # use smol::{io, block_on};
5211    /// #
5212    /// # block_on(async {
5213    /// let mut client = ClientRendezvous::new(vec![
5214    ///     Connection::default().await?,
5215    ///     Connection::unix_connect("/tmp/memcached0.sock").await?,
5216    /// ]);
5217    ///
5218    /// assert!(client.add(b"key", 0, -1, true, b"value").await?);
5219    /// # Ok::<(), io::Error>(())
5220    /// # }).unwrap()
5221    /// ```
5222    pub async fn add(
5223        &mut self,
5224        key: impl AsRef<[u8]>,
5225        flags: u32,
5226        exptime: i64,
5227        noreply: bool,
5228        data_block: impl AsRef<[u8]>,
5229    ) -> io::Result<bool> {
5230        let i = *self.1.sorted(&key.as_ref()).next().unwrap();
5231        self.0[i]
5232            .add(key.as_ref(), flags, exptime, noreply, data_block.as_ref())
5233            .await
5234    }
5235
5236    /// # Example
5237    ///
5238    /// ```
5239    /// use mcmc_rs::{ClientRendezvous, Connection};
5240    /// # use smol::{io, block_on};
5241    /// #
5242    /// # block_on(async {
5243    /// let mut client = ClientRendezvous::new(vec![
5244    ///     Connection::default().await?,
5245    ///     Connection::unix_connect("/tmp/memcached0.sock").await?,
5246    /// ]);
5247    ///
5248    /// assert!(client.replace(b"key", 0, -1, true, b"value").await?);
5249    /// # Ok::<(), io::Error>(())
5250    /// # }).unwrap()
5251    /// ```
5252    pub async fn replace(
5253        &mut self,
5254        key: impl AsRef<[u8]>,
5255        flags: u32,
5256        exptime: i64,
5257        noreply: bool,
5258        data_block: impl AsRef<[u8]>,
5259    ) -> io::Result<bool> {
5260        let i = *self.1.sorted(&key.as_ref()).next().unwrap();
5261        self.0[i]
5262            .replace(key.as_ref(), flags, exptime, noreply, data_block.as_ref())
5263            .await
5264    }
5265
5266    /// # Example
5267    ///
5268    /// ```
5269    /// use mcmc_rs::{ClientRendezvous, Connection};
5270    /// # use smol::{io, block_on};
5271    /// #
5272    /// # block_on(async {
5273    /// let mut client = ClientRendezvous::new(vec![
5274    ///     Connection::default().await?,
5275    ///     Connection::unix_connect("/tmp/memcached0.sock").await?,
5276    /// ]);
5277    ///
5278    /// assert!(client.append(b"key", 0, -1, true, b"value").await?);
5279    /// # Ok::<(), io::Error>(())
5280    /// # }).unwrap()
5281    /// ```
5282    pub async fn append(
5283        &mut self,
5284        key: impl AsRef<[u8]>,
5285        flags: u32,
5286        exptime: i64,
5287        noreply: bool,
5288        data_block: impl AsRef<[u8]>,
5289    ) -> io::Result<bool> {
5290        let i = *self.1.sorted(&key.as_ref()).next().unwrap();
5291        self.0[i]
5292            .append(key.as_ref(), flags, exptime, noreply, data_block.as_ref())
5293            .await
5294    }
5295
5296    /// # Example
5297    ///
5298    /// ```
5299    /// use mcmc_rs::{ClientRendezvous, Connection};
5300    /// # use smol::{io, block_on};
5301    /// #
5302    /// # block_on(async {
5303    /// let mut client = ClientRendezvous::new(vec![
5304    ///     Connection::default().await?,
5305    ///     Connection::unix_connect("/tmp/memcached0.sock").await?,
5306    /// ]);
5307    ///
5308    /// assert!(client.prepend(b"key", 0, -1, true, b"value").await?);
5309    /// # Ok::<(), io::Error>(())
5310    /// # }).unwrap()
5311    /// ```
5312    pub async fn prepend(
5313        &mut self,
5314        key: impl AsRef<[u8]>,
5315        flags: u32,
5316        exptime: i64,
5317        noreply: bool,
5318        data_block: impl AsRef<[u8]>,
5319    ) -> io::Result<bool> {
5320        let i = *self.1.sorted(&key.as_ref()).next().unwrap();
5321        self.0[i]
5322            .prepend(key.as_ref(), flags, exptime, noreply, data_block.as_ref())
5323            .await
5324    }
5325
5326    /// # Example
5327    ///
5328    /// ```
5329    /// use mcmc_rs::{ClientRendezvous, Connection};
5330    /// # use smol::{io, block_on};
5331    /// #
5332    /// # block_on(async {
5333    /// let mut client = ClientRendezvous::new(vec![
5334    ///     Connection::default().await?,
5335    ///     Connection::unix_connect("/tmp/memcached0.sock").await?,
5336    /// ]);
5337    ///
5338    /// assert!(client.cas(b"key", 0, -1, 0, true, b"value").await?);
5339    /// # Ok::<(), io::Error>(())
5340    /// # }).unwrap()
5341    /// ```
5342    pub async fn cas(
5343        &mut self,
5344        key: impl AsRef<[u8]>,
5345        flags: u32,
5346        exptime: i64,
5347        cas_unique: u64,
5348        noreply: bool,
5349        data_block: impl AsRef<[u8]>,
5350    ) -> io::Result<bool> {
5351        let i = *self.1.sorted(&key.as_ref()).next().unwrap();
5352        self.0[i]
5353            .cas(
5354                key.as_ref(),
5355                flags,
5356                exptime,
5357                cas_unique,
5358                noreply,
5359                data_block.as_ref(),
5360            )
5361            .await
5362    }
5363
5364    /// # Example
5365    ///
5366    /// ```
5367    /// use mcmc_rs::{ClientRendezvous, Connection};
5368    /// # use smol::{io, block_on};
5369    /// #
5370    /// # block_on(async {
5371    /// let mut client = ClientRendezvous::new(vec![
5372    ///     Connection::default().await?,
5373    ///     Connection::unix_connect("/tmp/memcached0.sock").await?,
5374    /// ]);
5375    ///
5376    /// assert!(client.delete(b"key", true).await?);
5377    /// # Ok::<(), io::Error>(())
5378    /// # }).unwrap()
5379    /// ```
5380    pub async fn delete(&mut self, key: impl AsRef<[u8]>, noreply: bool) -> io::Result<bool> {
5381        let i = *self.1.sorted(&key.as_ref()).next().unwrap();
5382        self.0[i].delete(key.as_ref(), noreply).await
5383    }
5384
5385    /// # Example
5386    ///
5387    /// ```
5388    /// use mcmc_rs::{ClientRendezvous, Connection};
5389    /// # use smol::{io, block_on};
5390    /// #
5391    /// # block_on(async {
5392    /// let mut client = ClientRendezvous::new(vec![
5393    ///     Connection::default().await?,
5394    ///     Connection::unix_connect("/tmp/memcached0.sock").await?,
5395    /// ]);
5396    ///
5397    /// assert!(client.incr(b"key", 1, true).await?.is_none());
5398    /// # Ok::<(), io::Error>(())
5399    /// # }).unwrap()
5400    /// ```
5401    pub async fn incr(
5402        &mut self,
5403        key: impl AsRef<[u8]>,
5404        value: u64,
5405        noreply: bool,
5406    ) -> io::Result<Option<u64>> {
5407        let i = *self.1.sorted(&key.as_ref()).next().unwrap();
5408        self.0[i].incr(key.as_ref(), value, noreply).await
5409    }
5410
5411    /// # Example
5412    ///
5413    /// ```
5414    /// use mcmc_rs::{ClientRendezvous, Connection};
5415    /// # use smol::{io, block_on};
5416    /// #
5417    /// # block_on(async {
5418    /// let mut client = ClientRendezvous::new(vec![
5419    ///     Connection::default().await?,
5420    ///     Connection::unix_connect("/tmp/memcached0.sock").await?,
5421    /// ]);
5422    ///
5423    /// assert!(client.decr(b"key", 1, true).await?.is_none());
5424    /// # Ok::<(), io::Error>(())
5425    /// # }).unwrap()
5426    /// ```
5427    pub async fn decr(
5428        &mut self,
5429        key: impl AsRef<[u8]>,
5430        value: u64,
5431        noreply: bool,
5432    ) -> io::Result<Option<u64>> {
5433        let i = *self.1.sorted(&key.as_ref()).next().unwrap();
5434        self.0[i].decr(key.as_ref(), value, noreply).await
5435    }
5436
5437    /// # Example
5438    ///
5439    /// ```
5440    /// use mcmc_rs::{ClientRendezvous, Connection};
5441    /// # use smol::{io, block_on};
5442    /// #
5443    /// # block_on(async {
5444    /// let mut client = ClientRendezvous::new(vec![
5445    ///     Connection::default().await?,
5446    ///     Connection::unix_connect("/tmp/memcached0.sock").await?,
5447    /// ]);
5448    ///
5449    /// assert!(client.touch(b"key", -1, true).await?);
5450    /// # Ok::<(), io::Error>(())
5451    /// # }).unwrap()
5452    /// ```
5453    pub async fn touch(
5454        &mut self,
5455        key: impl AsRef<[u8]>,
5456        exptime: i64,
5457        noreply: bool,
5458    ) -> io::Result<bool> {
5459        let i = *self.1.sorted(&key.as_ref()).next().unwrap();
5460        self.0[i].touch(key.as_ref(), exptime, noreply).await
5461    }
5462
5463    /// # Example
5464    ///
5465    /// ```
5466    /// use mcmc_rs::{ClientRendezvous, Connection};
5467    /// # use smol::{io, block_on};
5468    /// #
5469    /// # block_on(async {
5470    /// let mut client = ClientRendezvous::new(vec![
5471    ///     Connection::default().await?,
5472    ///     Connection::unix_connect("/tmp/memcached0.sock").await?,
5473    /// ]);
5474    /// assert!(client.set(b"k11", 0, 0, false, b"v11").await?);
5475    /// assert!(client.me(b"k11").await?.is_some());
5476    /// # Ok::<(), io::Error>(())
5477    /// # }).unwrap()
5478    /// ```
5479    pub async fn me(&mut self, key: impl AsRef<[u8]>) -> io::Result<Option<String>> {
5480        let i = *self.1.sorted(&key.as_ref()).next().unwrap();
5481        self.0[i].me(key.as_ref()).await
5482    }
5483
5484    /// # Example
5485    ///
5486    /// ```
5487    /// use mcmc_rs::{ClientRendezvous, Connection, MgFlag, MgItem};
5488    /// # use smol::{io, block_on};
5489    /// #
5490    /// # block_on(async {
5491    /// let mut client = ClientRendezvous::new(vec![
5492    ///     Connection::default().await?,
5493    ///     Connection::unix_connect("/tmp/memcached0.sock").await?,
5494    /// ]);
5495    /// let result = client
5496    ///     .mg(
5497    ///         b"44OG44K544OI",
5498    ///         &[
5499    ///             MgFlag::Base64Key,
5500    ///             MgFlag::ReturnCas,
5501    ///             MgFlag::ReturnFlags,
5502    ///             MgFlag::ReturnHit,
5503    ///             MgFlag::ReturnKey,
5504    ///             MgFlag::ReturnLastAccess,
5505    ///             MgFlag::Opaque("opaque".to_string()),
5506    ///             MgFlag::ReturnSize,
5507    ///             MgFlag::ReturnTtl,
5508    ///             MgFlag::UnBump,
5509    ///             MgFlag::ReturnValue,
5510    ///             MgFlag::NewCas(0),
5511    ///             MgFlag::Autovivify(-1),
5512    ///             MgFlag::RecacheTtl(-1),
5513    ///             MgFlag::UpdateTtl(-1),
5514    ///         ],
5515    ///     )
5516    ///     .await?;
5517    /// assert_eq!(
5518    ///     result,
5519    ///     MgItem {
5520    ///         success: true,
5521    ///         base64_key: false,
5522    ///         cas: Some(0),
5523    ///         flags: Some(0),
5524    ///         hit: Some(0),
5525    ///         key: Some("テスト".to_string()),
5526    ///         last_access_ttl: Some(0),
5527    ///         opaque: Some("opaque".to_string()),
5528    ///         size: Some(0),
5529    ///         ttl: Some(-1),
5530    ///         data_block: Some(vec![]),
5531    ///         already_win: false,
5532    ///         won_recache: true,
5533    ///         stale: false,
5534    ///     }
5535    /// );
5536    /// # Ok::<(), io::Error>(())
5537    /// # }).unwrap()
5538    /// ```
5539    pub async fn mg(&mut self, key: impl AsRef<[u8]>, flags: &[MgFlag]) -> io::Result<MgItem> {
5540        let i = *self.1.sorted(&key.as_ref()).next().unwrap();
5541        self.0[i].mg(key.as_ref(), flags).await
5542    }
5543
5544    /// # Example
5545    ///
5546    /// ```
5547    /// use mcmc_rs::{ClientRendezvous, Connection, MsFlag, MsItem, MsMode};
5548    /// # use smol::{io, block_on};
5549    /// #
5550    /// # block_on(async {
5551    /// let mut client = ClientRendezvous::new(vec![
5552    ///     Connection::default().await?,
5553    ///     Connection::unix_connect("/tmp/memcached0.sock").await?,
5554    /// ]);
5555    /// let result = client
5556    ///     .ms(
5557    ///         b"44OG44K544OI",
5558    ///         &[
5559    ///             MsFlag::Base64Key,
5560    ///             MsFlag::ReturnCas,
5561    ///             MsFlag::CompareCas(0),
5562    ///             MsFlag::NewCas(0),
5563    ///             MsFlag::SetFlags(0),
5564    ///             MsFlag::Invalidate,
5565    ///             MsFlag::ReturnKey,
5566    ///             MsFlag::Opaque("opaque".to_string()),
5567    ///             MsFlag::ReturnSize,
5568    ///             MsFlag::Ttl(-1),
5569    ///             MsFlag::Mode(MsMode::Set),
5570    ///             MsFlag::Autovivify(0),
5571    ///         ],
5572    ///         b"hi",
5573    ///     )
5574    ///     .await?;
5575    /// assert_eq!(
5576    ///     result,
5577    ///     MsItem {
5578    ///         success: false,
5579    ///         cas: Some(0),
5580    ///         key: Some("44OG44K544OI".to_string()),
5581    ///         opaque: Some("opaque".to_string()),
5582    ///         size: Some(2),
5583    ///         base64_key: true
5584    ///     }
5585    /// );
5586    /// # Ok::<(), io::Error>(())
5587    /// # }).unwrap()
5588    /// ```
5589    pub async fn ms(
5590        &mut self,
5591        key: impl AsRef<[u8]>,
5592        flags: &[MsFlag],
5593        data_block: impl AsRef<[u8]>,
5594    ) -> io::Result<MsItem> {
5595        let i = *self.1.sorted(&key.as_ref()).next().unwrap();
5596        self.0[i].ms(key.as_ref(), flags, data_block.as_ref()).await
5597    }
5598
5599    /// # Example
5600    ///
5601    /// ```
5602    /// use mcmc_rs::{ClientRendezvous, Connection, MdFlag, MdItem};
5603    /// # use smol::{io, block_on};
5604    /// #
5605    /// # block_on(async {
5606    /// let mut client = ClientRendezvous::new(vec![
5607    ///     Connection::default().await?,
5608    ///     Connection::unix_connect("/tmp/memcached0.sock").await?,
5609    /// ]);
5610    /// let result = client
5611    ///     .md(
5612    ///         b"44OG44K544OI",
5613    ///         &[
5614    ///             MdFlag::Base64Key,
5615    ///             MdFlag::CompareCas(0),
5616    ///             MdFlag::NewCas(0),
5617    ///             MdFlag::Invalidate,
5618    ///             MdFlag::ReturnKey,
5619    ///             MdFlag::Opaque("opaque".to_string()),
5620    ///             MdFlag::UpdateTtl(-1),
5621    ///             MdFlag::LeaveKey,
5622    ///         ],
5623    ///     )
5624    ///     .await?;
5625    /// assert_eq!(
5626    ///     result,
5627    ///     MdItem {
5628    ///         success: false,
5629    ///         key: Some("44OG44K544OI".to_string()),
5630    ///         opaque: Some("opaque".to_string()),
5631    ///         base64_key: true
5632    ///     }
5633    /// );
5634    /// # Ok::<(), io::Error>(())
5635    /// # }).unwrap()
5636    /// ```
5637    pub async fn md(&mut self, key: impl AsRef<[u8]>, flags: &[MdFlag]) -> io::Result<MdItem> {
5638        let i = *self.1.sorted(&key.as_ref()).next().unwrap();
5639        self.0[i].md(key.as_ref(), flags).await
5640    }
5641
5642    /// # Example
5643    ///
5644    /// ```
5645    /// use mcmc_rs::{ClientRendezvous, Connection, MaFlag, MaItem, MaMode};
5646    /// # use smol::{io, block_on};
5647    /// #
5648    /// # block_on(async {
5649    /// let mut client = ClientRendezvous::new(vec![
5650    ///     Connection::default().await?,
5651    ///     Connection::unix_connect("/tmp/memcached0.sock").await?,
5652    /// ]);
5653    /// let result = client
5654    ///     .ma(
5655    ///         b"aGk=",
5656    ///         &[
5657    ///             MaFlag::Base64Key,
5658    ///             MaFlag::CompareCas(0),
5659    ///             MaFlag::NewCas(0),
5660    ///             MaFlag::AutoCreate(0),
5661    ///             MaFlag::InitValue(0),
5662    ///             MaFlag::DeltaApply(0),
5663    ///             MaFlag::UpdateTtl(0),
5664    ///             MaFlag::Mode(MaMode::Incr),
5665    ///             MaFlag::Opaque("opaque".to_string()),
5666    ///             MaFlag::ReturnTtl,
5667    ///             MaFlag::ReturnCas,
5668    ///             MaFlag::ReturnValue,
5669    ///             MaFlag::ReturnKey,
5670    ///         ],
5671    ///     )
5672    ///     .await?;
5673    /// assert_eq!(
5674    ///     result,
5675    ///     MaItem {
5676    ///         success: true,
5677    ///         opaque: Some("opaque".to_string()),
5678    ///         ttl: Some(-1),
5679    ///         cas: Some(0),
5680    ///         number: Some(0),
5681    ///         key: Some("aGk=".to_string()),
5682    ///         base64_key: true
5683    ///     }
5684    /// );
5685    /// # Ok::<(), io::Error>(())
5686    /// # }).unwrap()
5687    /// ```
5688    pub async fn ma(&mut self, key: impl AsRef<[u8]>, flags: &[MaFlag]) -> io::Result<MaItem> {
5689        let i = *self.1.sorted(&key.as_ref()).next().unwrap();
5690        self.0[i].ma(key.as_ref(), flags).await
5691    }
5692}
5693
5694pub struct Pipeline<'a>(&'a mut Connection, Vec<Vec<u8>>);
5695impl<'a> Pipeline<'a> {
5696    /// # Example
5697    ///
5698    /// ```
5699    /// use mcmc_rs::Connection;
5700    /// # use smol::{io, block_on};
5701    /// #
5702    /// # block_on(async {
5703    /// let mut conn = Connection::default().await?;
5704    /// conn.pipeline();
5705    /// # Ok::<(), io::Error>(())
5706    /// # }).unwrap()
5707    /// ```
5708    fn new(conn: &'a mut Connection) -> Self {
5709        Self(conn, Vec::new())
5710    }
5711
5712    /// # Example
5713    ///
5714    /// ```
5715    /// use mcmc_rs::{Connection, PipelineResponse};
5716    /// # use smol::{io, block_on};
5717    /// #
5718    /// # block_on(async {
5719    /// for mut c in [
5720    ///     Connection::default().await?,
5721    ///     Connection::unix_connect("/tmp/memcached0.sock").await?,
5722    ///     Connection::tls_connect("localhost", 11216, "cert.pem").await?,
5723    /// ] {
5724    ///     let result = c
5725    ///         .pipeline()
5726    ///         .set(b"key", 0, -1, false, b"value")
5727    ///         .get("key")
5728    ///         .execute()
5729    ///         .await?;
5730    ///     assert_eq!(
5731    ///         result,
5732    ///         [
5733    ///             PipelineResponse::Bool(true),
5734    ///             PipelineResponse::OptionItem(None),
5735    ///         ]
5736    ///     );
5737    /// }
5738    /// # Ok::<(), io::Error>(())
5739    /// # }).unwrap()
5740    /// ```
5741    pub async fn execute(self) -> io::Result<Vec<PipelineResponse>> {
5742        if self.1.is_empty() {
5743            return Ok(Vec::new());
5744        };
5745        match self.0 {
5746            Connection::Tcp(s) => execute_cmd(s, &self.1).await,
5747            Connection::Unix(s) => execute_cmd(s, &self.1).await,
5748            Connection::Udp(_s, _r) => todo!(),
5749            Connection::Tls(s) => execute_cmd(s, &self.1).await,
5750        }
5751    }
5752
5753    /// # Example
5754    ///
5755    /// ```
5756    /// use mcmc_rs::Connection;
5757    /// # use smol::{io, block_on};
5758    /// #
5759    /// # block_on(async {
5760    /// let mut conn = Connection::default().await?;
5761    /// conn.pipeline().version();
5762    /// # Ok::<(), io::Error>(())
5763    /// # }).unwrap()
5764    /// ```
5765    pub fn version(mut self) -> Self {
5766        self.1.push(build_version_cmd().to_vec());
5767        self
5768    }
5769
5770    /// # Example
5771    ///
5772    /// ```
5773    /// use mcmc_rs::Connection;
5774    /// # use smol::{io, block_on};
5775    /// #
5776    /// # block_on(async {
5777    /// let mut conn = Connection::default().await?;
5778    /// conn.pipeline().quit();
5779    /// # Ok::<(), io::Error>(())
5780    /// # }).unwrap()
5781    /// ```
5782    pub fn quit(mut self) -> Self {
5783        self.1.push(build_quit_cmd().to_vec());
5784        self
5785    }
5786
5787    /// # Example
5788    ///
5789    /// ```
5790    /// use mcmc_rs::Connection;
5791    /// # use smol::{io, block_on};
5792    /// #
5793    /// # block_on(async {
5794    /// let mut conn = Connection::default().await?;
5795    /// conn.pipeline().shutdown(false);
5796    /// # Ok::<(), io::Error>(())
5797    /// # }).unwrap()
5798    /// ```
5799    pub fn shutdown(mut self, graceful: bool) -> Self {
5800        self.1.push(build_shutdown_cmd(graceful).to_vec());
5801        self
5802    }
5803
5804    /// # Example
5805    ///
5806    /// ```
5807    /// use mcmc_rs::Connection;
5808    /// # use smol::{io, block_on};
5809    /// #
5810    /// # block_on(async {
5811    /// let mut conn = Connection::default().await?;
5812    /// conn.pipeline().cache_memlimit(1, false);
5813    /// # Ok::<(), io::Error>(())
5814    /// # }).unwrap()
5815    /// ```
5816    pub fn cache_memlimit(mut self, limit: usize, noreply: bool) -> Self {
5817        self.1
5818            .push(build_cache_memlimit_cmd(limit, noreply).to_vec());
5819        self
5820    }
5821
5822    /// # Example
5823    ///
5824    /// ```
5825    /// use mcmc_rs::Connection;
5826    /// # use smol::{io, block_on};
5827    /// #
5828    /// # block_on(async {
5829    /// let mut conn = Connection::default().await?;
5830    /// conn.pipeline().flush_all(None, false);
5831    /// # Ok::<(), io::Error>(())
5832    /// # }).unwrap()
5833    /// ```
5834    pub fn flush_all(mut self, exptime: Option<i64>, noreply: bool) -> Self {
5835        self.1.push(build_flush_all_cmd(exptime, noreply).to_vec());
5836        self
5837    }
5838
5839    /// # Example
5840    ///
5841    /// ```
5842    /// use mcmc_rs::Connection;
5843    /// # use smol::{io, block_on};
5844    /// #
5845    /// # block_on(async {
5846    /// let mut conn = Connection::default().await?;
5847    /// conn.pipeline().set(b"key", 0, 0, false, b"value");
5848    /// # Ok::<(), io::Error>(())
5849    /// # }).unwrap()
5850    /// ```
5851    pub fn set(
5852        mut self,
5853        key: impl AsRef<[u8]>,
5854        flags: u32,
5855        exptime: i64,
5856        noreply: bool,
5857        data_block: impl AsRef<[u8]>,
5858    ) -> Self {
5859        self.1.push(build_storage_cmd(
5860            b"set",
5861            key.as_ref(),
5862            flags,
5863            exptime,
5864            None,
5865            noreply,
5866            data_block.as_ref(),
5867        ));
5868        self
5869    }
5870
5871    /// # Example
5872    ///
5873    /// ```
5874    /// use mcmc_rs::Connection;
5875    /// # use smol::{io, block_on};
5876    /// #
5877    /// # block_on(async {
5878    /// let mut conn = Connection::default().await?;
5879    /// conn.pipeline().add(b"key", 0, 0, false, b"value");
5880    /// # Ok::<(), io::Error>(())
5881    /// # }).unwrap()
5882    /// ```
5883    pub fn add(
5884        mut self,
5885        key: impl AsRef<[u8]>,
5886        flags: u32,
5887        exptime: i64,
5888        noreply: bool,
5889        data_block: impl AsRef<[u8]>,
5890    ) -> Self {
5891        self.1.push(build_storage_cmd(
5892            b"add",
5893            key.as_ref(),
5894            flags,
5895            exptime,
5896            None,
5897            noreply,
5898            data_block.as_ref(),
5899        ));
5900        self
5901    }
5902
5903    /// # Example
5904    ///
5905    /// ```
5906    /// use mcmc_rs::Connection;
5907    /// # use smol::{io, block_on};
5908    /// #
5909    /// # block_on(async {
5910    /// let mut conn = Connection::default().await?;
5911    /// conn.pipeline().replace(b"key", 0, 0, false, b"value");
5912    /// # Ok::<(), io::Error>(())
5913    /// # }).unwrap()
5914    /// ```
5915    pub fn replace(
5916        mut self,
5917        key: impl AsRef<[u8]>,
5918        flags: u32,
5919        exptime: i64,
5920        noreply: bool,
5921        data_block: impl AsRef<[u8]>,
5922    ) -> Self {
5923        self.1.push(build_storage_cmd(
5924            b"replace",
5925            key.as_ref(),
5926            flags,
5927            exptime,
5928            None,
5929            noreply,
5930            data_block.as_ref(),
5931        ));
5932        self
5933    }
5934
5935    /// # Example
5936    ///
5937    /// ```
5938    /// use mcmc_rs::Connection;
5939    /// # use smol::{io, block_on};
5940    /// #
5941    /// # block_on(async {
5942    /// let mut conn = Connection::default().await?;
5943    /// conn.pipeline().append(b"key", 0, 0, false, b"value");
5944    /// # Ok::<(), io::Error>(())
5945    /// # }).unwrap()
5946    /// ```
5947    pub fn append(
5948        mut self,
5949        key: impl AsRef<[u8]>,
5950        flags: u32,
5951        exptime: i64,
5952        noreply: bool,
5953        data_block: impl AsRef<[u8]>,
5954    ) -> Self {
5955        self.1.push(build_storage_cmd(
5956            b"append",
5957            key.as_ref(),
5958            flags,
5959            exptime,
5960            None,
5961            noreply,
5962            data_block.as_ref(),
5963        ));
5964        self
5965    }
5966
5967    /// # Example
5968    ///
5969    /// ```
5970    /// use mcmc_rs::Connection;
5971    /// # use smol::{io, block_on};
5972    /// #
5973    /// # block_on(async {
5974    /// let mut conn = Connection::default().await?;
5975    /// conn.pipeline().prepend(b"key", 0, 0, false, b"value");
5976    /// # Ok::<(), io::Error>(())
5977    /// # }).unwrap()
5978    /// ```
5979    pub fn prepend(
5980        mut self,
5981        key: impl AsRef<[u8]>,
5982        flags: u32,
5983        exptime: i64,
5984        noreply: bool,
5985        data_block: impl AsRef<[u8]>,
5986    ) -> Self {
5987        self.1.push(build_storage_cmd(
5988            b"prepend",
5989            key.as_ref(),
5990            flags,
5991            exptime,
5992            None,
5993            noreply,
5994            data_block.as_ref(),
5995        ));
5996        self
5997    }
5998
5999    /// # Example
6000    ///
6001    /// ```
6002    /// use mcmc_rs::Connection;
6003    /// # use smol::{io, block_on};
6004    /// #
6005    /// # block_on(async {
6006    /// let mut conn = Connection::default().await?;
6007    /// conn.pipeline().cas(b"key", 0, 0, 0, false, b"value");
6008    /// # Ok::<(), io::Error>(())
6009    /// # }).unwrap()
6010    /// ```
6011    pub fn cas(
6012        mut self,
6013        key: impl AsRef<[u8]>,
6014        flags: u32,
6015        exptime: i64,
6016        cas_unique: u64,
6017        noreply: bool,
6018        data_block: impl AsRef<[u8]>,
6019    ) -> Self {
6020        self.1.push(build_storage_cmd(
6021            b"cas",
6022            key.as_ref(),
6023            flags,
6024            exptime,
6025            Some(cas_unique),
6026            noreply,
6027            data_block.as_ref(),
6028        ));
6029        self
6030    }
6031
6032    /// # Example
6033    ///
6034    /// ```
6035    /// use mcmc_rs::Connection;
6036    /// # use smol::{io, block_on};
6037    /// #
6038    /// # block_on(async {
6039    /// let mut conn = Connection::default().await?;
6040    /// conn.pipeline().auth(b"username", b"password");
6041    /// # Ok::<(), io::Error>(())
6042    /// # }).unwrap()
6043    /// ```
6044    pub fn auth(mut self, username: impl AsRef<[u8]>, password: impl AsRef<[u8]>) -> Self {
6045        self.1
6046            .push(build_auth_cmd(username.as_ref(), password.as_ref()));
6047        self
6048    }
6049
6050    /// # Example
6051    ///
6052    /// ```
6053    /// use mcmc_rs::Connection;
6054    /// # use smol::{io, block_on};
6055    /// #
6056    /// # block_on(async {
6057    /// let mut conn = Connection::default().await?;
6058    /// conn.pipeline().delete(b"key", false);
6059    /// # Ok::<(), io::Error>(())
6060    /// # }).unwrap()
6061    /// ```
6062    pub fn delete(mut self, key: impl AsRef<[u8]>, noreply: bool) -> Self {
6063        self.1.push(build_delete_cmd(key.as_ref(), noreply));
6064        self
6065    }
6066
6067    /// # Example
6068    ///
6069    /// ```
6070    /// use mcmc_rs::Connection;
6071    /// # use smol::{io, block_on};
6072    /// #
6073    /// # block_on(async {
6074    /// let mut conn = Connection::default().await?;
6075    /// conn.pipeline().incr(b"key", 1, false);
6076    /// # Ok::<(), io::Error>(())
6077    /// # }).unwrap()
6078    /// ```
6079    pub fn incr(mut self, key: impl AsRef<[u8]>, value: u64, noreply: bool) -> Self {
6080        self.1
6081            .push(build_incr_decr_cmd(b"incr", key.as_ref(), value, noreply));
6082        self
6083    }
6084
6085    /// # Example
6086    ///
6087    /// ```
6088    /// use mcmc_rs::Connection;
6089    /// # use smol::{io, block_on};
6090    /// #
6091    /// # block_on(async {
6092    /// let mut conn = Connection::default().await?;
6093    /// conn.pipeline().decr(b"key", 1, false);
6094    /// # Ok::<(), io::Error>(())
6095    /// # }).unwrap()
6096    /// ```
6097    pub fn decr(mut self, key: impl AsRef<[u8]>, value: u64, noreply: bool) -> Self {
6098        self.1
6099            .push(build_incr_decr_cmd(b"decr", key.as_ref(), value, noreply));
6100        self
6101    }
6102
6103    /// # Example
6104    ///
6105    /// ```
6106    /// use mcmc_rs::Connection;
6107    /// # use smol::{io, block_on};
6108    /// #
6109    /// # block_on(async {
6110    /// let mut conn = Connection::default().await?;
6111    /// conn.pipeline().touch(b"key", 1, false);
6112    /// # Ok::<(), io::Error>(())
6113    /// # }).unwrap()
6114    /// ```
6115    pub fn touch(mut self, key: impl AsRef<[u8]>, exptime: i64, noreply: bool) -> Self {
6116        self.1.push(build_touch_cmd(key.as_ref(), exptime, noreply));
6117        self
6118    }
6119
6120    /// # Example
6121    ///
6122    /// ```
6123    /// use mcmc_rs::Connection;
6124    /// # use smol::{io, block_on};
6125    /// #
6126    /// # block_on(async {
6127    /// let mut conn = Connection::default().await?;
6128    /// conn.pipeline().get(b"key");
6129    /// # Ok::<(), io::Error>(())
6130    /// # }).unwrap()
6131    /// ```
6132    pub fn get(mut self, key: impl AsRef<[u8]>) -> Self {
6133        self.1
6134            .push(build_retrieval_cmd(b"get", None, &[key.as_ref()]));
6135        self
6136    }
6137
6138    /// # Example
6139    ///
6140    /// ```
6141    /// use mcmc_rs::Connection;
6142    /// # use smol::{io, block_on};
6143    /// #
6144    /// # block_on(async {
6145    /// let mut conn = Connection::default().await?;
6146    /// conn.pipeline().gets(b"key");
6147    /// # Ok::<(), io::Error>(())
6148    /// # }).unwrap()
6149    /// ```
6150    pub fn gets(mut self, key: impl AsRef<[u8]>) -> Self {
6151        self.1
6152            .push(build_retrieval_cmd(b"gets", None, &[key.as_ref()]));
6153        self
6154    }
6155
6156    /// # Example
6157    ///
6158    /// ```
6159    /// use mcmc_rs::Connection;
6160    /// # use smol::{io, block_on};
6161    /// #
6162    /// # block_on(async {
6163    /// let mut conn = Connection::default().await?;
6164    /// conn.pipeline().gat(0, b"key");
6165    /// # Ok::<(), io::Error>(())
6166    /// # }).unwrap()
6167    /// ```
6168    pub fn gat(mut self, exptime: i64, key: impl AsRef<[u8]>) -> Self {
6169        self.1
6170            .push(build_retrieval_cmd(b"gat", Some(exptime), &[key.as_ref()]));
6171        self
6172    }
6173
6174    /// # Example
6175    ///
6176    /// ```
6177    /// use mcmc_rs::Connection;
6178    /// # use smol::{io, block_on};
6179    /// #
6180    /// # block_on(async {
6181    /// let mut conn = Connection::default().await?;
6182    /// conn.pipeline().gats(0, b"key");
6183    /// # Ok::<(), io::Error>(())
6184    /// # }).unwrap()
6185    /// ```
6186    pub fn gats(mut self, exptime: i64, key: impl AsRef<[u8]>) -> Self {
6187        self.1
6188            .push(build_retrieval_cmd(b"gats", Some(exptime), &[key.as_ref()]));
6189        self
6190    }
6191
6192    /// # Example
6193    ///
6194    /// ```
6195    /// use mcmc_rs::Connection;
6196    /// # use smol::{io, block_on};
6197    /// #
6198    /// # block_on(async {
6199    /// let mut conn = Connection::default().await?;
6200    /// conn.pipeline()
6201    ///     .get_multi(&[b"key".as_slice(), b"key2".as_slice()]);
6202    /// # Ok::<(), io::Error>(())
6203    /// # }).unwrap()
6204    /// ```
6205    pub fn get_multi(mut self, keys: &[impl AsRef<[u8]>]) -> Self {
6206        self.1.push(build_retrieval_cmd(
6207            b"get",
6208            None,
6209            &keys.iter().map(|x| x.as_ref()).collect::<Vec<&[u8]>>(),
6210        ));
6211        self
6212    }
6213
6214    /// # Example
6215    ///
6216    /// ```
6217    /// use mcmc_rs::Connection;
6218    /// # use smol::{io, block_on};
6219    /// #
6220    /// # block_on(async {
6221    /// let mut conn = Connection::default().await?;
6222    /// conn.pipeline()
6223    ///     .gets_multi(&[b"key".as_slice(), b"key2".as_slice()]);
6224    /// # Ok::<(), io::Error>(())
6225    /// # }).unwrap()
6226    /// ```
6227    pub fn gets_multi(mut self, keys: &[impl AsRef<[u8]>]) -> Self {
6228        self.1.push(build_retrieval_cmd(
6229            b"gets",
6230            None,
6231            &keys.iter().map(|x| x.as_ref()).collect::<Vec<&[u8]>>(),
6232        ));
6233        self
6234    }
6235
6236    /// # Example
6237    ///
6238    /// ```
6239    /// use mcmc_rs::Connection;
6240    /// # use smol::{io, block_on};
6241    /// #
6242    /// # block_on(async {
6243    /// let mut conn = Connection::default().await?;
6244    /// conn.pipeline()
6245    ///     .gat_multi(0, &[b"key".as_slice(), b"key2".as_slice()]);
6246    /// # Ok::<(), io::Error>(())
6247    /// # }).unwrap()
6248    /// ```
6249    pub fn gat_multi(mut self, exptime: i64, keys: &[impl AsRef<[u8]>]) -> Self {
6250        self.1.push(build_retrieval_cmd(
6251            b"gat",
6252            Some(exptime),
6253            &keys.iter().map(|x| x.as_ref()).collect::<Vec<&[u8]>>(),
6254        ));
6255        self
6256    }
6257
6258    /// # Example
6259    ///
6260    /// ```
6261    /// use mcmc_rs::Connection;
6262    /// # use smol::{io, block_on};
6263    /// #
6264    /// # block_on(async {
6265    /// let mut conn = Connection::default().await?;
6266    /// conn.pipeline()
6267    ///     .gats_multi(0, &[b"key".as_slice(), b"key2".as_slice()]);
6268    /// # Ok::<(), io::Error>(())
6269    /// # }).unwrap()
6270    /// ```
6271    pub fn gats_multi(mut self, exptime: i64, keys: &[impl AsRef<[u8]>]) -> Self {
6272        self.1.push(build_retrieval_cmd(
6273            b"gats",
6274            Some(exptime),
6275            &keys.iter().map(|x| x.as_ref()).collect::<Vec<&[u8]>>(),
6276        ));
6277        self
6278    }
6279
6280    /// # Example
6281    ///
6282    /// ```
6283    /// use mcmc_rs::Connection;
6284    /// # use smol::{io, block_on};
6285    /// #
6286    /// # block_on(async {
6287    /// let mut conn = Connection::default().await?;
6288    /// conn.pipeline().stats(None);
6289    /// # Ok::<(), io::Error>(())
6290    /// # }).unwrap()
6291    /// ```
6292    pub fn stats(mut self, arg: Option<StatsArg>) -> Self {
6293        self.1.push(build_stats_cmd(arg).to_vec());
6294        self
6295    }
6296
6297    /// # Example
6298    ///
6299    /// ```
6300    /// use mcmc_rs::{Connection, SlabsAutomoveArg};
6301    /// # use smol::{io, block_on};
6302    /// #
6303    /// # block_on(async {
6304    /// let mut conn = Connection::default().await?;
6305    /// conn.pipeline().slabs_automove(SlabsAutomoveArg::Zero);
6306    /// # Ok::<(), io::Error>(())
6307    /// # }).unwrap()
6308    /// ```
6309    pub fn slabs_automove(mut self, arg: SlabsAutomoveArg) -> Self {
6310        self.1.push(build_slabs_automove_cmd(arg).to_vec());
6311        self
6312    }
6313
6314    /// # Example
6315    ///
6316    /// ```
6317    /// use mcmc_rs::{Connection, LruCrawlerArg};
6318    /// # use smol::{io, block_on};
6319    /// #
6320    /// # block_on(async {
6321    /// let mut conn = Connection::default().await?;
6322    /// conn.pipeline().lru_crawler(LruCrawlerArg::Enable);
6323    /// # Ok::<(), io::Error>(())
6324    /// # }).unwrap()
6325    /// ```
6326    pub fn lru_crawler(mut self, arg: LruCrawlerArg) -> Self {
6327        self.1.push(build_lru_crawler_cmd(arg).to_vec());
6328        self
6329    }
6330
6331    /// # Example
6332    ///
6333    /// ```
6334    /// use mcmc_rs::Connection;
6335    /// # use smol::{io, block_on};
6336    /// #
6337    /// # block_on(async {
6338    /// let mut conn = Connection::default().await?;
6339    /// conn.pipeline().lru_crawler_sleep(0);
6340    /// # Ok::<(), io::Error>(())
6341    /// # }).unwrap()
6342    /// ```
6343    pub fn lru_crawler_sleep(mut self, microseconds: usize) -> Self {
6344        self.1.push(build_lru_clawler_sleep_cmd(microseconds));
6345        self
6346    }
6347
6348    /// # Example
6349    ///
6350    /// ```
6351    /// use mcmc_rs::Connection;
6352    /// # use smol::{io, block_on};
6353    /// #
6354    /// # block_on(async {
6355    /// let mut conn = Connection::default().await?;
6356    /// conn.pipeline().lru_crawler_tocrawl(0);
6357    /// # Ok::<(), io::Error>(())
6358    /// # }).unwrap()
6359    /// ```
6360    pub fn lru_crawler_tocrawl(mut self, arg: u32) -> Self {
6361        self.1.push(build_lru_crawler_tocrawl_cmd(arg));
6362        self
6363    }
6364
6365    /// # Example
6366    ///
6367    /// ```
6368    /// use mcmc_rs::{Connection, LruCrawlerCrawlArg};
6369    /// # use smol::{io, block_on};
6370    /// #
6371    /// # block_on(async {
6372    /// let mut conn = Connection::default().await?;
6373    /// conn.pipeline().lru_crawler_crawl(LruCrawlerCrawlArg::All);
6374    /// # Ok::<(), io::Error>(())
6375    /// # }).unwrap()
6376    /// ```
6377    pub fn lru_crawler_crawl(mut self, arg: LruCrawlerCrawlArg<'_>) -> Self {
6378        self.1.push(build_lru_clawler_crawl_cmd(arg));
6379        self
6380    }
6381
6382    /// # Example
6383    ///
6384    /// ```
6385    /// use mcmc_rs::Connection;
6386    /// # use smol::{io, block_on};
6387    /// #
6388    /// # block_on(async {
6389    /// let mut conn = Connection::default().await?;
6390    /// conn.pipeline().slabs_reassign(1, 2);
6391    /// # Ok::<(), io::Error>(())
6392    /// # }).unwrap()
6393    /// ```
6394    pub fn slabs_reassign(mut self, source_class: isize, dest_class: isize) -> Self {
6395        self.1
6396            .push(build_slabs_reassign_cmd(source_class, dest_class));
6397        self
6398    }
6399
6400    /// # Example
6401    ///
6402    /// ```
6403    /// use mcmc_rs::{Connection, LruCrawlerMetadumpArg};
6404    /// # use smol::{io, block_on};
6405    /// #
6406    /// # block_on(async {
6407    /// let mut conn = Connection::default().await?;
6408    /// conn.pipeline()
6409    ///     .lru_crawler_metadump(LruCrawlerMetadumpArg::All);
6410    /// # Ok::<(), io::Error>(())
6411    /// # }).unwrap()
6412    /// ```
6413    pub fn lru_crawler_metadump(mut self, arg: LruCrawlerMetadumpArg<'_>) -> Self {
6414        self.1.push(build_lru_clawler_metadump_cmd(arg));
6415        self
6416    }
6417
6418    /// # Example
6419    ///
6420    /// ```
6421    /// use mcmc_rs::{Connection, LruCrawlerMgdumpArg};
6422    /// # use smol::{io, block_on};
6423    /// #
6424    /// # block_on(async {
6425    /// let mut conn = Connection::default().await?;
6426    /// conn.pipeline().lru_crawler_mgdump(LruCrawlerMgdumpArg::All);
6427    /// # Ok::<(), io::Error>(())
6428    /// # }).unwrap()
6429    /// ```
6430    pub fn lru_crawler_mgdump(mut self, arg: LruCrawlerMgdumpArg<'_>) -> Self {
6431        self.1.push(build_lru_clawler_mgdump_cmd(arg));
6432        self
6433    }
6434
6435    /// # Example
6436    ///
6437    /// ```
6438    /// use mcmc_rs::Connection;
6439    /// # use smol::{io, block_on};
6440    /// #
6441    /// # block_on(async {
6442    /// let mut conn = Connection::default().await?;
6443    /// conn.pipeline().mn();
6444    /// # Ok::<(), io::Error>(())
6445    /// # }).unwrap()
6446    /// ```
6447    pub fn mn(mut self) -> Self {
6448        self.1.push(build_mn_cmd().to_vec());
6449        self
6450    }
6451
6452    /// # Example
6453    ///
6454    /// ```
6455    /// use mcmc_rs::Connection;
6456    /// # use smol::{io, block_on};
6457    /// #
6458    /// # block_on(async {
6459    /// let mut conn = Connection::default().await?;
6460    /// conn.pipeline().me(b"key");
6461    /// # Ok::<(), io::Error>(())
6462    /// # }).unwrap()
6463    /// ```
6464    pub fn me(mut self, key: impl AsRef<[u8]>) -> Self {
6465        self.1.push(build_me_cmd(key.as_ref()));
6466        self
6467    }
6468
6469    /// # Example
6470    ///
6471    /// ```
6472    /// use mcmc_rs::{Connection, MgFlag};
6473    /// # use smol::{io, block_on};
6474    /// #
6475    /// # block_on(async {
6476    /// let mut conn = Connection::default().await?;
6477    /// conn.pipeline().mg(b"key", &[MgFlag::Base64Key]);
6478    /// # Ok::<(), io::Error>(())
6479    /// # }).unwrap()
6480    /// ```
6481    pub fn mg(mut self, key: impl AsRef<[u8]>, flags: &[MgFlag]) -> Self {
6482        self.1.push(build_mc_cmd(
6483            b"mg",
6484            key.as_ref(),
6485            &build_mg_flags(flags),
6486            None,
6487        ));
6488        self
6489    }
6490
6491    /// # Example
6492    ///
6493    /// ```
6494    /// use mcmc_rs::{Connection, MsFlag};
6495    /// # use smol::{io, block_on};
6496    /// #
6497    /// # block_on(async {
6498    /// let mut conn = Connection::default().await?;
6499    /// conn.pipeline().ms(b"key", &[MsFlag::Base64Key], b"value");
6500    /// # Ok::<(), io::Error>(())
6501    /// # }).unwrap()
6502    /// ```
6503    pub fn ms(
6504        mut self,
6505        key: impl AsRef<[u8]>,
6506        flags: &[MsFlag],
6507        data_block: impl AsRef<[u8]>,
6508    ) -> Self {
6509        self.1.push(build_mc_cmd(
6510            b"ms",
6511            key.as_ref(),
6512            &build_ms_flags(flags),
6513            Some(data_block.as_ref()),
6514        ));
6515        self
6516    }
6517
6518    /// # Example
6519    ///
6520    /// ```
6521    /// use mcmc_rs::{Connection, MdFlag};
6522    /// # use smol::{io, block_on};
6523    /// #
6524    /// # block_on(async {
6525    /// let mut conn = Connection::default().await?;
6526    /// conn.pipeline().md(b"key", &[MdFlag::ReturnKey]);
6527    /// # Ok::<(), io::Error>(())
6528    /// # }).unwrap()
6529    /// ```
6530    pub fn md(mut self, key: impl AsRef<[u8]>, flags: &[MdFlag]) -> Self {
6531        self.1.push(build_mc_cmd(
6532            b"md",
6533            key.as_ref(),
6534            &build_md_flags(flags),
6535            None,
6536        ));
6537        self
6538    }
6539
6540    /// # Example
6541    ///
6542    /// ```
6543    /// use mcmc_rs::{Connection, MaFlag};
6544    /// # use smol::{io, block_on};
6545    /// #
6546    /// # block_on(async {
6547    /// let mut conn = Connection::default().await?;
6548    /// conn.pipeline().ma(b"key", &[MaFlag::Base64Key]);
6549    /// # Ok::<(), io::Error>(())
6550    /// # }).unwrap()
6551    /// ```
6552    pub fn ma(mut self, key: impl AsRef<[u8]>, flags: &[MaFlag]) -> Self {
6553        self.1.push(build_mc_cmd(
6554            b"ma",
6555            key.as_ref(),
6556            &build_ma_flags(flags),
6557            None,
6558        ));
6559        self
6560    }
6561
6562    /// # Example
6563    ///
6564    /// ```
6565    /// use mcmc_rs::{Connection, LruArg, LruMode};
6566    /// # use smol::{io, block_on};
6567    /// #
6568    /// # block_on(async {
6569    /// let mut conn = Connection::default().await?;
6570    /// conn.pipeline().lru(LruArg::Mode(LruMode::Flat));
6571    /// # Ok::<(), io::Error>(())
6572    /// # }).unwrap()
6573    /// ```
6574    pub fn lru(mut self, arg: LruArg) -> Self {
6575        self.1.push(build_lru_cmd(arg));
6576        self
6577    }
6578}
6579
6580#[cfg(test)]
6581mod tests {
6582    use super::*;
6583    use smol::block_on;
6584
6585    #[test]
6586    fn test_version() {
6587        block_on(async {
6588            let mut c = Cursor::new(b"version\r\nVERSION 1.2.3\r\n".to_vec());
6589            assert_eq!("1.2.3", version_cmd(&mut c).await.unwrap());
6590
6591            let mut c = Cursor::new(b"version\r\nERROR\r\n".to_vec());
6592            assert!(version_cmd(&mut c).await.is_err())
6593        })
6594    }
6595
6596    #[test]
6597    fn test_quit() {
6598        block_on(async {
6599            let mut c = Cursor::new(b"quit\r\n".to_vec());
6600            assert!(quit_cmd(&mut c).await.is_ok())
6601        })
6602    }
6603
6604    #[test]
6605    fn test_shutdown() {
6606        block_on(async {
6607            let mut c = Cursor::new(b"shutdown\r\n".to_vec());
6608            assert!(shutdown_cmd(&mut c, false).await.is_ok());
6609
6610            let mut c = Cursor::new(b"shutdown graceful\r\n".to_vec());
6611            assert!(shutdown_cmd(&mut c, true).await.is_ok())
6612        })
6613    }
6614
6615    #[test]
6616    fn test_cache_memlimit() {
6617        block_on(async {
6618            let mut c = Cursor::new(b"cache_memlimit 1\r\nOK\r\n".to_vec());
6619            assert!(cache_memlimit_cmd(&mut c, 1, false).await.is_ok());
6620
6621            let mut c = Cursor::new(b"cache_memlimit 1 noreply\r\n".to_vec());
6622            assert!(cache_memlimit_cmd(&mut c, 1, true).await.is_ok());
6623
6624            let mut c = Cursor::new(b"cache_memlimit 1\r\nERROR\r\n".to_vec());
6625            assert!(cache_memlimit_cmd(&mut c, 1, false).await.is_err());
6626        })
6627    }
6628
6629    #[test]
6630    fn test_flush_all() {
6631        block_on(async {
6632            let mut c = Cursor::new(b"flush_all\r\nOK\r\n".to_vec());
6633            assert!(flush_all_cmd(&mut c, None, false).await.is_ok());
6634
6635            let mut c = Cursor::new(b"flush_all 1 noreply\r\n".to_vec());
6636            assert!(flush_all_cmd(&mut c, Some(1), true).await.is_ok());
6637
6638            let mut c = Cursor::new(b"flush_all\r\nERROR\r\n".to_vec());
6639            assert!(flush_all_cmd(&mut c, None, false).await.is_err());
6640        })
6641    }
6642
6643    #[test]
6644    fn test_storage() {
6645        block_on(async {
6646            let mut c = Cursor::new(b"cas key 0 0 0 0\r\nvalue\r\nSTORED\r\n".to_vec());
6647            assert!(
6648                storage_cmd(&mut c, b"cas", b"key", 0, 0, Some(0), false, b"value")
6649                    .await
6650                    .unwrap()
6651            );
6652
6653            let mut c = Cursor::new(b"append key 0 0 0 noreply\r\nvalue\r\n".to_vec());
6654            assert!(
6655                storage_cmd(&mut c, b"append", b"key", 0, 0, None, true, b"value")
6656                    .await
6657                    .unwrap()
6658            );
6659
6660            let mut c = Cursor::new(b"prepend key 0 0 0\r\nvalue\r\nNOT_STORED\r\n".to_vec());
6661            assert!(
6662                !storage_cmd(&mut c, b"prepend", b"key", 0, 0, None, false, b"value")
6663                    .await
6664                    .unwrap()
6665            );
6666
6667            let mut c = Cursor::new(b"add key 0 0 0\r\nvalue\r\nERROR\r\n".to_vec());
6668            assert!(
6669                storage_cmd(&mut c, b"add", b"key", 0, 0, None, false, b"value")
6670                    .await
6671                    .is_err()
6672            )
6673        })
6674    }
6675
6676    #[test]
6677    fn test_delete() {
6678        block_on(async {
6679            let mut c = Cursor::new(b"delete key\r\nDELETED\r\n".to_vec());
6680            assert!(delete_cmd(&mut c, b"key", false).await.unwrap());
6681
6682            let mut c = Cursor::new(b"delete key\r\nNOT_FOUND\r\n".to_vec());
6683            assert!(!delete_cmd(&mut c, b"key", false).await.unwrap());
6684
6685            let mut c = Cursor::new(b"delete key noreply\r\n".to_vec());
6686            assert!(delete_cmd(&mut c, b"key", true).await.unwrap());
6687
6688            let mut c = Cursor::new(b"delete key\r\nERROR\r\n".to_vec());
6689            assert!(delete_cmd(&mut c, b"key", false).await.is_err());
6690        })
6691    }
6692
6693    #[test]
6694    fn test_auth() {
6695        block_on(async {
6696            let mut c = Cursor::new(b"set _ _ _ 3\r\na b\r\nSTORED\r\n".to_vec());
6697            assert!(auth_cmd(&mut c, b"a", b"b").await.is_ok());
6698
6699            let mut c = Cursor::new(b"set _ _ _ 3\r\na b\r\nERROR\r\n".to_vec());
6700            assert!(auth_cmd(&mut c, b"a", b"b").await.is_err());
6701        })
6702    }
6703
6704    #[test]
6705    fn test_incr_decr() {
6706        block_on(async {
6707            let mut c = Cursor::new(b"incr key 1\r\n2\r\n".to_vec());
6708            assert_eq!(
6709                incr_decr_cmd(&mut c, b"incr", b"key", 1, false)
6710                    .await
6711                    .unwrap(),
6712                Some(2)
6713            );
6714
6715            let mut c = Cursor::new(b"incr key 1 noreply\r\n".to_vec());
6716            assert!(
6717                incr_decr_cmd(&mut c, b"incr", b"key", 1, true)
6718                    .await
6719                    .unwrap()
6720                    .is_none(),
6721            );
6722
6723            let mut c = Cursor::new(b"incr key 1\r\nNOT_FOUND\r\n".to_vec());
6724            assert!(
6725                incr_decr_cmd(&mut c, b"incr", b"key", 1, false)
6726                    .await
6727                    .unwrap()
6728                    .is_none()
6729            );
6730
6731            let mut c = Cursor::new(b"incr key 1\r\nERROR\r\n".to_vec());
6732            assert!(
6733                incr_decr_cmd(&mut c, b"incr", b"key", 1, false)
6734                    .await
6735                    .is_err()
6736            );
6737        })
6738    }
6739
6740    #[test]
6741    fn test_touch() {
6742        block_on(async {
6743            let mut c = Cursor::new(b"touch key 0\r\nTOUCHED\r\n".to_vec());
6744            assert!(touch_cmd(&mut c, b"key", 0, false).await.unwrap());
6745
6746            let mut c = Cursor::new(b"touch key 0\r\nNOT_FOUND\r\n".to_vec());
6747            assert!(!touch_cmd(&mut c, b"key", 0, false).await.unwrap());
6748
6749            let mut c = Cursor::new(b"touch key 0 noreply\r\n".to_vec());
6750            assert!(touch_cmd(&mut c, b"key", 0, true).await.unwrap());
6751
6752            let mut c = Cursor::new(b"touch key 0\r\nERROR\r\n".to_vec());
6753            assert!(touch_cmd(&mut c, b"key", 0, false).await.is_err())
6754        })
6755    }
6756
6757    #[test]
6758    fn test_retrieval() {
6759        block_on(async {
6760            let mut c = Cursor::new(b"gets key\r\nEND\r\n".to_vec());
6761            assert_eq!(
6762                retrieval_cmd(&mut c, b"gets", None, &[b"key"])
6763                    .await
6764                    .unwrap(),
6765                vec![]
6766            );
6767
6768            let mut c = Cursor::new(b"gat 0 key\r\nVALUE key 0 1\r\na\r\nEND\r\n".to_vec());
6769            assert_eq!(
6770                retrieval_cmd(&mut c, b"gat", Some(0), &[b"key"])
6771                    .await
6772                    .unwrap(),
6773                vec![Item {
6774                    key: "key".to_string(),
6775                    flags: 0,
6776                    cas_unique: None,
6777                    data_block: b"a".to_vec(),
6778                }]
6779            );
6780
6781            let mut c = Cursor::new(
6782                b"gats 0 key key2\r\nVALUE key 0 1 0\r\na\r\nVALUE key2 0 1 0\r\na\r\nEND\r\n"
6783                    .to_vec(),
6784            );
6785            assert_eq!(
6786                retrieval_cmd(&mut c, b"gats", Some(0), &[b"key", b"key2"])
6787                    .await
6788                    .unwrap(),
6789                vec![
6790                    Item {
6791                        key: "key".to_string(),
6792                        flags: 0,
6793                        cas_unique: Some(0),
6794                        data_block: b"a".to_vec()
6795                    },
6796                    Item {
6797                        key: "key2".to_string(),
6798                        flags: 0,
6799                        cas_unique: Some(0),
6800                        data_block: b"a".to_vec()
6801                    }
6802                ]
6803            );
6804
6805            let mut c = Cursor::new(b"get key\r\nERROR\r\n".to_vec());
6806            assert!(
6807                retrieval_cmd(&mut c, b"get", None, &[b"key"])
6808                    .await
6809                    .is_err()
6810            )
6811        })
6812    }
6813
6814    #[test]
6815    fn test_stats() {
6816        block_on(async {
6817            let mut c =
6818                Cursor::new(b"stats\r\nSTAT version 1.2.3\r\nSTAT threads 4\r\nEND\r\n".to_vec());
6819            assert_eq!(
6820                stats_cmd(&mut c, None).await.unwrap(),
6821                HashMap::from([
6822                    ("version".to_string(), "1.2.3".to_string()),
6823                    ("threads".to_string(), "4".to_string()),
6824                ])
6825            );
6826
6827            let mut c = Cursor::new(b"stats settings\r\nERROR\r\n".to_vec());
6828            assert!(stats_cmd(&mut c, Some(StatsArg::Settings)).await.is_err());
6829
6830            let mut c = Cursor::new(b"stats items\r\nERROR\r\n".to_vec());
6831            assert!(stats_cmd(&mut c, Some(StatsArg::Items)).await.is_err());
6832
6833            let mut c = Cursor::new(b"stats sizes\r\nERROR\r\n".to_vec());
6834            assert!(stats_cmd(&mut c, Some(StatsArg::Sizes)).await.is_err());
6835
6836            let mut c = Cursor::new(b"stats slabs\r\nERROR\r\n".to_vec());
6837            assert!(stats_cmd(&mut c, Some(StatsArg::Slabs)).await.is_err());
6838
6839            let mut c = Cursor::new(b"stats conns\r\nERROR\r\n".to_vec());
6840            assert!(stats_cmd(&mut c, Some(StatsArg::Conns)).await.is_err())
6841        })
6842    }
6843
6844    #[test]
6845    fn test_slabs_automove() {
6846        block_on(async {
6847            let mut c = Cursor::new(b"slabs automove 0\r\nOK\r\n".to_vec());
6848            assert!(
6849                slabs_automove_cmd(&mut c, SlabsAutomoveArg::Zero)
6850                    .await
6851                    .is_ok()
6852            );
6853
6854            let mut c = Cursor::new(b"slabs automove 1\r\nERROR\r\n".to_vec());
6855            assert!(
6856                slabs_automove_cmd(&mut c, SlabsAutomoveArg::One)
6857                    .await
6858                    .is_err()
6859            );
6860
6861            let mut c = Cursor::new(b"slabs automove 2\r\nERROR\r\n".to_vec());
6862            assert!(
6863                slabs_automove_cmd(&mut c, SlabsAutomoveArg::Two)
6864                    .await
6865                    .is_err()
6866            )
6867        })
6868    }
6869
6870    #[test]
6871    fn test_lru_crawler() {
6872        block_on(async {
6873            let mut c = Cursor::new(b"lru_crawler enable\r\nOK\r\n".to_vec());
6874            assert!(lru_crawler_cmd(&mut c, LruCrawlerArg::Enable).await.is_ok());
6875
6876            let mut c = Cursor::new(b"lru_crawler disable\r\nERROR\r\n".to_vec());
6877            assert!(
6878                lru_crawler_cmd(&mut c, LruCrawlerArg::Disable)
6879                    .await
6880                    .is_err()
6881            )
6882        })
6883    }
6884
6885    #[test]
6886    fn test_lru_crawler_sleep() {
6887        block_on(async {
6888            let mut c = Cursor::new(b"lru_crawler sleep 1000000\r\nOK\r\n".to_vec());
6889            assert!(lru_crawler_sleep_cmd(&mut c, 1_000_000).await.is_ok());
6890
6891            let mut c = Cursor::new(b"lru_crawler sleep 0\r\nERROR\r\n".to_vec());
6892            assert!(lru_crawler_sleep_cmd(&mut c, 0).await.is_err())
6893        })
6894    }
6895
6896    #[test]
6897    fn test_lru_crawler_tocrawl() {
6898        block_on(async {
6899            let mut c = Cursor::new(b"lru_crawler tocrawl 0\r\nOK\r\n".to_vec());
6900            assert!(lru_crawler_tocrawl_cmd(&mut c, 0).await.is_ok());
6901
6902            let mut c = Cursor::new(b"lru_crawler tocrawl 0\r\nERROR\r\n".to_vec());
6903            assert!(lru_crawler_tocrawl_cmd(&mut c, 0).await.is_err())
6904        })
6905    }
6906
6907    #[test]
6908    fn test_lru_crawler_crawl() {
6909        block_on(async {
6910            let mut c = Cursor::new(b"lru_crawler crawl 1,2,3\r\nOK\r\n".to_vec());
6911            assert!(
6912                lru_crawler_crawl_cmd(&mut c, LruCrawlerCrawlArg::Classids(&[1, 2, 3]))
6913                    .await
6914                    .is_ok()
6915            );
6916
6917            let mut c = Cursor::new(b"lru_crawler crawl all\r\nERROR\r\n".to_vec());
6918            assert!(
6919                lru_crawler_crawl_cmd(&mut c, LruCrawlerCrawlArg::All)
6920                    .await
6921                    .is_err()
6922            )
6923        })
6924    }
6925
6926    #[test]
6927    fn test_slabs_reassign() {
6928        block_on(async {
6929            let mut c = Cursor::new(b"slabs reassign 1 10\r\nOK\r\n".to_vec());
6930            assert!(slabs_reassign_cmd(&mut c, 1, 10).await.is_ok());
6931
6932            let mut c = Cursor::new(b"slabs reassign 1 10\r\nERROR\r\n".to_vec());
6933            assert!(slabs_reassign_cmd(&mut c, 1, 10).await.is_err())
6934        })
6935    }
6936
6937    #[test]
6938    fn test_lru_crawler_metadump() {
6939        block_on(async {
6940            let mut c = Cursor::new(b"lru_crawler metadump all\r\nkey=key exp=-1 la=1745299782 cas=2 fetch=no cls=1 size=63 flags=0\r\nkey=key2 exp=-1 la=1745299782 cas=2 fetch=no cls=1 size=63 flags=0\r\nEND\r\n".to_vec());
6941            assert_eq!(
6942                lru_crawler_metadump_cmd(&mut c, LruCrawlerMetadumpArg::All)
6943                    .await
6944                    .unwrap(),
6945                [
6946                    "key=key exp=-1 la=1745299782 cas=2 fetch=no cls=1 size=63 flags=0",
6947                    "key=key2 exp=-1 la=1745299782 cas=2 fetch=no cls=1 size=63 flags=0"
6948                ]
6949            );
6950
6951            let mut c = Cursor::new(b"lru_crawler metadump 1,2,3\r\nERROR\r\n".to_vec());
6952            assert!(
6953                lru_crawler_metadump_cmd(&mut c, LruCrawlerMetadumpArg::Classids(&[1, 2, 3]))
6954                    .await
6955                    .is_err()
6956            );
6957
6958            let mut c = Cursor::new(b"lru_crawler metadump hash\r\nERROR\r\n".to_vec());
6959            assert!(
6960                lru_crawler_metadump_cmd(&mut c, LruCrawlerMetadumpArg::Hash)
6961                    .await
6962                    .is_err()
6963            )
6964        })
6965    }
6966
6967    #[test]
6968    fn test_lru_crawler_mgdump() {
6969        block_on(async {
6970            let mut c =
6971                Cursor::new(b"lru_crawler mgdump 1,2,3\r\nmg key\r\nmg key2\r\nEN\r\n".to_vec());
6972            assert_eq!(
6973                lru_crawler_mgdump_cmd(&mut c, LruCrawlerMgdumpArg::Classids(&[1, 2, 3]))
6974                    .await
6975                    .unwrap(),
6976                ["key", "key2"]
6977            );
6978
6979            let mut c = Cursor::new(b"lru_crawler mgdump all\r\nERROR\r\n".to_vec());
6980            assert!(
6981                lru_crawler_mgdump_cmd(&mut c, LruCrawlerMgdumpArg::All)
6982                    .await
6983                    .is_err()
6984            );
6985
6986            let mut c = Cursor::new(b"lru_crawler mgdump hash\r\nERROR\r\n".to_vec());
6987            assert!(
6988                lru_crawler_mgdump_cmd(&mut c, LruCrawlerMgdumpArg::Hash)
6989                    .await
6990                    .is_err()
6991            )
6992        })
6993    }
6994
6995    #[test]
6996    fn test_mn() {
6997        block_on(async {
6998            let mut c = Cursor::new(b"mn\r\nMN\r\n".to_vec());
6999            assert!(mn_cmd(&mut c).await.is_ok());
7000
7001            let mut c = Cursor::new(b"mn\r\nERROR\r\n".to_vec());
7002            assert!(mn_cmd(&mut c).await.is_err())
7003        })
7004    }
7005
7006    #[test]
7007    fn test_me() {
7008        block_on(async {
7009            let mut c = Cursor::new(b"me key\r\nEN\r\n".to_vec());
7010            assert!(me_cmd(&mut c, b"key").await.unwrap().is_none());
7011
7012            let mut c = Cursor::new(
7013                b"me key\r\nME key exp=-1 la=3 cas=2 fetch=no cls=1 size=63\r\n".to_vec(),
7014            );
7015            assert_eq!(
7016                me_cmd(&mut c, b"key").await.unwrap().unwrap(),
7017                "key exp=-1 la=3 cas=2 fetch=no cls=1 size=63"
7018            );
7019
7020            let mut c = Cursor::new(b"me key\r\nERROR\r\n".to_vec());
7021            assert!(me_cmd(&mut c, b"key").await.is_err());
7022        })
7023    }
7024
7025    #[test]
7026    fn test_pipeline() {
7027        block_on(async {
7028            let cmds = [
7029                b"version\r\n".to_vec(),
7030                b"quit\r\n".to_vec(),
7031                b"shutdown\r\n".to_vec(),
7032                b"cache_memlimit 1\r\n".to_vec(),
7033                b"cache_memlimit 1 noreply\r\n".to_vec(),
7034                b"flush_all\r\n".to_vec(),
7035                b"flush_all 1 noreply\r\n".to_vec(),
7036                b"cas key 0 0 5 0\r\nvalue\r\n".to_vec(),
7037                b"append key 0 0 5 noreply\r\nvalue\r\n".to_vec(),
7038                b"delete key\r\n".to_vec(),
7039                b"delete key noreply\r\n".to_vec(),
7040                b"set _ _ _ 3\r\na b\r\n".to_vec(),
7041                b"incr key 1\r\n".to_vec(),
7042                b"incr key 1 noreply\r\n".to_vec(),
7043                b"touch key 0\r\n".to_vec(),
7044                b"touch key 0 noreply\r\n".to_vec(),
7045                b"gets key\r\n".to_vec(),
7046                b"get key key2\r\n".to_vec(),
7047                b"gat 0 key key2\r\n".to_vec(),
7048                b"gats 0 key\r\n".to_vec(),
7049                b"stats\r\n".to_vec(),
7050                b"slabs automove 0\r\n".to_vec(),
7051                b"lru_crawler enable\r\n".to_vec(),
7052                b"lru_crawler disable\r\n".to_vec(),
7053                b"lru_crawler sleep 1000000\r\n".to_vec(),
7054                b"lru_crawler tocrawl 0\r\n".to_vec(),
7055                b"lru_crawler crawl 1,2,3\r\n".to_vec(),
7056                b"slabs reassign 1 10\r\n".to_vec(),
7057                b"lru_crawler metadump all\r\n".to_vec(),
7058                b"lru_crawler mgdump 3\r\n".to_vec(),
7059                b"mn\r\n".to_vec(),
7060                b"me key\r\n".to_vec(),
7061                b"mg 44OG44K544OI b c f h k l Oopaque s t u E0 N0 R0 T0 v\r\n".to_vec(),
7062                b"ms 44OG44K544OI 2 b c C0 E0 F0 I k Oopaque s T0 MS N0\r\nhi\r\n".to_vec(),
7063                b"md 44OG44K544OI b C0 E0 I k Oopaque T0 x\r\n".to_vec(),
7064                b"ma 44OG44K544OI b C0 E0 N0 J0 D0 T0 M+ Oopaque t c v k\r\n".to_vec(),
7065                b"lru mode flat\r\n".to_vec(),
7066            ];
7067            let rps = [
7068                b"VERSION 1.2.3\r\n".to_vec(),
7069                b"OK\r\n".to_vec(),
7070                b"OK\r\n".to_vec(),
7071                b"STORED\r\n".to_vec(),
7072                b"DELETED\r\n".to_vec(),
7073                b"STORED\r\n".to_vec(),
7074                b"2\r\n".to_vec(),
7075                b"TOUCHED\r\n".to_vec(),
7076                b"END\r\n".to_vec(),
7077                b"END\r\n".to_vec(),
7078                b"VALUE key 0 1 0\r\na\r\nVALUE key2 0 1 0\r\na\r\nEND\r\n".to_vec(),
7079                b"VALUE key 0 1 0\r\na\r\nEND\r\n".to_vec(),
7080                b"STAT version 1.2.3\r\nSTAT threads 4\r\nEND\r\n".to_vec(),
7081                b"OK\r\n".to_vec(),
7082                b"OK\r\n".to_vec(),
7083                b"OK\r\n".to_vec(),
7084                b"OK\r\n".to_vec(),
7085                b"OK\r\n".to_vec(),
7086                b"OK\r\n".to_vec(),
7087                b"OK\r\n".to_vec(),
7088                b"key=key exp=-1 la=1745299782 cas=2 fetch=no cls=1 size=63 flags=0\r\nkey=key2 exp=-1 la=1745299782 cas=2 fetch=no cls=1 size=63 flags=0\r\nEND\r\n".to_vec(),
7089                b"mg key\r\nmg key2\r\nEN\r\n".to_vec(),
7090                b"MN\r\n".to_vec(),
7091                b"ME key exp=-1 la=3 cas=2 fetch=no cls=1 size=63\r\n".to_vec(),
7092                b"VA 1 b c0 f0 h0 k44OG44K544OI l0 Oopaque s0 t0 W X Z\r\nA\r\n".to_vec(),
7093                b"HD b c0 k44OG44K544OI Oopaque s0\r\n".to_vec(),
7094                b"HD k44OG44K544OI Oopaque b\r\n".to_vec(),
7095                b"VA 2 Oopaque t0 c0 k44OG44K544OI b\r\n10\r\n".to_vec(),
7096                b"OK\r\n".to_vec(),
7097            ];
7098            let mut c = Cursor::new([cmds.concat(), rps.concat()].concat().to_vec());
7099            assert_eq!(
7100                execute_cmd(&mut c, &cmds).await.unwrap(),
7101                [
7102                    PipelineResponse::String("1.2.3".to_string()),
7103                    PipelineResponse::Unit(()),
7104                    PipelineResponse::Unit(()),
7105                    PipelineResponse::Unit(()),
7106                    PipelineResponse::Unit(()),
7107                    PipelineResponse::Unit(()),
7108                    PipelineResponse::Unit(()),
7109                    PipelineResponse::Bool(true),
7110                    PipelineResponse::Bool(true),
7111                    PipelineResponse::Bool(true),
7112                    PipelineResponse::Bool(true),
7113                    PipelineResponse::Unit(()),
7114                    PipelineResponse::Value(Some(2)),
7115                    PipelineResponse::Value(None),
7116                    PipelineResponse::Bool(true),
7117                    PipelineResponse::Bool(true),
7118                    PipelineResponse::OptionItem(None),
7119                    PipelineResponse::VecItem(Vec::new()),
7120                    PipelineResponse::VecItem(vec![
7121                        Item {
7122                            key: "key".to_string(),
7123                            flags: 0,
7124                            cas_unique: Some(0),
7125                            data_block: b"a".to_vec()
7126                        },
7127                        Item {
7128                            key: "key2".to_string(),
7129                            flags: 0,
7130                            cas_unique: Some(0),
7131                            data_block: b"a".to_vec()
7132                        }
7133                    ]),
7134                    PipelineResponse::OptionItem(Some(Item {
7135                        key: "key".to_string(),
7136                        flags: 0,
7137                        cas_unique: Some(0),
7138                        data_block: b"a".to_vec()
7139                    })),
7140                    PipelineResponse::HashMap(HashMap::from([
7141                        ("threads".to_string(), "4".to_string()),
7142                        ("version".to_string(), "1.2.3".to_string())
7143                    ])),
7144                    PipelineResponse::Unit(()),
7145                    PipelineResponse::Unit(()),
7146                    PipelineResponse::Unit(()),
7147                    PipelineResponse::Unit(()),
7148                    PipelineResponse::Unit(()),
7149                    PipelineResponse::Unit(()),
7150                    PipelineResponse::Unit(()),
7151                    PipelineResponse::VecString(vec![
7152                        "key=key exp=-1 la=1745299782 cas=2 fetch=no cls=1 size=63 flags=0"
7153                            .to_string(),
7154                        "key=key2 exp=-1 la=1745299782 cas=2 fetch=no cls=1 size=63 flags=0"
7155                            .to_string()
7156                    ]),
7157                    PipelineResponse::VecString(vec!["key".to_string(), "key2".to_string()]),
7158                    PipelineResponse::Unit(()),
7159                    PipelineResponse::OptionString(Some(
7160                        "key exp=-1 la=3 cas=2 fetch=no cls=1 size=63".to_string()
7161                    )),
7162                    PipelineResponse::MetaGet(MgItem {
7163                        success: true,
7164                        base64_key: true,
7165                        cas: Some(0),
7166                        flags: Some(0),
7167                        hit: Some(0),
7168                        key: Some("44OG44K544OI".to_string()),
7169                        last_access_ttl: Some(0),
7170                        opaque: Some("opaque".to_string()),
7171                        size: Some(0),
7172                        ttl: Some(0),
7173                        data_block: Some(b"A".to_vec()),
7174                        won_recache: true,
7175                        stale: true,
7176                        already_win: true
7177                    }),
7178                    PipelineResponse::MetaSet(MsItem {
7179                        success: true,
7180                        cas: Some(0),
7181                        key: Some("44OG44K544OI".to_string()),
7182                        opaque: Some("opaque".to_string()),
7183                        size: Some(0),
7184                        base64_key: true
7185                    }),
7186                    PipelineResponse::MetaDelete(MdItem {
7187                        success: true,
7188                        key: Some("44OG44K544OI".to_string()),
7189                        opaque: Some("opaque".to_string()),
7190                        base64_key: true
7191                    }),
7192                    PipelineResponse::MetaArithmetic(MaItem {
7193                        success: true,
7194                        opaque: Some("opaque".to_string()),
7195                        ttl: Some(0),
7196                        cas: Some(0),
7197                        number: Some(10),
7198                        key: Some("44OG44K544OI".to_string()),
7199                        base64_key: true
7200                    }),
7201                    PipelineResponse::Unit(()),
7202                ]
7203            );
7204
7205            let cmds = [b"version\r\n".to_vec(), b"quit\r\n".to_vec()];
7206            let rps = [b"ERROR\r\n".to_vec(), b"OK\r\n".to_vec()];
7207            let mut c = Cursor::new([cmds.concat(), rps.concat()].concat().to_vec());
7208            assert!(execute_cmd(&mut c, &cmds).await.is_err());
7209        })
7210    }
7211
7212    #[test]
7213    fn test_watch() {
7214        block_on(async {
7215            let mut c = Cursor::new(b"watch fetchers mutations evictions connevents proxyreqs proxyevents proxyuser deletions\r\nOK\r\n".to_vec());
7216            assert!(
7217                watch_cmd(
7218                    &mut c,
7219                    &[
7220                        WatchArg::Fetchers,
7221                        WatchArg::Mutations,
7222                        WatchArg::Evictions,
7223                        WatchArg::Connevents,
7224                        WatchArg::Proxyreqs,
7225                        WatchArg::Proxyevents,
7226                        WatchArg::Proxyuser,
7227                        WatchArg::Deletions
7228                    ]
7229                )
7230                .await
7231                .is_ok()
7232            );
7233
7234            let mut c = Cursor::new(b"watch fetchers mutations\r\nERROR\r\n".to_vec());
7235            assert!(
7236                watch_cmd(&mut c, &[WatchArg::Fetchers, WatchArg::Mutations])
7237                    .await
7238                    .is_err()
7239            );
7240        })
7241    }
7242
7243    #[test]
7244    fn test_mg() {
7245        block_on(async {
7246            let mut c = Cursor::new(b"mg key b\r\nEN b\r\n".to_vec());
7247            assert_eq!(
7248                mg_cmd(&mut c, b"key", &[MgFlag::Base64Key]).await.unwrap(),
7249                MgItem {
7250                    success: false,
7251                    base64_key: true,
7252                    cas: None,
7253                    flags: None,
7254                    hit: None,
7255                    key: None,
7256                    last_access_ttl: None,
7257                    opaque: None,
7258                    size: None,
7259                    ttl: None,
7260                    data_block: None,
7261                    already_win: false,
7262                    won_recache: false,
7263                    stale: false,
7264                }
7265            );
7266
7267            let mut c = Cursor::new(b"mg 44OG44K544OI b c C0 f h k l Oopaque s t u E0 N0 R0 T0\r\nHD b c0 f0 h0 k44OG44K544OI l0 Oopaque s0 t0 W X Z\r\n".to_vec());
7268            assert_eq!(
7269                mg_cmd(
7270                    &mut c,
7271                    b"44OG44K544OI",
7272                    &[
7273                        MgFlag::Base64Key,
7274                        MgFlag::ReturnCas,
7275                        MgFlag::CheckCas(0),
7276                        MgFlag::ReturnFlags,
7277                        MgFlag::ReturnHit,
7278                        MgFlag::ReturnKey,
7279                        MgFlag::ReturnLastAccess,
7280                        MgFlag::Opaque("opaque".to_string()),
7281                        MgFlag::ReturnSize,
7282                        MgFlag::ReturnTtl,
7283                        MgFlag::UnBump,
7284                        MgFlag::NewCas(0),
7285                        MgFlag::Autovivify(0),
7286                        MgFlag::RecacheTtl(0),
7287                        MgFlag::UpdateTtl(0),
7288                    ]
7289                )
7290                .await
7291                .unwrap(),
7292                MgItem {
7293                    success: true,
7294                    base64_key: true,
7295                    cas: Some(0),
7296                    flags: Some(0),
7297                    hit: Some(0),
7298                    key: Some("44OG44K544OI".to_string()),
7299                    last_access_ttl: Some(0),
7300                    opaque: Some("opaque".to_string()),
7301                    size: Some(0),
7302                    ttl: Some(0),
7303                    data_block: None,
7304                    already_win: true,
7305                    won_recache: true,
7306                    stale: true,
7307                }
7308            );
7309
7310            let mut c = Cursor::new(b"mg 44OG44K544OI b c C0 f h k l Oopaque s t u E0 N0 R0 T0 v\r\nVA 1 b c0 f0 h0 k44OG44K544OI l0 Oopaque s0 t0 W X Z\r\nA\r\n".to_vec());
7311            assert_eq!(
7312                mg_cmd(
7313                    &mut c,
7314                    b"44OG44K544OI",
7315                    &[
7316                        MgFlag::Base64Key,
7317                        MgFlag::ReturnCas,
7318                        MgFlag::CheckCas(0),
7319                        MgFlag::ReturnFlags,
7320                        MgFlag::ReturnHit,
7321                        MgFlag::ReturnKey,
7322                        MgFlag::ReturnLastAccess,
7323                        MgFlag::Opaque("opaque".to_string()),
7324                        MgFlag::ReturnSize,
7325                        MgFlag::ReturnTtl,
7326                        MgFlag::UnBump,
7327                        MgFlag::ReturnValue,
7328                        MgFlag::NewCas(0),
7329                        MgFlag::Autovivify(0),
7330                        MgFlag::RecacheTtl(0),
7331                        MgFlag::UpdateTtl(0),
7332                    ]
7333                )
7334                .await
7335                .unwrap(),
7336                MgItem {
7337                    success: true,
7338                    base64_key: true,
7339                    cas: Some(0),
7340                    flags: Some(0),
7341                    hit: Some(0),
7342                    key: Some("44OG44K544OI".to_string()),
7343                    last_access_ttl: Some(0),
7344                    opaque: Some("opaque".to_string()),
7345                    size: Some(0),
7346                    ttl: Some(0),
7347                    data_block: Some(b"A".to_vec()),
7348                    already_win: true,
7349                    won_recache: true,
7350                    stale: true,
7351                }
7352            );
7353
7354            let mut c = Cursor::new(
7355                b"mg 44OG44K544OI b c f h k l Oopaque s t u E0 N0 R0 T0 v\r\nERROR\r\n".to_vec(),
7356            );
7357            assert!(
7358                mg_cmd(
7359                    &mut c,
7360                    b"44OG44K544OI",
7361                    &[
7362                        MgFlag::Base64Key,
7363                        MgFlag::ReturnCas,
7364                        MgFlag::ReturnFlags,
7365                        MgFlag::ReturnHit,
7366                        MgFlag::ReturnKey,
7367                        MgFlag::ReturnLastAccess,
7368                        MgFlag::Opaque("opaque".to_string()),
7369                        MgFlag::ReturnSize,
7370                        MgFlag::ReturnTtl,
7371                        MgFlag::UnBump,
7372                        MgFlag::ReturnValue,
7373                        MgFlag::NewCas(0),
7374                        MgFlag::Autovivify(0),
7375                        MgFlag::RecacheTtl(0),
7376                        MgFlag::UpdateTtl(0),
7377                    ]
7378                )
7379                .await
7380                .is_err(),
7381            );
7382        })
7383    }
7384
7385    #[test]
7386    fn test_ms() {
7387        block_on(async {
7388            let mut c = Cursor::new(
7389                b"ms 44OG44K544OI 2 b c C0 E0 F0 I k Oopaque s T0 MP N0\r\nhi\r\nNF\r\n".to_vec(),
7390            );
7391            assert_eq!(
7392                ms_cmd(
7393                    &mut c,
7394                    b"44OG44K544OI",
7395                    &[
7396                        MsFlag::Base64Key,
7397                        MsFlag::ReturnCas,
7398                        MsFlag::CompareCas(0),
7399                        MsFlag::NewCas(0),
7400                        MsFlag::SetFlags(0),
7401                        MsFlag::Invalidate,
7402                        MsFlag::ReturnKey,
7403                        MsFlag::Opaque("opaque".to_string()),
7404                        MsFlag::ReturnSize,
7405                        MsFlag::Ttl(0),
7406                        MsFlag::Mode(MsMode::Prepend),
7407                        MsFlag::Autovivify(0)
7408                    ],
7409                    b"hi"
7410                )
7411                .await
7412                .unwrap(),
7413                MsItem {
7414                    success: false,
7415                    cas: None,
7416                    key: None,
7417                    opaque: None,
7418                    size: None,
7419                    base64_key: false
7420                }
7421            );
7422
7423            let mut c = Cursor::new(b"ms 44OG44K544OI 2 MR\r\nhi\r\nEX\r\n".to_vec());
7424            assert_eq!(
7425                ms_cmd(
7426                    &mut c,
7427                    b"44OG44K544OI",
7428                    &[MsFlag::Mode(MsMode::Replace)],
7429                    b"hi"
7430                )
7431                .await
7432                .unwrap(),
7433                MsItem {
7434                    success: false,
7435                    cas: None,
7436                    key: None,
7437                    opaque: None,
7438                    size: None,
7439                    base64_key: false
7440                }
7441            );
7442
7443            let mut c = Cursor::new(
7444                b"ms 44OG44K544OI 2 b c C0 E0 F0 I k Oopaque s T0 ME N0\r\nhi\r\nNS\r\n".to_vec(),
7445            );
7446            assert_eq!(
7447                ms_cmd(
7448                    &mut c,
7449                    b"44OG44K544OI",
7450                    &[
7451                        MsFlag::Base64Key,
7452                        MsFlag::ReturnCas,
7453                        MsFlag::CompareCas(0),
7454                        MsFlag::NewCas(0),
7455                        MsFlag::SetFlags(0),
7456                        MsFlag::Invalidate,
7457                        MsFlag::ReturnKey,
7458                        MsFlag::Opaque("opaque".to_string()),
7459                        MsFlag::ReturnSize,
7460                        MsFlag::Ttl(0),
7461                        MsFlag::Mode(MsMode::Add),
7462                        MsFlag::Autovivify(0)
7463                    ],
7464                    b"hi"
7465                )
7466                .await
7467                .unwrap(),
7468                MsItem {
7469                    success: false,
7470                    cas: None,
7471                    key: None,
7472                    opaque: None,
7473                    size: None,
7474                    base64_key: false
7475                }
7476            );
7477
7478            let mut c = Cursor::new(
7479                b"ms 44OG44K544OI 2 b c C0 E0 F0 I k Oopaque s T0 ME N0\r\nhi\r\nERROR\r\n"
7480                    .to_vec(),
7481            );
7482            assert!(
7483                ms_cmd(
7484                    &mut c,
7485                    b"44OG44K544OI",
7486                    &[
7487                        MsFlag::Base64Key,
7488                        MsFlag::ReturnCas,
7489                        MsFlag::CompareCas(0),
7490                        MsFlag::NewCas(0),
7491                        MsFlag::SetFlags(0),
7492                        MsFlag::Invalidate,
7493                        MsFlag::ReturnKey,
7494                        MsFlag::Opaque("opaque".to_string()),
7495                        MsFlag::ReturnSize,
7496                        MsFlag::Ttl(0),
7497                        MsFlag::Mode(MsMode::Append),
7498                        MsFlag::Autovivify(0)
7499                    ],
7500                    b"hi"
7501                )
7502                .await
7503                .is_err()
7504            );
7505
7506            let mut c = Cursor::new(
7507                b"ms 44OG44K544OI 2 b c C0 E0 F0 I k Oopaque s T0 MS N0\r\nhi\r\nHD b c0 k44OG44K544OI Oopaque s0\r\n".to_vec(),
7508            );
7509            assert_eq!(
7510                ms_cmd(
7511                    &mut c,
7512                    b"44OG44K544OI",
7513                    &[
7514                        MsFlag::Base64Key,
7515                        MsFlag::ReturnCas,
7516                        MsFlag::CompareCas(0),
7517                        MsFlag::NewCas(0),
7518                        MsFlag::SetFlags(0),
7519                        MsFlag::Invalidate,
7520                        MsFlag::ReturnKey,
7521                        MsFlag::Opaque("opaque".to_string()),
7522                        MsFlag::ReturnSize,
7523                        MsFlag::Ttl(0),
7524                        MsFlag::Mode(MsMode::Set),
7525                        MsFlag::Autovivify(0)
7526                    ],
7527                    b"hi"
7528                )
7529                .await
7530                .unwrap(),
7531                MsItem {
7532                    success: true,
7533                    cas: Some(0),
7534                    key: Some("44OG44K544OI".to_string()),
7535                    opaque: Some("opaque".to_string()),
7536                    size: Some(0),
7537                    base64_key: true
7538                }
7539            );
7540        })
7541    }
7542
7543    #[test]
7544    fn test_md() {
7545        block_on(async {
7546            let mut c = Cursor::new(b"md 44OG44K544OI b C0 E0 I k Oopaque T0 x\r\nNF\r\n".to_vec());
7547            assert_eq!(
7548                md_cmd(
7549                    &mut c,
7550                    b"44OG44K544OI",
7551                    &[
7552                        MdFlag::Base64Key,
7553                        MdFlag::CompareCas(0),
7554                        MdFlag::NewCas(0),
7555                        MdFlag::Invalidate,
7556                        MdFlag::ReturnKey,
7557                        MdFlag::Opaque("opaque".to_string()),
7558                        MdFlag::UpdateTtl(0),
7559                        MdFlag::LeaveKey,
7560                    ]
7561                )
7562                .await
7563                .unwrap(),
7564                MdItem {
7565                    success: false,
7566                    key: None,
7567                    opaque: None,
7568                    base64_key: false,
7569                }
7570            );
7571
7572            let mut c = Cursor::new(b"md 44OG44K544OI\r\nEX\r\n".to_vec());
7573            assert_eq!(
7574                md_cmd(&mut c, b"44OG44K544OI", &[]).await.unwrap(),
7575                MdItem {
7576                    success: false,
7577                    key: None,
7578                    opaque: None,
7579                    base64_key: false,
7580                }
7581            );
7582
7583            let mut c = Cursor::new(
7584                b"md 44OG44K544OI b C0 E0 I k Oopaque T0 x\r\nHD k44OG44K544OI Oopaque b\r\n"
7585                    .to_vec(),
7586            );
7587            assert_eq!(
7588                md_cmd(
7589                    &mut c,
7590                    b"44OG44K544OI",
7591                    &[
7592                        MdFlag::Base64Key,
7593                        MdFlag::CompareCas(0),
7594                        MdFlag::NewCas(0),
7595                        MdFlag::Invalidate,
7596                        MdFlag::ReturnKey,
7597                        MdFlag::Opaque("opaque".to_string()),
7598                        MdFlag::UpdateTtl(0),
7599                        MdFlag::LeaveKey,
7600                    ]
7601                )
7602                .await
7603                .unwrap(),
7604                MdItem {
7605                    success: true,
7606                    key: Some("44OG44K544OI".to_string()),
7607                    opaque: Some("opaque".to_string()),
7608                    base64_key: true
7609                }
7610            );
7611
7612            let mut c =
7613                Cursor::new(b"md 44OG44K544OI b C0 E0 I k Oopaque T0 x\r\nERROR\r\n".to_vec());
7614            assert!(
7615                md_cmd(
7616                    &mut c,
7617                    b"44OG44K544OI",
7618                    &[
7619                        MdFlag::Base64Key,
7620                        MdFlag::CompareCas(0),
7621                        MdFlag::NewCas(0),
7622                        MdFlag::Invalidate,
7623                        MdFlag::ReturnKey,
7624                        MdFlag::Opaque("opaque".to_string()),
7625                        MdFlag::UpdateTtl(0),
7626                        MdFlag::LeaveKey,
7627                    ]
7628                )
7629                .await
7630                .is_err(),
7631            )
7632        })
7633    }
7634
7635    #[test]
7636    fn test_ma() {
7637        block_on(async {
7638            let mut c = Cursor::new(
7639                b"ma 44OG44K544OI b C0 E0 N0 J0 D0 T0 M+ Oopaque t c v k\r\nNF\r\n".to_vec(),
7640            );
7641            assert_eq!(
7642                ma_cmd(
7643                    &mut c,
7644                    b"44OG44K544OI",
7645                    &[
7646                        MaFlag::Base64Key,
7647                        MaFlag::CompareCas(0),
7648                        MaFlag::NewCas(0),
7649                        MaFlag::AutoCreate(0),
7650                        MaFlag::InitValue(0),
7651                        MaFlag::DeltaApply(0),
7652                        MaFlag::UpdateTtl(0),
7653                        MaFlag::Mode(MaMode::Incr),
7654                        MaFlag::Opaque("opaque".to_string()),
7655                        MaFlag::ReturnTtl,
7656                        MaFlag::ReturnCas,
7657                        MaFlag::ReturnValue,
7658                        MaFlag::ReturnKey,
7659                    ],
7660                )
7661                .await
7662                .unwrap(),
7663                MaItem {
7664                    success: false,
7665                    opaque: None,
7666                    ttl: None,
7667                    cas: None,
7668                    number: None,
7669                    key: None,
7670                    base64_key: false,
7671                }
7672            );
7673
7674            let mut c = Cursor::new(
7675            b"ma 44OG44K544OI b C0 E0 N0 J0 D0 T0 M+ Oopaque t c v k\r\nNS Oopaque t0 c0 k44OG44K544OI b\r\n"
7676                .to_vec(),
7677        );
7678            assert_eq!(
7679                ma_cmd(
7680                    &mut c,
7681                    b"44OG44K544OI",
7682                    &[
7683                        MaFlag::Base64Key,
7684                        MaFlag::CompareCas(0),
7685                        MaFlag::NewCas(0),
7686                        MaFlag::AutoCreate(0),
7687                        MaFlag::InitValue(0),
7688                        MaFlag::DeltaApply(0),
7689                        MaFlag::UpdateTtl(0),
7690                        MaFlag::Mode(MaMode::Incr),
7691                        MaFlag::Opaque("opaque".to_string()),
7692                        MaFlag::ReturnTtl,
7693                        MaFlag::ReturnCas,
7694                        MaFlag::ReturnValue,
7695                        MaFlag::ReturnKey,
7696                    ],
7697                )
7698                .await
7699                .unwrap(),
7700                MaItem {
7701                    success: false,
7702                    opaque: Some("opaque".to_string()),
7703                    ttl: Some(0),
7704                    cas: Some(0),
7705                    number: None,
7706                    key: Some("44OG44K544OI".to_string()),
7707                    base64_key: true,
7708                }
7709            );
7710
7711            let mut c = Cursor::new(b"ma 44OG44K544OI\r\nEX\r\n".to_vec());
7712            assert_eq!(
7713                ma_cmd(&mut c, b"44OG44K544OI", &[],).await.unwrap(),
7714                MaItem {
7715                    success: false,
7716                    opaque: None,
7717                    ttl: None,
7718                    cas: None,
7719                    number: None,
7720                    key: None,
7721                    base64_key: false,
7722                }
7723            );
7724            let mut c = Cursor::new(b"ma 44OG44K544OI\r\nHD\r\n".to_vec());
7725            assert_eq!(
7726                ma_cmd(&mut c, b"44OG44K544OI", &[],).await.unwrap(),
7727                MaItem {
7728                    success: true,
7729                    opaque: None,
7730                    ttl: None,
7731                    cas: None,
7732                    number: None,
7733                    key: None,
7734                    base64_key: false,
7735                }
7736            );
7737
7738            let mut c = Cursor::new(
7739            b"ma 44OG44K544OI b C0 E0 N0 J0 D0 T0 M+ Oopaque t c v k\r\nVA 2 Oopaque t0 c0 k44OG44K544OI b\r\n10\r\n"
7740                .to_vec(),
7741        );
7742            assert_eq!(
7743                ma_cmd(
7744                    &mut c,
7745                    b"44OG44K544OI",
7746                    &[
7747                        MaFlag::Base64Key,
7748                        MaFlag::CompareCas(0),
7749                        MaFlag::NewCas(0),
7750                        MaFlag::AutoCreate(0),
7751                        MaFlag::InitValue(0),
7752                        MaFlag::DeltaApply(0),
7753                        MaFlag::UpdateTtl(0),
7754                        MaFlag::Mode(MaMode::Incr),
7755                        MaFlag::Opaque("opaque".to_string()),
7756                        MaFlag::ReturnTtl,
7757                        MaFlag::ReturnCas,
7758                        MaFlag::ReturnValue,
7759                        MaFlag::ReturnKey,
7760                    ],
7761                )
7762                .await
7763                .unwrap(),
7764                MaItem {
7765                    success: true,
7766                    opaque: Some("opaque".to_string()),
7767                    ttl: Some(0),
7768                    cas: Some(0),
7769                    number: Some(10),
7770                    key: Some("44OG44K544OI".to_string()),
7771                    base64_key: true,
7772                }
7773            );
7774
7775            let mut c = Cursor::new(
7776                b"ma 44OG44K544OI b C0 E0 N0 J0 D0 T0 M+ Oopaque t c v k\r\nERROR\r\n".to_vec(),
7777            );
7778            assert!(
7779                ma_cmd(
7780                    &mut c,
7781                    b"44OG44K544OI",
7782                    &[
7783                        MaFlag::Base64Key,
7784                        MaFlag::CompareCas(0),
7785                        MaFlag::NewCas(0),
7786                        MaFlag::AutoCreate(0),
7787                        MaFlag::InitValue(0),
7788                        MaFlag::DeltaApply(0),
7789                        MaFlag::UpdateTtl(0),
7790                        MaFlag::Mode(MaMode::Decr),
7791                        MaFlag::Opaque("opaque".to_string()),
7792                        MaFlag::ReturnTtl,
7793                        MaFlag::ReturnCas,
7794                        MaFlag::ReturnValue,
7795                        MaFlag::ReturnKey,
7796                    ],
7797                )
7798                .await
7799                .is_err()
7800            )
7801        })
7802    }
7803
7804    #[test]
7805    fn test_lru() {
7806        block_on(async {
7807            let mut c = Cursor::new(b"lru mode flat\r\nERROR\r\n".to_vec());
7808            assert!(lru_cmd(&mut c, LruArg::Mode(LruMode::Flat)).await.is_err());
7809
7810            let mut c = Cursor::new(b"lru mode segmented\r\nOK\r\n".to_vec());
7811            assert!(
7812                lru_cmd(&mut c, LruArg::Mode(LruMode::Segmented))
7813                    .await
7814                    .is_ok()
7815            );
7816
7817            let mut c = Cursor::new(b"lru tune 10 25 0.1 2\r\nOK\r\n".to_vec());
7818            assert!(
7819                lru_cmd(
7820                    &mut c,
7821                    LruArg::Tune {
7822                        percent_hot: 10,
7823                        percent_warm: 25,
7824                        max_hot_factor: 0.1,
7825                        max_warm_factor: 2.0
7826                    }
7827                )
7828                .await
7829                .is_ok()
7830            );
7831
7832            let mut c = Cursor::new(b"lru temp_ttl 0\r\nOK\r\n".to_vec());
7833            assert!(lru_cmd(&mut c, LruArg::TempTtl(0)).await.is_ok())
7834        })
7835    }
7836}