1use std::marker::Unpin;
6
7use futures_core::future::BoxFuture;
8use serde::{Deserialize, Serialize};
9use tokio::io::{AsyncRead, AsyncReadExt, AsyncWrite, AsyncWriteExt, ReadHalf, WriteHalf};
10
11use crate::command;
12use crate::resp3::{de, from_msg, ser_cmd, token, write_cmd, Reader, Value};
13
14#[derive(Debug)]
16pub struct Connection<T> {
17 transport: T,
18 sender: SendCtx,
19 receiver: ReceiveCtx,
20}
21
22#[derive(Debug)]
25pub struct ConnectionSendHalf<T> {
26 transport: WriteHalf<T>,
27 sender: SendCtx,
28}
29
30#[derive(Debug)]
33pub struct ConnectionReceiveHalf<T> {
34 transport: ReadHalf<T>,
35 receiver: ReceiveCtx,
36}
37
38#[derive(Debug)]
39struct SendCtx {
40 buf: Vec<u8>,
41 count: u64,
42}
43
44#[derive(Debug)]
45struct ReceiveCtx {
46 reader: Reader,
47 count: u64,
48}
49
50#[derive(Debug, thiserror::Error)]
52#[error(transparent)]
53pub struct Error(#[from] pub Box<ErrorKind>);
54
55#[derive(Debug, thiserror::Error)]
57pub enum ErrorKind {
58 #[error("io error")]
60 Io(#[from] std::io::Error),
61 #[error("tokenize error")]
63 Tokenize(#[from] token::Error),
64 #[error("serialize error")]
66 Serialize(#[from] ser_cmd::Error),
67 #[error("deserialize error")]
69 Deserialize(#[from] de::Error),
70 #[error("invalid message order")]
73 InvalidMessageOrder,
74}
75
76impl<T: AsyncRead + AsyncWrite + Unpin> Connection<T> {
77 pub async fn new(transport: T) -> Result<(Self, Value), Error> {
82 Self::with_args(transport, None, None, None).await
83 }
84
85 pub async fn with_args(
88 transport: T,
89 auth: Option<(&str, &str)>,
90 setname: Option<&str>,
91 select: Option<u32>,
92 ) -> Result<(Self, Value), Error> {
93 let mut chan = Connection {
94 transport,
95 sender: SendCtx {
96 buf: Vec::new(),
97 count: 0,
98 },
99 receiver: ReceiveCtx {
100 reader: Reader::new(),
101 count: 0,
102 },
103 };
104
105 let auth = auth.map(|(username, password)| ("AUTH", username, password));
106 let setname = setname.map(|clientname| ("SETNAME", clientname));
107 let resp = chan.raw_command(&("HELLO", 3, auth, setname)).await?;
108
109 if let Some(db) = select {
110 let serde::de::IgnoredAny = chan.raw_command(&("SELECT", db)).await?;
111 }
112
113 Ok((chan, resp))
114 }
115
116 pub async fn send<Req: Serialize>(&mut self, request: Req) -> Result<u64, Error> {
120 self.sender.send(&mut self.transport, request).await
121 }
122
123 pub async fn wait_response(&mut self) -> Result<Option<u64>, Error> {
133 self.receiver.wait_response(&mut self.transport).await
134 }
135
136 pub fn response(&self) -> Option<token::Message<'_>> {
138 self.receiver.response()
139 }
140
141 pub async fn raw_command<'de, Req: Serialize, Resp: Deserialize<'de>>(
149 &'de mut self,
150 request: Req,
151 ) -> Result<Resp, Error> {
152 let req_cnt = self.send(request).await?;
153
154 loop {
155 match self.wait_response().await? {
156 None => continue,
158 Some(cnt) if cnt < req_cnt => continue,
161 Some(cnt) if cnt > req_cnt => return Err(ErrorKind::InvalidMessageOrder.into()),
163 Some(_) => break,
165 }
166 }
167
168 Ok(from_msg(self.receiver.response().unwrap())?)
170 }
171
172 pub fn split(self) -> (ConnectionSendHalf<T>, ConnectionReceiveHalf<T>) {
175 let (read, write) = tokio::io::split(self.transport);
176 (
177 ConnectionSendHalf {
178 transport: write,
179 sender: self.sender,
180 },
181 ConnectionReceiveHalf {
182 transport: read,
183 receiver: self.receiver,
184 },
185 )
186 }
187}
188
189impl<T: AsyncRead + AsyncWrite + Send + Unpin> command::RawCommandMut for Connection<T> {
190 fn raw_command<'de, Req, Resp>(
191 &'de mut self,
192 request: Req,
193 ) -> BoxFuture<'de, Result<Resp, Error>>
194 where
195 Req: Serialize + Send + 'de,
196 Resp: Deserialize<'de> + 'de,
197 {
198 Box::pin(self.raw_command(request))
199 }
200}
201
202impl<T: AsyncWrite + Unpin> ConnectionSendHalf<T> {
203 pub async fn send<Req: Serialize>(&mut self, request: Req) -> Result<u64, Error> {
207 self.sender.send(&mut self.transport, request).await
208 }
209
210 pub fn is_pair_of(&self, other: &ConnectionReceiveHalf<T>) -> bool {
212 other.transport.is_pair_of(&self.transport)
213 }
214
215 pub fn unsplit(self, other: ConnectionReceiveHalf<T>) -> Connection<T> {
221 let transport = other.transport.unsplit(self.transport);
222
223 Connection {
224 transport,
225 sender: self.sender,
226 receiver: other.receiver,
227 }
228 }
229}
230
231impl<T: AsyncRead + Unpin> ConnectionReceiveHalf<T> {
232 pub async fn wait_response(&mut self) -> Result<Option<u64>, Error> {
242 self.receiver.wait_response(&mut self.transport).await
243 }
244
245 pub fn response(&self) -> Option<token::Message<'_>> {
247 self.receiver.response()
248 }
249}
250
251impl SendCtx {
252 async fn send<T, Req>(&mut self, transport: &mut T, request: Req) -> Result<u64, Error>
253 where
254 T: AsyncWrite + Unpin,
255 Req: Serialize,
256 {
257 let cmd = write_cmd(&mut self.buf, &request)?;
258 transport.write_all(cmd).await?;
259
260 self.count += 1;
261 Ok(self.count)
262 }
263}
264
265impl ReceiveCtx {
266 async fn wait_response<T>(&mut self, transport: &mut T) -> Result<Option<u64>, Error>
267 where
268 T: AsyncRead + Unpin,
269 {
270 while self.reader.message_not_ready()? {
271 transport.read_buf(self.reader.buf()).await?;
272 }
273
274 let msg = self.reader.message().unwrap();
276
277 let count = match msg.head() {
278 token::Token::Push(_) => None,
280 _ => {
281 self.count += 1;
282 Some(self.count)
283 }
284 };
285
286 Ok(count)
287 }
288
289 fn response(&self) -> Option<token::Message<'_>> {
290 self.reader.message()
291 }
292}
293
294impl From<ErrorKind> for Error {
295 fn from(err: ErrorKind) -> Self {
296 Self(Box::new(err))
297 }
298}
299
300impl From<std::io::Error> for Error {
301 fn from(err: std::io::Error) -> Self {
302 Self(Box::new(err.into()))
303 }
304}
305
306impl From<token::Error> for Error {
307 fn from(err: token::Error) -> Self {
308 Self(Box::new(err.into()))
309 }
310}
311
312impl From<ser_cmd::Error> for Error {
313 fn from(err: ser_cmd::Error) -> Self {
314 Self(Box::new(err.into()))
315 }
316}
317
318impl From<de::Error> for Error {
319 fn from(err: de::Error) -> Self {
320 Self(Box::new(err.into()))
321 }
322}