tiberius/tds/codec/
header.rsuse super::{Decode, Encode};
use crate::Error;
use bytes::{Buf, BufMut, BytesMut};
use std::convert::TryFrom;
uint_enum! {
#[repr(u8)]
pub enum PacketType {
SQLBatch = 1,
PreTDSv7Login = 2,
Rpc = 3,
TabularResult = 4,
AttentionSignal = 6,
BulkLoad = 7,
Fat = 8,
TransactionManagerReq = 14,
TDSv7Login = 16,
Sspi = 17,
PreLogin = 18,
}
}
uint_enum! {
#[repr(u8)]
pub enum PacketStatus {
NormalMessage = 0,
EndOfMessage = 1,
IgnoreEvent = 3,
ResetConnection = 0x08,
ResetConnectionSkipTran = 0x10,
}
}
#[derive(Debug, Clone, Copy)]
pub(crate) struct PacketHeader {
ty: PacketType,
status: PacketStatus,
length: u16,
spid: u16,
id: u8,
window: u8,
}
impl PacketHeader {
pub fn new(length: usize, id: u8) -> PacketHeader {
assert!(length <= u16::max_value() as usize);
PacketHeader {
ty: PacketType::TDSv7Login,
status: PacketStatus::ResetConnection,
length: length as u16,
spid: 0,
id,
window: 0,
}
}
pub fn rpc(id: u8) -> Self {
Self {
ty: PacketType::Rpc,
status: PacketStatus::NormalMessage,
..Self::new(0, id)
}
}
pub fn pre_login(id: u8) -> Self {
Self {
ty: PacketType::PreLogin,
status: PacketStatus::EndOfMessage,
..Self::new(0, id)
}
}
pub fn login(id: u8) -> Self {
Self {
ty: PacketType::TDSv7Login,
status: PacketStatus::EndOfMessage,
..Self::new(0, id)
}
}
pub fn batch(id: u8) -> Self {
Self {
ty: PacketType::SQLBatch,
status: PacketStatus::NormalMessage,
..Self::new(0, id)
}
}
pub fn bulk_load(id: u8) -> Self {
Self {
ty: PacketType::BulkLoad,
status: PacketStatus::NormalMessage,
..Self::new(0, id)
}
}
pub fn set_status(&mut self, status: PacketStatus) {
self.status = status;
}
pub fn set_type(&mut self, ty: PacketType) {
self.ty = ty;
}
pub fn status(&self) -> PacketStatus {
self.status
}
pub fn r#type(&self) -> PacketType {
self.ty
}
pub fn length(&self) -> u16 {
self.length
}
}
impl<B> Encode<B> for PacketHeader
where
B: BufMut,
{
fn encode(self, dst: &mut B) -> crate::Result<()> {
dst.put_u8(self.ty as u8);
dst.put_u8(self.status as u8);
dst.put_u16(self.length);
dst.put_u16(self.spid);
dst.put_u8(self.id);
dst.put_u8(self.window);
Ok(())
}
}
impl Decode<BytesMut> for PacketHeader {
fn decode(src: &mut BytesMut) -> crate::Result<Self>
where
Self: Sized,
{
let raw_ty = src.get_u8();
let ty = PacketType::try_from(raw_ty).map_err(|_| {
Error::Protocol(format!("header: invalid packet type: {}", raw_ty).into())
})?;
let status = PacketStatus::try_from(src.get_u8())
.map_err(|_| Error::Protocol("header: invalid packet status".into()))?;
let header = PacketHeader {
ty,
status,
length: src.get_u16(),
spid: src.get_u16(),
id: src.get_u8(),
window: src.get_u8(),
};
Ok(header)
}
}