embedded_redis/commands/ping.rs
1//! Abstraction of PING command.
2//!
3//! For general information about this command, see the [Redis documentation](<https://redis.io/commands/ping/>).
4//!
5//! # Basic usage (client shorthand)
6//! Internally it is checked whether the server answers with PONG. If not, an error is returned.
7//! ```
8//!# use core::str::FromStr;
9//!# use core::net::SocketAddr;
10//!# use std_embedded_nal::Stack;
11//!# use std_embedded_time::StandardClock;
12//!# use embedded_redis::network::ConnectionHandler;
13//!#
14//! let mut stack = Stack::default();
15//! let clock = StandardClock::default();
16//!
17//! let mut connection_handler = ConnectionHandler::resp2(SocketAddr::from_str("127.0.0.1:6379").unwrap());
18//! let client = connection_handler.connect(&mut stack, Some(&clock)).unwrap();
19//!
20//! let response = client.ping().unwrap().wait().unwrap();
21//! ```
22//! # Verbose command
23//! Sending a `PingCommand` as alternative to client shorthand.
24//! ```
25//!# use core::str::FromStr;
26//!# use core::net::SocketAddr;
27//!# use std_embedded_nal::Stack;
28//!# use std_embedded_time::StandardClock;
29//!# use embedded_redis::commands::ping::PingCommand;
30//!# use embedded_redis::network::ConnectionHandler;
31//!#
32//!# let mut stack = Stack::default();
33//!# let clock = StandardClock::default();
34//!#
35//!# let mut connection_handler = ConnectionHandler::resp2(SocketAddr::from_str("127.0.0.1:6379").unwrap());
36//!# let client = connection_handler.connect(&mut stack, Some(&clock)).unwrap();
37//!#
38//! let command = PingCommand::new(None);
39//! let response = client.send(command).unwrap().wait().unwrap();
40//! ```
41//! # Custom argument
42//! Optionally, a user-defined argument can be specified.
43//!
44//! The abstraction compares the server's response with the argument and returns an error if there is no match.
45//! ```
46//!# use core::str::FromStr;
47//!# use core::net::SocketAddr;
48//!# use std_embedded_nal::Stack;
49//!# use std_embedded_time::StandardClock;
50//!# use embedded_redis::commands::ping::PingCommand;
51//!# use embedded_redis::network::ConnectionHandler;
52//!#
53//!# let mut stack = Stack::default();
54//!# let clock = StandardClock::default();
55//!#
56//!# let mut connection_handler = ConnectionHandler::resp2(SocketAddr::from_str("127.0.0.1:6379").unwrap());
57//!# let client = connection_handler.connect(&mut stack, Some(&clock)).unwrap();
58//!#
59//! let command = PingCommand::new(Some("hello world".into()));
60//! let response = client.send(command).unwrap().wait().unwrap();
61//! ```
62use crate::commands::auth::AuthCommand;
63use crate::commands::builder::{CommandBuilder, ToStringOption};
64use crate::commands::hello::HelloCommand;
65use crate::commands::{Command, ResponseTypeError};
66use crate::network::protocol::Protocol;
67use crate::network::{Client, CommandErrors, Future};
68use bytes::Bytes;
69use embedded_nal::TcpClientStack;
70use embedded_time::Clock;
71
72/// Abstraction for PING command
73pub struct PingCommand {
74 argument: Option<Bytes>,
75}
76
77impl PingCommand {
78 pub fn new(argument: Option<Bytes>) -> Self {
79 PingCommand { argument }
80 }
81}
82
83static PONG: Bytes = Bytes::from_static(b"PONG");
84
85impl<F> Command<F> for PingCommand
86where
87 F: From<CommandBuilder> + ToStringOption,
88{
89 type Response = ();
90
91 fn encode(&self) -> F {
92 CommandBuilder::new("PING").arg_option(self.argument.as_ref()).into()
93 }
94
95 fn eval_response(&self, frame: F) -> Result<Self::Response, ResponseTypeError> {
96 let response = frame.to_string_option().ok_or(ResponseTypeError {})?;
97 let pong = &PONG;
98 let expected = self.argument.as_ref().unwrap_or(pong);
99
100 if response.as_bytes() != expected.as_ref() {
101 return Err(ResponseTypeError {});
102 }
103
104 Ok(())
105 }
106}
107
108impl<'a, N: TcpClientStack, C: Clock, P: Protocol> Client<'a, N, C, P>
109where
110 AuthCommand: Command<<P as Protocol>::FrameType>,
111 HelloCommand: Command<<P as Protocol>::FrameType>,
112{
113 /// Shorthand for [PingCommand]
114 pub fn ping(&'a self) -> Result<Future<'a, N, C, P, PingCommand>, CommandErrors>
115 where
116 <P as Protocol>::FrameType: ToStringOption,
117 <P as Protocol>::FrameType: From<CommandBuilder>,
118 {
119 self.send(PingCommand::new(None))
120 }
121}