use std::io::{Cursor, Write};
use super::Error;
use crate::tuple::{ToTupleBuffer, Tuple};
use super::codec::IProtoType;
use super::{codec, SyncIndex};
pub trait Request {
const TYPE: IProtoType;
type Response: Sized;
fn encode_header(&self, out: &mut impl Write, sync: SyncIndex) -> Result<(), Error> {
codec::encode_header(out, sync, Self::TYPE)
}
fn encode_body(&self, out: &mut impl Write) -> Result<(), Error>;
fn encode(&self, out: &mut impl Write, sync: SyncIndex) -> Result<(), Error> {
self.encode_header(out, sync)?;
self.encode_body(out)?;
Ok(())
}
fn decode_body(&self, r#in: &mut Cursor<Vec<u8>>) -> Result<Self::Response, Error>;
}
pub struct Ping;
impl Request for Ping {
const TYPE: IProtoType = IProtoType::Ping;
type Response = ();
fn encode_body(&self, out: &mut impl Write) -> Result<(), Error> {
codec::encode_ping(out)
}
fn decode_body(&self, _in: &mut Cursor<Vec<u8>>) -> Result<Self::Response, Error> {
Ok(())
}
}
pub struct Call<'a, 'b, T: ?Sized> {
pub fn_name: &'a str,
pub args: &'b T,
}
impl<'a, 'b, T> Request for Call<'a, 'b, T>
where
T: ToTupleBuffer + ?Sized,
{
const TYPE: IProtoType = IProtoType::Call;
type Response = Tuple;
fn encode_body(&self, out: &mut impl Write) -> Result<(), Error> {
codec::encode_call(out, self.fn_name, self.args)
}
fn decode_body(&self, r#in: &mut Cursor<Vec<u8>>) -> Result<Self::Response, Error> {
codec::decode_call(r#in)
}
}
pub struct Eval<'a, 'b, T: ?Sized> {
pub expr: &'a str,
pub args: &'b T,
}
impl<'a, 'b, T> Request for Eval<'a, 'b, T>
where
T: ToTupleBuffer + ?Sized,
{
const TYPE: IProtoType = IProtoType::Eval;
type Response = Tuple;
fn encode_body(&self, out: &mut impl Write) -> Result<(), Error> {
codec::encode_eval(out, self.expr, self.args)
}
fn decode_body(&self, r#in: &mut Cursor<Vec<u8>>) -> Result<Self::Response, Error> {
codec::decode_call(r#in)
}
}
pub struct Execute<'a, 'b, T: ?Sized> {
pub sql: &'a str,
pub bind_params: &'b T,
pub limit: Option<usize>,
}
impl<'a, 'b, T> Request for Execute<'a, 'b, T>
where
T: ToTupleBuffer + ?Sized,
{
const TYPE: IProtoType = IProtoType::Execute;
type Response = Vec<Tuple>;
fn encode_body(&self, out: &mut impl Write) -> Result<(), Error> {
codec::encode_execute(out, self.sql, self.bind_params)
}
fn decode_body(&self, r#in: &mut Cursor<Vec<u8>>) -> Result<Self::Response, Error> {
codec::decode_multiple_rows(r#in, self.limit)
}
}
pub struct Auth<'u, 'p, 's> {
pub user: &'u str,
pub pass: &'p str,
pub salt: &'s [u8],
}
impl<'u, 'p, 's> Request for Auth<'u, 'p, 's> {
const TYPE: IProtoType = IProtoType::Auth;
type Response = ();
fn encode_body(&self, out: &mut impl Write) -> Result<(), Error> {
codec::encode_auth(out, self.user, self.pass, self.salt)
}
fn decode_body(&self, _in: &mut Cursor<Vec<u8>>) -> Result<Self::Response, Error> {
Ok(())
}
}