use bitflags::bitflags;
use either::Either;
use crate::io::Encode;
use crate::mssql::io::MssqlBufMutExt;
use crate::mssql::protocol::header::{AllHeaders, Header};
use crate::mssql::MssqlArguments;
pub(crate) struct RpcRequest<'a> {
pub(crate) transaction_descriptor: u64,
pub(crate) procedure: Either<&'a str, Procedure>,
pub(crate) options: OptionFlags,
pub(crate) arguments: &'a MssqlArguments,
}
#[derive(Debug, Copy, Clone)]
#[repr(u16)]
#[allow(dead_code)]
pub(crate) enum Procedure {
Cursor = 1,
CursorOpen = 2,
CursorPrepare = 3,
CursorExecute = 4,
CursorPrepareExecute = 5,
CursorUnprepare = 6,
CursorFetch = 7,
CursorOption = 8,
CursorClose = 9,
ExecuteSql = 10,
Prepare = 11,
Execute = 12,
PrepareExecute = 13,
PrepareExecuteRpc = 14,
Unprepare = 15,
}
bitflags! {
#[derive(Default, Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub(crate) struct OptionFlags: u16 {
const WITH_RECOMPILE = 1;
const NO_META_DATA = 2;
const REUSE_META_DATA = 4;
}
}
bitflags! {
#[derive(Default, Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub(crate) struct StatusFlags: u8 {
const BY_REF_VALUE = 1;
const DEFAULT_VALUE = 2;
const ENCRYPTED = 8;
}
}
impl Encode<'_> for RpcRequest<'_> {
fn encode_with(&self, buf: &mut Vec<u8>, _: ()) {
AllHeaders(&[Header::TransactionDescriptor {
outstanding_request_count: 1,
transaction_descriptor: self.transaction_descriptor,
}])
.encode(buf);
match &self.procedure {
Either::Left(name) => {
buf.extend(&(u16::try_from(name.len()).unwrap()).to_le_bytes());
buf.put_utf16_str(name);
}
Either::Right(id) => {
buf.extend(&(0xffff_u16).to_le_bytes());
buf.extend(&(*id as u16).to_le_bytes());
}
}
buf.extend(&self.options.bits().to_le_bytes());
buf.extend(&self.arguments.data);
}
}