use futures::{try_ready, Async, AsyncSink, Future, Poll, Sink};
use mysql_common::packets::RawPacket;
use crate::{consts::MAX_PAYLOAD_LEN, error::*, io::Stream};
pub struct WritePacket {
data: Option<RawPacket>,
stream: Option<Stream>,
seq_id: u8,
resulting_seq_id: u8,
}
pub fn new(stream: Stream, data: Vec<u8>, seq_id: u8) -> WritePacket {
let resulting_seq_id = seq_id.wrapping_add(1);
let mut resulting_seq_id =
resulting_seq_id.wrapping_add(((data.len() / MAX_PAYLOAD_LEN) % 256) as u8);
if !data.is_empty() && data.len() % MAX_PAYLOAD_LEN == 0 {
resulting_seq_id = resulting_seq_id.wrapping_add(1);
}
WritePacket {
data: Some(RawPacket(data)),
stream: Some(stream),
seq_id,
resulting_seq_id,
}
}
impl Future for WritePacket {
type Item = (Stream, u8);
type Error = Error;
fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
if let Some(data) = self.data.take() {
let send_result = self
.stream
.as_mut()
.unwrap()
.codec
.as_mut()
.unwrap()
.start_send((data, self.seq_id))?;
if let AsyncSink::NotReady(data) = send_result {
self.data = Some(data.0);
return Ok(Async::NotReady);
}
}
try_ready!(self
.stream
.as_mut()
.unwrap()
.codec
.as_mut()
.unwrap()
.poll_complete()
.map_err(Error::from));
Ok(Async::Ready((
self.stream.take().unwrap(),
self.resulting_seq_id,
)))
}
}