1+ //! Redis client CLI application. A simple command line interface to interact with a Redis server.
2+ //!
3+ //! The clients default to RESP2 unless HELLO 3 is explicitly sent.
4+ //! It can operate in two modes: interactive and single command mode.
5+ //! In interactive mode, the user can send commands to the server and get the response. It starts an REPL loop.
6+ //! In single command mode, the user can send a single command to the server and get the response.
7+ //! Both modes are blocking and synchronous.
8+
19use crate :: Connection ;
210use crate :: Frame ;
311use crate :: RedisError ;
412use crate :: Result ;
5- use crate :: cmd:: { Command , Ping } ;
13+ use crate :: cmd:: * ;
614use crate :: error:: wrap_error;
715use bytes:: Bytes ;
16+ use std:: str:: from_utf8;
817use tokio:: net:: { TcpStream , ToSocketAddrs } ;
918
1019/// Redis client implementation.
@@ -39,7 +48,7 @@ impl Client {
3948 ///
4049 /// # Arguments
4150 ///
42- /// * `msg` - An optional message to send to the server.
51+ /// * `msg` - An optional message to send to the server
4352 ///
4453 /// # Returns
4554 ///
@@ -53,11 +62,10 @@ impl Client {
5362 ///
5463 /// #[tokio::main]
5564 /// async fn main() {
56- /// let mut c = Client::connect("127.0.0.1:6379").await.unwrap();
57- ///
58- /// let resp = c.ping(Some("Hello Redis".to_string())).await.unwrap();
59- /// }
60- pub async fn ping ( & mut self , msg : Option < String > ) -> Result < String > {
65+ /// let mut client = Client::connect("127.0.0.1:6379").await.unwrap();
66+ /// let resp = client.ping(Some("Hello Redis".to_string())).await.unwrap();
67+ /// ```
68+ pub async fn ping ( & mut self , msg : Option < & str > ) -> Result < String > {
6169 let frame: Frame = Ping :: new ( msg) . into_stream ( ) ;
6270
6371 self . conn . write_frame ( & frame) . await ?;
@@ -71,14 +79,70 @@ impl Client {
7179 }
7280 }
7381
74- #[ allow( dead_code) ]
75- pub async fn get ( & self , _: & str ) -> Self {
76- unimplemented ! ( )
82+ /// Sends a GET command to the Redis server, with a key.
83+ ///
84+ /// # Arguments
85+ ///
86+ /// * `key` - A required key to send to the server
87+ ///
88+ /// # Returns
89+ ///
90+ /// * `Ok(Some(String))` if the key to GET exists
91+ /// * `Ok(None)` if the key to GET does not exist
92+ /// * `Err(RedisError)` if an error occurs
93+ ///
94+ /// # Examples
95+ ///
96+ /// ```ignore
97+ /// use async_redis::Client;
98+ ///
99+ /// #[tokio::main]
100+ /// async fn main() {
101+ /// let mut client = Client::connect("127.0.0.1:6379").await.unwrap();
102+ /// let resp = client.get("mykey").await?;
103+ /// ```
104+ pub async fn get ( & mut self , key : & str ) -> Result < Option < String > > {
105+ let frame: Frame = Get :: new ( key) . into_stream ( ) ;
106+
107+ self . conn . write_frame ( & frame) . await ?;
108+
109+ match self . read_response ( ) . await ? {
110+ Some ( data) => {
111+ let resp = String :: from_utf8 ( data. to_vec ( ) ) . unwrap ( ) ;
112+ Ok ( Some ( resp) )
113+ }
114+ // no error, but the key doesn't exist
115+ None => Ok ( None ) ,
116+ }
117+ }
118+
119+ // todo: the real SET command has some other options like EX, PX, NX, XX
120+ // we need to add these options to the SET command. Possibly with option pattern
121+ pub async fn set ( & mut self , key : & str , val : & str ) -> Result < Option < String > > {
122+ let frame: Frame = Set :: new ( key, val) . into_stream ( ) ;
123+
124+ self . conn . write_frame ( & frame) . await ?;
125+
126+ match self . read_response ( ) . await ? {
127+ Some ( data) => {
128+ let resp = String :: from_utf8 ( data. to_vec ( ) ) . unwrap ( ) ;
129+ Ok ( Some ( resp) )
130+ }
131+ // we shouldn't get here, if no key is deleted, we expect an 0
132+ None => Ok ( None ) ,
133+ }
77134 }
78135
79- #[ allow( dead_code) ]
80- pub async fn set ( & self , _: & str , _: String ) -> Self {
81- unimplemented ! ( )
136+ pub async fn del ( & mut self , keys : Vec < & str > ) -> Result < i64 > {
137+ let frame: Frame = Del :: new ( keys) . into_stream ( ) ;
138+
139+ self . conn . write_frame ( & frame) . await ?;
140+
141+ match self . read_response ( ) . await ? {
142+ Some ( data) => Ok ( from_utf8 ( & data) ?. parse :: < i64 > ( ) ?) ,
143+ // we shouldn't get here, we always expect a number from the server
144+ None => Err ( wrap_error ( RedisError :: Other ( "Unknown error" . into ( ) ) ) ) ,
145+ }
82146 }
83147
84148 /// Reads the response from the server. The response is a searilzied frame.
@@ -93,7 +157,9 @@ impl Client {
93157 match self . conn . read_frame ( ) . await ? {
94158 Some ( Frame :: SimpleString ( data) ) => Ok ( Some ( Bytes :: from ( data) ) ) ,
95159 Some ( Frame :: SimpleError ( data) ) => Err ( wrap_error ( RedisError :: Other ( data. into ( ) ) ) ) ,
160+ Some ( Frame :: Integer ( data) ) => Ok ( Some ( Bytes :: from ( data. to_string ( ) ) ) ) ,
96161 Some ( Frame :: BulkString ( data) ) => Ok ( Some ( data) ) ,
162+ Some ( Frame :: Null ) => Ok ( None ) ,
97163 Some ( _) => unimplemented ! ( ) ,
98164 None => Err ( wrap_error ( RedisError :: Other ( "Unknown error" . into ( ) ) ) ) ,
99165 }
0 commit comments