1use bytes::{Buf, BufMut, Bytes};
33
34use crate::codec::{read_b_varchar, read_us_varchar};
35use crate::error::ProtocolError;
36use crate::prelude::*;
37use crate::types::TypeId;
38
39#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
41#[repr(u8)]
42#[non_exhaustive]
43pub enum TokenType {
44 ColMetaData = 0x81,
46 Error = 0xAA,
48 Info = 0xAB,
50 LoginAck = 0xAD,
52 Row = 0xD1,
54 NbcRow = 0xD2,
56 EnvChange = 0xE3,
58 Sspi = 0xED,
60 Done = 0xFD,
62 DoneInProc = 0xFF,
64 DoneProc = 0xFE,
66 ReturnStatus = 0x79,
68 ReturnValue = 0xAC,
70 Order = 0xA9,
72 FeatureExtAck = 0xAE,
74 SessionState = 0xE4,
76 FedAuthInfo = 0xEE,
78 ColInfo = 0xA5,
80 TabName = 0xA4,
82 Offset = 0x78,
84}
85
86impl TokenType {
87 pub fn from_u8(value: u8) -> Option<Self> {
89 match value {
90 0x81 => Some(Self::ColMetaData),
91 0xAA => Some(Self::Error),
92 0xAB => Some(Self::Info),
93 0xAD => Some(Self::LoginAck),
94 0xD1 => Some(Self::Row),
95 0xD2 => Some(Self::NbcRow),
96 0xE3 => Some(Self::EnvChange),
97 0xED => Some(Self::Sspi),
98 0xFD => Some(Self::Done),
99 0xFF => Some(Self::DoneInProc),
100 0xFE => Some(Self::DoneProc),
101 0x79 => Some(Self::ReturnStatus),
102 0xAC => Some(Self::ReturnValue),
103 0xA9 => Some(Self::Order),
104 0xAE => Some(Self::FeatureExtAck),
105 0xE4 => Some(Self::SessionState),
106 0xEE => Some(Self::FedAuthInfo),
107 0xA5 => Some(Self::ColInfo),
108 0xA4 => Some(Self::TabName),
109 0x78 => Some(Self::Offset),
110 _ => None,
111 }
112 }
113}
114
115#[derive(Debug, Clone)]
120#[non_exhaustive]
121pub enum Token {
122 ColMetaData(ColMetaData),
124 Row(RawRow),
126 NbcRow(NbcRow),
128 Done(Done),
130 DoneProc(DoneProc),
132 DoneInProc(DoneInProc),
134 ReturnStatus(i32),
136 ReturnValue(ReturnValue),
138 Error(ServerError),
140 Info(ServerInfo),
142 LoginAck(LoginAck),
144 EnvChange(EnvChange),
146 Order(Order),
148 FeatureExtAck(FeatureExtAck),
150 Sspi(SspiToken),
152 SessionState(SessionState),
154 FedAuthInfo(FedAuthInfo),
156}
157
158#[derive(Debug, Clone, Default)]
160pub struct ColMetaData {
161 pub columns: Vec<ColumnData>,
163 pub cek_table: Option<crate::crypto::CekTable>,
166}
167
168#[derive(Debug, Clone)]
170pub struct ColumnData {
171 pub name: String,
173 pub type_id: TypeId,
175 pub col_type: u8,
177 pub flags: u16,
179 pub user_type: u32,
181 pub type_info: TypeInfo,
183 pub crypto_metadata: Option<crate::crypto::CryptoMetadata>,
186}
187
188#[derive(Debug, Clone, Default)]
190pub struct TypeInfo {
191 pub max_length: Option<u32>,
193 pub precision: Option<u8>,
195 pub scale: Option<u8>,
197 pub collation: Option<Collation>,
199}
200
201#[derive(Debug, Clone, Copy, Default)]
224pub struct Collation {
225 pub lcid: u32,
233 pub sort_id: u8,
237}
238
239impl Collation {
240 pub fn from_bytes(bytes: &[u8; 5]) -> Self {
244 Self {
245 lcid: u32::from_le_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]),
246 sort_id: bytes[4],
247 }
248 }
249
250 pub fn to_bytes(&self) -> [u8; 5] {
254 let b = self.lcid.to_le_bytes();
255 [b[0], b[1], b[2], b[3], self.sort_id]
256 }
257
258 #[cfg(feature = "encoding")]
284 pub fn encoding(&self) -> Option<&'static encoding_rs::Encoding> {
285 crate::collation::encoding_for_lcid(self.lcid)
286 }
287
288 #[cfg(feature = "encoding")]
293 pub fn is_utf8(&self) -> bool {
294 crate::collation::is_utf8_collation(self.lcid)
295 }
296
297 #[cfg(feature = "encoding")]
305 pub fn code_page(&self) -> Option<u16> {
306 crate::collation::code_page_for_lcid(self.lcid)
307 }
308
309 #[cfg(feature = "encoding")]
313 pub fn encoding_name(&self) -> &'static str {
314 crate::collation::encoding_name_for_lcid(self.lcid)
315 }
316}
317
318#[derive(Debug, Clone)]
320pub struct RawRow {
321 pub data: bytes::Bytes,
323}
324
325#[derive(Debug, Clone)]
327pub struct NbcRow {
328 pub null_bitmap: Vec<u8>,
330 pub data: bytes::Bytes,
332}
333
334#[derive(Debug, Clone, Copy)]
336pub struct Done {
337 pub status: DoneStatus,
339 pub cur_cmd: u16,
341 pub row_count: u64,
343}
344
345#[derive(Debug, Clone, Copy, Default)]
347#[non_exhaustive]
348pub struct DoneStatus {
349 pub more: bool,
351 pub error: bool,
353 pub in_xact: bool,
355 pub count: bool,
357 pub attn: bool,
359 pub srverror: bool,
361}
362
363#[derive(Debug, Clone, Copy)]
365pub struct DoneInProc {
366 pub status: DoneStatus,
368 pub cur_cmd: u16,
370 pub row_count: u64,
372}
373
374#[derive(Debug, Clone, Copy)]
376pub struct DoneProc {
377 pub status: DoneStatus,
379 pub cur_cmd: u16,
381 pub row_count: u64,
383}
384
385#[derive(Debug, Clone)]
387#[non_exhaustive]
388pub struct ReturnValue {
389 pub param_ordinal: u16,
391 pub param_name: String,
393 pub status: u8,
395 pub user_type: u32,
397 pub flags: u16,
399 pub col_type: u8,
401 pub type_info: TypeInfo,
403 pub value: bytes::Bytes,
405}
406
407#[derive(Debug, Clone)]
409pub struct ServerError {
410 pub number: i32,
412 pub state: u8,
414 pub class: u8,
416 pub message: String,
418 pub server: String,
420 pub procedure: String,
422 pub line: i32,
424}
425
426#[derive(Debug, Clone)]
428pub struct ServerInfo {
429 pub number: i32,
431 pub state: u8,
433 pub class: u8,
435 pub message: String,
437 pub server: String,
439 pub procedure: String,
441 pub line: i32,
443}
444
445#[derive(Debug, Clone)]
447pub struct LoginAck {
448 pub interface: u8,
450 pub tds_version: u32,
452 pub prog_name: String,
454 pub prog_version: u32,
456}
457
458#[derive(Debug, Clone)]
460pub struct EnvChange {
461 pub env_type: EnvChangeType,
463 pub new_value: EnvChangeValue,
465 pub old_value: EnvChangeValue,
467}
468
469#[derive(Debug, Clone, Copy, PartialEq, Eq)]
471#[repr(u8)]
472#[non_exhaustive]
473pub enum EnvChangeType {
474 Database = 1,
476 Language = 2,
478 CharacterSet = 3,
480 PacketSize = 4,
482 UnicodeSortingLocalId = 5,
484 UnicodeComparisonFlags = 6,
486 SqlCollation = 7,
488 BeginTransaction = 8,
490 CommitTransaction = 9,
492 RollbackTransaction = 10,
494 EnlistDtcTransaction = 11,
496 DefectTransaction = 12,
498 RealTimeLogShipping = 13,
500 PromoteTransaction = 15,
502 TransactionManagerAddress = 16,
504 TransactionEnded = 17,
506 ResetConnectionCompletionAck = 18,
508 UserInstanceStarted = 19,
510 Routing = 20,
512}
513
514#[derive(Debug, Clone)]
516#[non_exhaustive]
517pub enum EnvChangeValue {
518 String(String),
520 Binary(bytes::Bytes),
522 Routing {
524 host: String,
526 port: u16,
528 },
529}
530
531#[derive(Debug, Clone)]
533pub struct Order {
534 pub columns: Vec<u16>,
536}
537
538#[derive(Debug, Clone)]
540pub struct FeatureExtAck {
541 pub features: Vec<FeatureAck>,
543}
544
545#[derive(Debug, Clone)]
547pub struct FeatureAck {
548 pub feature_id: u8,
550 pub data: bytes::Bytes,
552}
553
554#[derive(Debug, Clone)]
556pub struct SspiToken {
557 pub data: bytes::Bytes,
559}
560
561#[derive(Debug, Clone)]
563pub struct SessionState {
564 pub data: bytes::Bytes,
566}
567
568#[derive(Debug, Clone)]
570pub struct FedAuthInfo {
571 pub sts_url: String,
573 pub spn: String,
575}
576
577pub(crate) fn decode_collation(src: &mut impl Buf) -> Result<Collation, ProtocolError> {
585 if src.remaining() < 5 {
586 return Err(ProtocolError::UnexpectedEof);
587 }
588 let lcid = src.get_u32_le();
590 let sort_id = src.get_u8();
591 Ok(Collation { lcid, sort_id })
592}
593
594pub(crate) fn decode_type_info(
598 src: &mut impl Buf,
599 type_id: TypeId,
600 col_type: u8,
601) -> Result<TypeInfo, ProtocolError> {
602 match type_id {
603 TypeId::Null => Ok(TypeInfo::default()),
605 TypeId::Int1 | TypeId::Bit => Ok(TypeInfo::default()),
606 TypeId::Int2 => Ok(TypeInfo::default()),
607 TypeId::Int4 => Ok(TypeInfo::default()),
608 TypeId::Int8 => Ok(TypeInfo::default()),
609 TypeId::Float4 => Ok(TypeInfo::default()),
610 TypeId::Float8 => Ok(TypeInfo::default()),
611 TypeId::Money => Ok(TypeInfo::default()),
612 TypeId::Money4 => Ok(TypeInfo::default()),
613 TypeId::DateTime => Ok(TypeInfo::default()),
614 TypeId::DateTime4 => Ok(TypeInfo::default()),
615
616 TypeId::IntN | TypeId::BitN | TypeId::FloatN | TypeId::MoneyN | TypeId::DateTimeN => {
618 if src.remaining() < 1 {
619 return Err(ProtocolError::UnexpectedEof);
620 }
621 let max_length = src.get_u8() as u32;
622 Ok(TypeInfo {
623 max_length: Some(max_length),
624 ..Default::default()
625 })
626 }
627
628 TypeId::Guid => {
630 if src.remaining() < 1 {
631 return Err(ProtocolError::UnexpectedEof);
632 }
633 let max_length = src.get_u8() as u32;
634 Ok(TypeInfo {
635 max_length: Some(max_length),
636 ..Default::default()
637 })
638 }
639
640 TypeId::Decimal | TypeId::Numeric | TypeId::DecimalN | TypeId::NumericN => {
642 if src.remaining() < 3 {
643 return Err(ProtocolError::UnexpectedEof);
644 }
645 let max_length = src.get_u8() as u32;
646 let precision = src.get_u8();
647 let scale = src.get_u8();
648 Ok(TypeInfo {
649 max_length: Some(max_length),
650 precision: Some(precision),
651 scale: Some(scale),
652 ..Default::default()
653 })
654 }
655
656 TypeId::Char | TypeId::VarChar | TypeId::Binary | TypeId::VarBinary => {
658 if src.remaining() < 1 {
659 return Err(ProtocolError::UnexpectedEof);
660 }
661 let max_length = src.get_u8() as u32;
662 Ok(TypeInfo {
663 max_length: Some(max_length),
664 ..Default::default()
665 })
666 }
667
668 TypeId::BigVarChar | TypeId::BigChar => {
670 if src.remaining() < 7 {
671 return Err(ProtocolError::UnexpectedEof);
673 }
674 let max_length = src.get_u16_le() as u32;
675 let collation = decode_collation(src)?;
676 Ok(TypeInfo {
677 max_length: Some(max_length),
678 collation: Some(collation),
679 ..Default::default()
680 })
681 }
682
683 TypeId::BigVarBinary | TypeId::BigBinary => {
685 if src.remaining() < 2 {
686 return Err(ProtocolError::UnexpectedEof);
687 }
688 let max_length = src.get_u16_le() as u32;
689 Ok(TypeInfo {
690 max_length: Some(max_length),
691 ..Default::default()
692 })
693 }
694
695 TypeId::NChar | TypeId::NVarChar => {
697 if src.remaining() < 7 {
698 return Err(ProtocolError::UnexpectedEof);
700 }
701 let max_length = src.get_u16_le() as u32;
702 let collation = decode_collation(src)?;
703 Ok(TypeInfo {
704 max_length: Some(max_length),
705 collation: Some(collation),
706 ..Default::default()
707 })
708 }
709
710 TypeId::Date => Ok(TypeInfo::default()),
712
713 TypeId::Time | TypeId::DateTime2 | TypeId::DateTimeOffset => {
715 if src.remaining() < 1 {
716 return Err(ProtocolError::UnexpectedEof);
717 }
718 let scale = src.get_u8();
719 Ok(TypeInfo {
720 scale: Some(scale),
721 ..Default::default()
722 })
723 }
724
725 TypeId::Text | TypeId::NText | TypeId::Image => {
727 if src.remaining() < 4 {
729 return Err(ProtocolError::UnexpectedEof);
730 }
731 let max_length = src.get_u32_le();
732
733 let collation = if type_id == TypeId::Text || type_id == TypeId::NText {
735 if src.remaining() < 5 {
736 return Err(ProtocolError::UnexpectedEof);
737 }
738 Some(decode_collation(src)?)
739 } else {
740 None
741 };
742
743 if src.remaining() < 1 {
746 return Err(ProtocolError::UnexpectedEof);
747 }
748 let num_parts = src.get_u8();
749 for _ in 0..num_parts {
750 let _ = read_us_varchar(src).ok_or(ProtocolError::UnexpectedEof)?;
752 }
753
754 Ok(TypeInfo {
755 max_length: Some(max_length),
756 collation,
757 ..Default::default()
758 })
759 }
760
761 TypeId::Xml => {
763 if src.remaining() < 1 {
764 return Err(ProtocolError::UnexpectedEof);
765 }
766 let schema_present = src.get_u8();
767
768 if schema_present != 0 {
769 let _ = read_us_varchar(src).ok_or(ProtocolError::UnexpectedEof)?; let _ = read_us_varchar(src).ok_or(ProtocolError::UnexpectedEof)?; let _ = read_us_varchar(src).ok_or(ProtocolError::UnexpectedEof)?; }
774
775 Ok(TypeInfo::default())
776 }
777
778 TypeId::Udt => {
780 if src.remaining() < 2 {
782 return Err(ProtocolError::UnexpectedEof);
783 }
784 let max_length = src.get_u16_le() as u32;
785
786 let _ = read_us_varchar(src).ok_or(ProtocolError::UnexpectedEof)?; let _ = read_us_varchar(src).ok_or(ProtocolError::UnexpectedEof)?; let _ = read_us_varchar(src).ok_or(ProtocolError::UnexpectedEof)?; let _ = read_us_varchar(src).ok_or(ProtocolError::UnexpectedEof)?; Ok(TypeInfo {
793 max_length: Some(max_length),
794 ..Default::default()
795 })
796 }
797
798 TypeId::Tvp => {
800 Err(ProtocolError::InvalidTokenType(col_type))
803 }
804
805 TypeId::Variant => {
807 if src.remaining() < 4 {
808 return Err(ProtocolError::UnexpectedEof);
809 }
810 let max_length = src.get_u32_le();
811 Ok(TypeInfo {
812 max_length: Some(max_length),
813 ..Default::default()
814 })
815 }
816 }
817}
818
819impl ColMetaData {
820 pub const NO_METADATA: u16 = 0xFFFF;
822
823 pub fn decode(src: &mut impl Buf) -> Result<Self, ProtocolError> {
825 if src.remaining() < 2 {
826 return Err(ProtocolError::UnexpectedEof);
827 }
828
829 let column_count = src.get_u16_le();
830
831 if column_count == Self::NO_METADATA {
833 return Ok(Self {
834 columns: Vec::new(),
835 cek_table: None,
836 });
837 }
838
839 let mut columns = Vec::with_capacity(column_count as usize);
840
841 for _ in 0..column_count {
842 let column = Self::decode_column(src)?;
843 columns.push(column);
844 }
845
846 Ok(Self {
847 columns,
848 cek_table: None,
849 })
850 }
851
852 fn decode_column(src: &mut impl Buf) -> Result<ColumnData, ProtocolError> {
854 if src.remaining() < 7 {
856 return Err(ProtocolError::UnexpectedEof);
857 }
858
859 let user_type = src.get_u32_le();
860 let flags = src.get_u16_le();
861 let col_type = src.get_u8();
862
863 let type_id = TypeId::from_u8(col_type).unwrap_or(TypeId::Null); let type_info = decode_type_info(src, type_id, col_type)?;
867
868 let name = read_b_varchar(src).ok_or(ProtocolError::UnexpectedEof)?;
870
871 Ok(ColumnData {
872 name,
873 type_id,
874 col_type,
875 flags,
876 user_type,
877 type_info,
878 crypto_metadata: None,
879 })
880 }
881
882 pub fn decode_encrypted(src: &mut impl Buf) -> Result<Self, ProtocolError> {
895 if src.remaining() < 2 {
896 return Err(ProtocolError::UnexpectedEof);
897 }
898
899 let column_count = src.get_u16_le();
900
901 if column_count == Self::NO_METADATA {
902 return Ok(Self {
903 columns: Vec::new(),
904 cek_table: None,
905 });
906 }
907
908 let cek_table = crate::crypto::CekTable::decode(src)?;
910
911 let mut columns = Vec::with_capacity(column_count as usize);
912
913 for _ in 0..column_count {
914 let column = Self::decode_column_encrypted(src)?;
915 columns.push(column);
916 }
917
918 Ok(Self {
919 columns,
920 cek_table: Some(cek_table),
921 })
922 }
923
924 fn decode_column_encrypted(src: &mut impl Buf) -> Result<ColumnData, ProtocolError> {
928 if src.remaining() < 7 {
929 return Err(ProtocolError::UnexpectedEof);
930 }
931
932 let user_type = src.get_u32_le();
933 let flags = src.get_u16_le();
934 let col_type = src.get_u8();
935
936 let type_id = TypeId::from_u8(col_type).unwrap_or(TypeId::Null);
937
938 let type_info = decode_type_info(src, type_id, col_type)?;
940
941 let crypto_metadata = if crate::crypto::is_column_encrypted(flags) {
943 Some(crate::crypto::CryptoMetadata::decode(src)?)
944 } else {
945 None
946 };
947
948 let name = read_b_varchar(src).ok_or(ProtocolError::UnexpectedEof)?;
950
951 Ok(ColumnData {
952 name,
953 type_id,
954 col_type,
955 flags,
956 user_type,
957 type_info,
958 crypto_metadata,
959 })
960 }
961
962 #[must_use]
964 pub fn column_count(&self) -> usize {
965 self.columns.len()
966 }
967
968 #[must_use]
970 pub fn is_empty(&self) -> bool {
971 self.columns.is_empty()
972 }
973}
974
975impl ColumnData {
976 #[must_use]
978 pub fn is_nullable(&self) -> bool {
979 (self.flags & 0x0001) != 0
980 }
981
982 #[must_use]
986 pub fn fixed_size(&self) -> Option<usize> {
987 match self.type_id {
988 TypeId::Null => Some(0),
989 TypeId::Int1 | TypeId::Bit => Some(1),
990 TypeId::Int2 => Some(2),
991 TypeId::Int4 => Some(4),
992 TypeId::Int8 => Some(8),
993 TypeId::Float4 => Some(4),
994 TypeId::Float8 => Some(8),
995 TypeId::Money => Some(8),
996 TypeId::Money4 => Some(4),
997 TypeId::DateTime => Some(8),
998 TypeId::DateTime4 => Some(4),
999 TypeId::Date => Some(3),
1000 _ => None,
1001 }
1002 }
1003}
1004
1005impl RawRow {
1010 pub fn decode(src: &mut impl Buf, metadata: &ColMetaData) -> Result<Self, ProtocolError> {
1015 let mut data = bytes::BytesMut::new();
1016
1017 for col in &metadata.columns {
1018 Self::decode_column_value(src, col, &mut data)?;
1019 }
1020
1021 Ok(Self {
1022 data: data.freeze(),
1023 })
1024 }
1025
1026 fn decode_column_value(
1028 src: &mut impl Buf,
1029 col: &ColumnData,
1030 dst: &mut bytes::BytesMut,
1031 ) -> Result<(), ProtocolError> {
1032 match col.type_id {
1033 TypeId::Null => {
1035 }
1037 TypeId::Int1 | TypeId::Bit => {
1038 if src.remaining() < 1 {
1039 return Err(ProtocolError::UnexpectedEof);
1040 }
1041 dst.extend_from_slice(&[src.get_u8()]);
1042 }
1043 TypeId::Int2 => {
1044 if src.remaining() < 2 {
1045 return Err(ProtocolError::UnexpectedEof);
1046 }
1047 dst.extend_from_slice(&src.get_u16_le().to_le_bytes());
1048 }
1049 TypeId::Int4 => {
1050 if src.remaining() < 4 {
1051 return Err(ProtocolError::UnexpectedEof);
1052 }
1053 dst.extend_from_slice(&src.get_u32_le().to_le_bytes());
1054 }
1055 TypeId::Int8 => {
1056 if src.remaining() < 8 {
1057 return Err(ProtocolError::UnexpectedEof);
1058 }
1059 dst.extend_from_slice(&src.get_u64_le().to_le_bytes());
1060 }
1061 TypeId::Float4 => {
1062 if src.remaining() < 4 {
1063 return Err(ProtocolError::UnexpectedEof);
1064 }
1065 dst.extend_from_slice(&src.get_u32_le().to_le_bytes());
1066 }
1067 TypeId::Float8 => {
1068 if src.remaining() < 8 {
1069 return Err(ProtocolError::UnexpectedEof);
1070 }
1071 dst.extend_from_slice(&src.get_u64_le().to_le_bytes());
1072 }
1073 TypeId::Money => {
1074 if src.remaining() < 8 {
1075 return Err(ProtocolError::UnexpectedEof);
1076 }
1077 let hi = src.get_u32_le();
1078 let lo = src.get_u32_le();
1079 dst.extend_from_slice(&hi.to_le_bytes());
1080 dst.extend_from_slice(&lo.to_le_bytes());
1081 }
1082 TypeId::Money4 => {
1083 if src.remaining() < 4 {
1084 return Err(ProtocolError::UnexpectedEof);
1085 }
1086 dst.extend_from_slice(&src.get_u32_le().to_le_bytes());
1087 }
1088 TypeId::DateTime => {
1089 if src.remaining() < 8 {
1090 return Err(ProtocolError::UnexpectedEof);
1091 }
1092 let days = src.get_u32_le();
1093 let time = src.get_u32_le();
1094 dst.extend_from_slice(&days.to_le_bytes());
1095 dst.extend_from_slice(&time.to_le_bytes());
1096 }
1097 TypeId::DateTime4 => {
1098 if src.remaining() < 4 {
1099 return Err(ProtocolError::UnexpectedEof);
1100 }
1101 dst.extend_from_slice(&src.get_u32_le().to_le_bytes());
1102 }
1103 TypeId::Date => {
1105 Self::decode_bytelen_type(src, dst)?;
1106 }
1107
1108 TypeId::IntN | TypeId::BitN | TypeId::FloatN | TypeId::MoneyN | TypeId::DateTimeN => {
1110 Self::decode_bytelen_type(src, dst)?;
1111 }
1112
1113 TypeId::Guid => {
1114 Self::decode_bytelen_type(src, dst)?;
1115 }
1116
1117 TypeId::Decimal | TypeId::Numeric | TypeId::DecimalN | TypeId::NumericN => {
1118 Self::decode_bytelen_type(src, dst)?;
1119 }
1120
1121 TypeId::Char | TypeId::VarChar | TypeId::Binary | TypeId::VarBinary => {
1123 Self::decode_bytelen_type(src, dst)?;
1124 }
1125
1126 TypeId::BigVarChar | TypeId::BigVarBinary => {
1128 if col.type_info.max_length == Some(0xFFFF) {
1130 Self::decode_plp_type(src, dst)?;
1131 } else {
1132 Self::decode_ushortlen_type(src, dst)?;
1133 }
1134 }
1135
1136 TypeId::BigChar | TypeId::BigBinary => {
1138 Self::decode_ushortlen_type(src, dst)?;
1139 }
1140
1141 TypeId::NVarChar => {
1143 if col.type_info.max_length == Some(0xFFFF) {
1145 Self::decode_plp_type(src, dst)?;
1146 } else {
1147 Self::decode_ushortlen_type(src, dst)?;
1148 }
1149 }
1150
1151 TypeId::NChar => {
1153 Self::decode_ushortlen_type(src, dst)?;
1154 }
1155
1156 TypeId::Time | TypeId::DateTime2 | TypeId::DateTimeOffset => {
1158 Self::decode_bytelen_type(src, dst)?;
1159 }
1160
1161 TypeId::Text | TypeId::NText | TypeId::Image => {
1163 Self::decode_textptr_type(src, dst)?;
1164 }
1165
1166 TypeId::Xml => {
1168 Self::decode_plp_type(src, dst)?;
1169 }
1170
1171 TypeId::Variant => {
1173 Self::decode_intlen_type(src, dst)?;
1174 }
1175
1176 TypeId::Udt => {
1177 Self::decode_plp_type(src, dst)?;
1179 }
1180
1181 TypeId::Tvp => {
1182 return Err(ProtocolError::InvalidTokenType(col.col_type));
1184 }
1185 }
1186
1187 Ok(())
1188 }
1189
1190 fn decode_bytelen_type(
1192 src: &mut impl Buf,
1193 dst: &mut bytes::BytesMut,
1194 ) -> Result<(), ProtocolError> {
1195 if src.remaining() < 1 {
1196 return Err(ProtocolError::UnexpectedEof);
1197 }
1198 let len = src.get_u8() as usize;
1199 if len == 0xFF {
1200 dst.extend_from_slice(&[0xFF]);
1202 } else if len == 0 {
1203 dst.extend_from_slice(&[0x00]);
1205 } else {
1206 if src.remaining() < len {
1207 return Err(ProtocolError::UnexpectedEof);
1208 }
1209 dst.extend_from_slice(&[len as u8]);
1210 for _ in 0..len {
1211 dst.extend_from_slice(&[src.get_u8()]);
1212 }
1213 }
1214 Ok(())
1215 }
1216
1217 fn decode_ushortlen_type(
1219 src: &mut impl Buf,
1220 dst: &mut bytes::BytesMut,
1221 ) -> Result<(), ProtocolError> {
1222 if src.remaining() < 2 {
1223 return Err(ProtocolError::UnexpectedEof);
1224 }
1225 let len = src.get_u16_le() as usize;
1226 if len == 0xFFFF {
1227 dst.extend_from_slice(&0xFFFFu16.to_le_bytes());
1229 } else if len == 0 {
1230 dst.extend_from_slice(&0u16.to_le_bytes());
1232 } else {
1233 if src.remaining() < len {
1234 return Err(ProtocolError::UnexpectedEof);
1235 }
1236 dst.extend_from_slice(&(len as u16).to_le_bytes());
1237 for _ in 0..len {
1238 dst.extend_from_slice(&[src.get_u8()]);
1239 }
1240 }
1241 Ok(())
1242 }
1243
1244 fn decode_intlen_type(
1246 src: &mut impl Buf,
1247 dst: &mut bytes::BytesMut,
1248 ) -> Result<(), ProtocolError> {
1249 if src.remaining() < 4 {
1250 return Err(ProtocolError::UnexpectedEof);
1251 }
1252 let len = src.get_u32_le() as usize;
1253 if len == 0xFFFFFFFF {
1254 dst.extend_from_slice(&0xFFFFFFFFu32.to_le_bytes());
1256 } else if len == 0 {
1257 dst.extend_from_slice(&0u32.to_le_bytes());
1259 } else {
1260 if src.remaining() < len {
1261 return Err(ProtocolError::UnexpectedEof);
1262 }
1263 dst.extend_from_slice(&(len as u32).to_le_bytes());
1264 for _ in 0..len {
1265 dst.extend_from_slice(&[src.get_u8()]);
1266 }
1267 }
1268 Ok(())
1269 }
1270
1271 fn decode_textptr_type(
1286 src: &mut impl Buf,
1287 dst: &mut bytes::BytesMut,
1288 ) -> Result<(), ProtocolError> {
1289 if src.remaining() < 1 {
1290 return Err(ProtocolError::UnexpectedEof);
1291 }
1292
1293 let textptr_len = src.get_u8() as usize;
1294
1295 if textptr_len == 0 {
1296 dst.extend_from_slice(&0xFFFFFFFFFFFFFFFFu64.to_le_bytes());
1298 return Ok(());
1299 }
1300
1301 if src.remaining() < textptr_len {
1303 return Err(ProtocolError::UnexpectedEof);
1304 }
1305 src.advance(textptr_len);
1306
1307 if src.remaining() < 8 {
1309 return Err(ProtocolError::UnexpectedEof);
1310 }
1311 src.advance(8);
1312
1313 if src.remaining() < 4 {
1315 return Err(ProtocolError::UnexpectedEof);
1316 }
1317 let data_len = src.get_u32_le() as usize;
1318
1319 if src.remaining() < data_len {
1320 return Err(ProtocolError::UnexpectedEof);
1321 }
1322
1323 dst.extend_from_slice(&(data_len as u64).to_le_bytes());
1329 dst.extend_from_slice(&(data_len as u32).to_le_bytes());
1330 for _ in 0..data_len {
1331 dst.extend_from_slice(&[src.get_u8()]);
1332 }
1333 dst.extend_from_slice(&0u32.to_le_bytes()); Ok(())
1336 }
1337
1338 fn decode_plp_type(src: &mut impl Buf, dst: &mut bytes::BytesMut) -> Result<(), ProtocolError> {
1344 if src.remaining() < 8 {
1345 return Err(ProtocolError::UnexpectedEof);
1346 }
1347
1348 let total_len = src.get_u64_le();
1349
1350 dst.extend_from_slice(&total_len.to_le_bytes());
1352
1353 if total_len == 0xFFFFFFFFFFFFFFFF {
1354 return Ok(());
1356 }
1357
1358 loop {
1360 if src.remaining() < 4 {
1361 return Err(ProtocolError::UnexpectedEof);
1362 }
1363 let chunk_len = src.get_u32_le() as usize;
1364 dst.extend_from_slice(&(chunk_len as u32).to_le_bytes());
1365
1366 if chunk_len == 0 {
1367 break;
1369 }
1370
1371 if src.remaining() < chunk_len {
1372 return Err(ProtocolError::UnexpectedEof);
1373 }
1374
1375 for _ in 0..chunk_len {
1376 dst.extend_from_slice(&[src.get_u8()]);
1377 }
1378 }
1379
1380 Ok(())
1381 }
1382}
1383
1384impl NbcRow {
1389 pub fn decode(src: &mut impl Buf, metadata: &ColMetaData) -> Result<Self, ProtocolError> {
1394 let col_count = metadata.columns.len();
1395 let bitmap_len = col_count.div_ceil(8);
1396
1397 if src.remaining() < bitmap_len {
1398 return Err(ProtocolError::UnexpectedEof);
1399 }
1400
1401 let mut null_bitmap = vec![0u8; bitmap_len];
1403 for byte in &mut null_bitmap {
1404 *byte = src.get_u8();
1405 }
1406
1407 let mut data = bytes::BytesMut::new();
1409
1410 for (i, col) in metadata.columns.iter().enumerate() {
1411 let byte_idx = i / 8;
1412 let bit_idx = i % 8;
1413 let is_null = (null_bitmap[byte_idx] & (1 << bit_idx)) != 0;
1414
1415 if !is_null {
1416 RawRow::decode_column_value(src, col, &mut data)?;
1419 }
1420 }
1421
1422 Ok(Self {
1423 null_bitmap,
1424 data: data.freeze(),
1425 })
1426 }
1427
1428 #[must_use]
1430 pub fn is_null(&self, column_index: usize) -> bool {
1431 let byte_idx = column_index / 8;
1432 let bit_idx = column_index % 8;
1433 if byte_idx < self.null_bitmap.len() {
1434 (self.null_bitmap[byte_idx] & (1 << bit_idx)) != 0
1435 } else {
1436 true }
1438 }
1439}
1440
1441impl ReturnValue {
1446 pub fn decode(src: &mut impl Buf) -> Result<Self, ProtocolError> {
1448 if src.remaining() < 2 {
1455 return Err(ProtocolError::UnexpectedEof);
1456 }
1457 let param_ordinal = src.get_u16_le();
1458
1459 let param_name = read_b_varchar(src).ok_or(ProtocolError::UnexpectedEof)?;
1461
1462 if src.remaining() < 1 {
1464 return Err(ProtocolError::UnexpectedEof);
1465 }
1466 let status = src.get_u8();
1467
1468 if src.remaining() < 7 {
1470 return Err(ProtocolError::UnexpectedEof);
1471 }
1472 let user_type = src.get_u32_le();
1473 let flags = src.get_u16_le();
1474 let col_type = src.get_u8();
1475
1476 let type_id = TypeId::from_u8(col_type).unwrap_or(TypeId::Null);
1477
1478 let type_info = decode_type_info(src, type_id, col_type)?;
1480
1481 let mut value_buf = bytes::BytesMut::new();
1483
1484 let temp_col = ColumnData {
1486 name: String::new(),
1487 type_id,
1488 col_type,
1489 flags,
1490 user_type,
1491 type_info: type_info.clone(),
1492 crypto_metadata: None,
1493 };
1494
1495 RawRow::decode_column_value(src, &temp_col, &mut value_buf)?;
1496
1497 Ok(Self {
1498 param_ordinal,
1499 param_name,
1500 status,
1501 user_type,
1502 flags,
1503 col_type,
1504 type_info,
1505 value: value_buf.freeze(),
1506 })
1507 }
1508}
1509
1510impl SessionState {
1515 pub fn decode(src: &mut impl Buf) -> Result<Self, ProtocolError> {
1517 if src.remaining() < 4 {
1518 return Err(ProtocolError::UnexpectedEof);
1519 }
1520
1521 let length = src.get_u32_le() as usize;
1522
1523 if src.remaining() < length {
1524 return Err(ProtocolError::IncompletePacket {
1525 expected: length,
1526 actual: src.remaining(),
1527 });
1528 }
1529
1530 let data = src.copy_to_bytes(length);
1531
1532 Ok(Self { data })
1533 }
1534}
1535
1536mod done_status_bits {
1542 pub const DONE_MORE: u16 = 0x0001;
1543 pub const DONE_ERROR: u16 = 0x0002;
1544 pub const DONE_INXACT: u16 = 0x0004;
1545 pub const DONE_COUNT: u16 = 0x0010;
1546 pub const DONE_ATTN: u16 = 0x0020;
1547 pub const DONE_SRVERROR: u16 = 0x0100;
1548}
1549
1550impl DoneStatus {
1551 #[must_use]
1553 pub fn from_bits(bits: u16) -> Self {
1554 use done_status_bits::*;
1555 Self {
1556 more: (bits & DONE_MORE) != 0,
1557 error: (bits & DONE_ERROR) != 0,
1558 in_xact: (bits & DONE_INXACT) != 0,
1559 count: (bits & DONE_COUNT) != 0,
1560 attn: (bits & DONE_ATTN) != 0,
1561 srverror: (bits & DONE_SRVERROR) != 0,
1562 }
1563 }
1564
1565 #[must_use]
1567 pub fn to_bits(&self) -> u16 {
1568 use done_status_bits::*;
1569 let mut bits = 0u16;
1570 if self.more {
1571 bits |= DONE_MORE;
1572 }
1573 if self.error {
1574 bits |= DONE_ERROR;
1575 }
1576 if self.in_xact {
1577 bits |= DONE_INXACT;
1578 }
1579 if self.count {
1580 bits |= DONE_COUNT;
1581 }
1582 if self.attn {
1583 bits |= DONE_ATTN;
1584 }
1585 if self.srverror {
1586 bits |= DONE_SRVERROR;
1587 }
1588 bits
1589 }
1590}
1591
1592impl Done {
1593 pub const SIZE: usize = 12; pub fn decode(src: &mut impl Buf) -> Result<Self, ProtocolError> {
1598 if src.remaining() < Self::SIZE {
1599 return Err(ProtocolError::IncompletePacket {
1600 expected: Self::SIZE,
1601 actual: src.remaining(),
1602 });
1603 }
1604
1605 let status = DoneStatus::from_bits(src.get_u16_le());
1606 let cur_cmd = src.get_u16_le();
1607 let row_count = src.get_u64_le();
1608
1609 Ok(Self {
1610 status,
1611 cur_cmd,
1612 row_count,
1613 })
1614 }
1615
1616 pub fn encode(&self, dst: &mut impl BufMut) {
1618 dst.put_u8(TokenType::Done as u8);
1619 dst.put_u16_le(self.status.to_bits());
1620 dst.put_u16_le(self.cur_cmd);
1621 dst.put_u64_le(self.row_count);
1622 }
1623
1624 #[must_use]
1626 pub const fn has_more(&self) -> bool {
1627 self.status.more
1628 }
1629
1630 #[must_use]
1632 pub const fn has_error(&self) -> bool {
1633 self.status.error
1634 }
1635
1636 #[must_use]
1638 pub const fn has_count(&self) -> bool {
1639 self.status.count
1640 }
1641}
1642
1643impl DoneProc {
1644 pub const SIZE: usize = 12;
1646
1647 pub fn decode(src: &mut impl Buf) -> Result<Self, ProtocolError> {
1649 if src.remaining() < Self::SIZE {
1650 return Err(ProtocolError::IncompletePacket {
1651 expected: Self::SIZE,
1652 actual: src.remaining(),
1653 });
1654 }
1655
1656 let status = DoneStatus::from_bits(src.get_u16_le());
1657 let cur_cmd = src.get_u16_le();
1658 let row_count = src.get_u64_le();
1659
1660 Ok(Self {
1661 status,
1662 cur_cmd,
1663 row_count,
1664 })
1665 }
1666
1667 pub fn encode(&self, dst: &mut impl BufMut) {
1669 dst.put_u8(TokenType::DoneProc as u8);
1670 dst.put_u16_le(self.status.to_bits());
1671 dst.put_u16_le(self.cur_cmd);
1672 dst.put_u64_le(self.row_count);
1673 }
1674}
1675
1676impl DoneInProc {
1677 pub const SIZE: usize = 12;
1679
1680 pub fn decode(src: &mut impl Buf) -> Result<Self, ProtocolError> {
1682 if src.remaining() < Self::SIZE {
1683 return Err(ProtocolError::IncompletePacket {
1684 expected: Self::SIZE,
1685 actual: src.remaining(),
1686 });
1687 }
1688
1689 let status = DoneStatus::from_bits(src.get_u16_le());
1690 let cur_cmd = src.get_u16_le();
1691 let row_count = src.get_u64_le();
1692
1693 Ok(Self {
1694 status,
1695 cur_cmd,
1696 row_count,
1697 })
1698 }
1699
1700 pub fn encode(&self, dst: &mut impl BufMut) {
1702 dst.put_u8(TokenType::DoneInProc as u8);
1703 dst.put_u16_le(self.status.to_bits());
1704 dst.put_u16_le(self.cur_cmd);
1705 dst.put_u64_le(self.row_count);
1706 }
1707}
1708
1709impl ServerError {
1710 pub fn decode(src: &mut impl Buf) -> Result<Self, ProtocolError> {
1712 if src.remaining() < 2 {
1715 return Err(ProtocolError::UnexpectedEof);
1716 }
1717
1718 let _length = src.get_u16_le();
1719
1720 if src.remaining() < 6 {
1721 return Err(ProtocolError::UnexpectedEof);
1722 }
1723
1724 let number = src.get_i32_le();
1725 let state = src.get_u8();
1726 let class = src.get_u8();
1727
1728 let message = read_us_varchar(src).ok_or(ProtocolError::UnexpectedEof)?;
1729 let server = read_b_varchar(src).ok_or(ProtocolError::UnexpectedEof)?;
1730 let procedure = read_b_varchar(src).ok_or(ProtocolError::UnexpectedEof)?;
1731
1732 if src.remaining() < 4 {
1733 return Err(ProtocolError::UnexpectedEof);
1734 }
1735 let line = src.get_i32_le();
1736
1737 Ok(Self {
1738 number,
1739 state,
1740 class,
1741 message,
1742 server,
1743 procedure,
1744 line,
1745 })
1746 }
1747
1748 #[must_use]
1750 pub const fn is_fatal(&self) -> bool {
1751 self.class >= 20
1752 }
1753
1754 #[must_use]
1756 pub const fn is_batch_abort(&self) -> bool {
1757 self.class >= 16
1758 }
1759}
1760
1761impl ServerInfo {
1762 pub fn decode(src: &mut impl Buf) -> Result<Self, ProtocolError> {
1766 if src.remaining() < 2 {
1767 return Err(ProtocolError::UnexpectedEof);
1768 }
1769
1770 let _length = src.get_u16_le();
1771
1772 if src.remaining() < 6 {
1773 return Err(ProtocolError::UnexpectedEof);
1774 }
1775
1776 let number = src.get_i32_le();
1777 let state = src.get_u8();
1778 let class = src.get_u8();
1779
1780 let message = read_us_varchar(src).ok_or(ProtocolError::UnexpectedEof)?;
1781 let server = read_b_varchar(src).ok_or(ProtocolError::UnexpectedEof)?;
1782 let procedure = read_b_varchar(src).ok_or(ProtocolError::UnexpectedEof)?;
1783
1784 if src.remaining() < 4 {
1785 return Err(ProtocolError::UnexpectedEof);
1786 }
1787 let line = src.get_i32_le();
1788
1789 Ok(Self {
1790 number,
1791 state,
1792 class,
1793 message,
1794 server,
1795 procedure,
1796 line,
1797 })
1798 }
1799}
1800
1801impl LoginAck {
1802 pub fn decode(src: &mut impl Buf) -> Result<Self, ProtocolError> {
1804 if src.remaining() < 2 {
1806 return Err(ProtocolError::UnexpectedEof);
1807 }
1808
1809 let _length = src.get_u16_le();
1810
1811 if src.remaining() < 5 {
1812 return Err(ProtocolError::UnexpectedEof);
1813 }
1814
1815 let interface = src.get_u8();
1816 let tds_version = src.get_u32_le();
1817 let prog_name = read_b_varchar(src).ok_or(ProtocolError::UnexpectedEof)?;
1818
1819 if src.remaining() < 4 {
1820 return Err(ProtocolError::UnexpectedEof);
1821 }
1822 let prog_version = src.get_u32_le();
1823
1824 Ok(Self {
1825 interface,
1826 tds_version,
1827 prog_name,
1828 prog_version,
1829 })
1830 }
1831
1832 #[must_use]
1834 pub fn tds_version(&self) -> crate::version::TdsVersion {
1835 crate::version::TdsVersion::new(self.tds_version)
1836 }
1837}
1838
1839impl EnvChangeType {
1840 pub fn from_u8(value: u8) -> Option<Self> {
1842 match value {
1843 1 => Some(Self::Database),
1844 2 => Some(Self::Language),
1845 3 => Some(Self::CharacterSet),
1846 4 => Some(Self::PacketSize),
1847 5 => Some(Self::UnicodeSortingLocalId),
1848 6 => Some(Self::UnicodeComparisonFlags),
1849 7 => Some(Self::SqlCollation),
1850 8 => Some(Self::BeginTransaction),
1851 9 => Some(Self::CommitTransaction),
1852 10 => Some(Self::RollbackTransaction),
1853 11 => Some(Self::EnlistDtcTransaction),
1854 12 => Some(Self::DefectTransaction),
1855 13 => Some(Self::RealTimeLogShipping),
1856 15 => Some(Self::PromoteTransaction),
1857 16 => Some(Self::TransactionManagerAddress),
1858 17 => Some(Self::TransactionEnded),
1859 18 => Some(Self::ResetConnectionCompletionAck),
1860 19 => Some(Self::UserInstanceStarted),
1861 20 => Some(Self::Routing),
1862 _ => None,
1863 }
1864 }
1865}
1866
1867impl EnvChange {
1868 pub fn decode(src: &mut impl Buf) -> Result<Self, ProtocolError> {
1870 if src.remaining() < 3 {
1871 return Err(ProtocolError::UnexpectedEof);
1872 }
1873
1874 let length = src.get_u16_le() as usize;
1875 if src.remaining() < length {
1876 return Err(ProtocolError::IncompletePacket {
1877 expected: length,
1878 actual: src.remaining(),
1879 });
1880 }
1881 let remaining_before = src.remaining();
1882
1883 let env_type_byte = src.get_u8();
1884 let env_type = EnvChangeType::from_u8(env_type_byte)
1885 .ok_or(ProtocolError::InvalidTokenType(env_type_byte))?;
1886
1887 let (new_value, old_value) = match env_type {
1888 EnvChangeType::Routing => {
1889 let new_value = Self::decode_routing_value(src)?;
1891 let old_value = EnvChangeValue::Binary(Bytes::new());
1892 (new_value, old_value)
1893 }
1894 EnvChangeType::BeginTransaction
1895 | EnvChangeType::CommitTransaction
1896 | EnvChangeType::RollbackTransaction
1897 | EnvChangeType::EnlistDtcTransaction
1898 | EnvChangeType::SqlCollation => {
1899 let new_len = if src.has_remaining() {
1908 src.get_u8() as usize
1909 } else {
1910 0
1911 };
1912 let new_value = if new_len > 0 && src.remaining() >= new_len {
1913 EnvChangeValue::Binary(src.copy_to_bytes(new_len))
1914 } else {
1915 EnvChangeValue::Binary(Bytes::new())
1916 };
1917
1918 let old_len = if src.has_remaining() {
1919 src.get_u8() as usize
1920 } else {
1921 0
1922 };
1923 let old_value = if old_len > 0 && src.remaining() >= old_len {
1924 EnvChangeValue::Binary(src.copy_to_bytes(old_len))
1925 } else {
1926 EnvChangeValue::Binary(Bytes::new())
1927 };
1928
1929 (new_value, old_value)
1930 }
1931 _ => {
1932 let new_value = read_b_varchar(src)
1934 .map(EnvChangeValue::String)
1935 .unwrap_or(EnvChangeValue::String(String::new()));
1936
1937 let old_value = read_b_varchar(src)
1938 .map(EnvChangeValue::String)
1939 .unwrap_or(EnvChangeValue::String(String::new()));
1940
1941 (new_value, old_value)
1942 }
1943 };
1944
1945 let consumed = remaining_before - src.remaining();
1953 if consumed < length {
1954 src.advance(length - consumed);
1955 }
1956
1957 Ok(Self {
1958 env_type,
1959 new_value,
1960 old_value,
1961 })
1962 }
1963
1964 fn decode_routing_value(src: &mut impl Buf) -> Result<EnvChangeValue, ProtocolError> {
1965 if src.remaining() < 2 {
1967 return Err(ProtocolError::UnexpectedEof);
1968 }
1969
1970 let _routing_len = src.get_u16_le();
1971
1972 if src.remaining() < 5 {
1973 return Err(ProtocolError::UnexpectedEof);
1974 }
1975
1976 let _protocol = src.get_u8();
1977 let port = src.get_u16_le();
1978 let server_len = src.get_u16_le() as usize;
1979
1980 if src.remaining() < server_len * 2 {
1982 return Err(ProtocolError::UnexpectedEof);
1983 }
1984
1985 let mut chars = Vec::with_capacity(server_len);
1986 for _ in 0..server_len {
1987 chars.push(src.get_u16_le());
1988 }
1989
1990 let host = String::from_utf16(&chars).map_err(|_| {
1991 ProtocolError::StringEncoding(
1992 #[cfg(feature = "std")]
1993 "invalid UTF-16 in routing hostname".to_string(),
1994 #[cfg(not(feature = "std"))]
1995 "invalid UTF-16 in routing hostname",
1996 )
1997 })?;
1998
1999 Ok(EnvChangeValue::Routing { host, port })
2000 }
2001
2002 #[must_use]
2004 pub fn is_routing(&self) -> bool {
2005 self.env_type == EnvChangeType::Routing
2006 }
2007
2008 #[must_use]
2010 pub fn routing_info(&self) -> Option<(&str, u16)> {
2011 if let EnvChangeValue::Routing { host, port } = &self.new_value {
2012 Some((host, *port))
2013 } else {
2014 None
2015 }
2016 }
2017
2018 #[must_use]
2020 pub fn new_database(&self) -> Option<&str> {
2021 if self.env_type == EnvChangeType::Database {
2022 if let EnvChangeValue::String(s) = &self.new_value {
2023 return Some(s);
2024 }
2025 }
2026 None
2027 }
2028}
2029
2030impl Order {
2031 pub fn decode(src: &mut impl Buf) -> Result<Self, ProtocolError> {
2033 if src.remaining() < 2 {
2034 return Err(ProtocolError::UnexpectedEof);
2035 }
2036
2037 let length = src.get_u16_le() as usize;
2038 let column_count = length / 2;
2039
2040 if src.remaining() < length {
2041 return Err(ProtocolError::IncompletePacket {
2042 expected: length,
2043 actual: src.remaining(),
2044 });
2045 }
2046
2047 let mut columns = Vec::with_capacity(column_count);
2048 for _ in 0..column_count {
2049 columns.push(src.get_u16_le());
2050 }
2051
2052 Ok(Self { columns })
2053 }
2054}
2055
2056impl FeatureExtAck {
2057 pub const TERMINATOR: u8 = 0xFF;
2059
2060 pub fn decode(src: &mut impl Buf) -> Result<Self, ProtocolError> {
2062 let mut features = Vec::new();
2063
2064 loop {
2065 if !src.has_remaining() {
2066 return Err(ProtocolError::UnexpectedEof);
2067 }
2068
2069 let feature_id = src.get_u8();
2070 if feature_id == Self::TERMINATOR {
2071 break;
2072 }
2073
2074 if src.remaining() < 4 {
2075 return Err(ProtocolError::UnexpectedEof);
2076 }
2077
2078 let data_len = src.get_u32_le() as usize;
2079
2080 if src.remaining() < data_len {
2081 return Err(ProtocolError::IncompletePacket {
2082 expected: data_len,
2083 actual: src.remaining(),
2084 });
2085 }
2086
2087 let data = src.copy_to_bytes(data_len);
2088 features.push(FeatureAck { feature_id, data });
2089 }
2090
2091 Ok(Self { features })
2092 }
2093}
2094
2095impl SspiToken {
2096 pub fn decode(src: &mut impl Buf) -> Result<Self, ProtocolError> {
2098 if src.remaining() < 2 {
2099 return Err(ProtocolError::UnexpectedEof);
2100 }
2101
2102 let length = src.get_u16_le() as usize;
2103
2104 if src.remaining() < length {
2105 return Err(ProtocolError::IncompletePacket {
2106 expected: length,
2107 actual: src.remaining(),
2108 });
2109 }
2110
2111 let data = src.copy_to_bytes(length);
2112 Ok(Self { data })
2113 }
2114}
2115
2116impl FedAuthInfo {
2117 pub fn decode(src: &mut impl Buf) -> Result<Self, ProtocolError> {
2119 if src.remaining() < 4 {
2120 return Err(ProtocolError::UnexpectedEof);
2121 }
2122
2123 let _length = src.get_u32_le();
2124
2125 if src.remaining() < 5 {
2126 return Err(ProtocolError::UnexpectedEof);
2127 }
2128
2129 let _count = src.get_u8();
2130
2131 let mut sts_url = String::new();
2133 let mut spn = String::new();
2134
2135 while src.has_remaining() {
2137 if src.remaining() < 9 {
2138 break;
2139 }
2140
2141 let info_id = src.get_u8();
2142 let info_len = src.get_u32_le() as usize;
2143 let _info_offset = src.get_u32_le();
2144
2145 if src.remaining() < info_len {
2146 break;
2147 }
2148
2149 let char_count = info_len / 2;
2151 let mut chars = Vec::with_capacity(char_count);
2152 for _ in 0..char_count {
2153 chars.push(src.get_u16_le());
2154 }
2155
2156 if let Ok(value) = String::from_utf16(&chars) {
2157 match info_id {
2158 0x01 => spn = value,
2159 0x02 => sts_url = value,
2160 _ => {}
2161 }
2162 }
2163 }
2164
2165 Ok(Self { sts_url, spn })
2166 }
2167}
2168
2169pub struct TokenParser {
2210 data: Bytes,
2211 position: usize,
2212 encryption_enabled: bool,
2215}
2216
2217impl TokenParser {
2218 #[must_use]
2220 pub fn new(data: Bytes) -> Self {
2221 Self {
2222 data,
2223 position: 0,
2224 encryption_enabled: false,
2225 }
2226 }
2227
2228 #[must_use]
2233 pub fn with_encryption(mut self, enabled: bool) -> Self {
2234 self.encryption_enabled = enabled;
2235 self
2236 }
2237
2238 #[must_use]
2240 pub fn remaining(&self) -> usize {
2241 self.data.len().saturating_sub(self.position)
2242 }
2243
2244 #[must_use]
2246 pub fn has_remaining(&self) -> bool {
2247 self.position < self.data.len()
2248 }
2249
2250 #[must_use]
2252 pub fn peek_token_type(&self) -> Option<TokenType> {
2253 if self.position < self.data.len() {
2254 TokenType::from_u8(self.data[self.position])
2255 } else {
2256 None
2257 }
2258 }
2259
2260 pub fn next_token(&mut self) -> Result<Option<Token>, ProtocolError> {
2268 self.next_token_with_metadata(None)
2269 }
2270
2271 pub fn next_token_with_metadata(
2278 &mut self,
2279 metadata: Option<&ColMetaData>,
2280 ) -> Result<Option<Token>, ProtocolError> {
2281 if !self.has_remaining() {
2282 return Ok(None);
2283 }
2284
2285 let mut buf = &self.data[self.position..];
2286 let start_pos = self.position;
2287
2288 let token_type_byte = buf.get_u8();
2289 let token_type = TokenType::from_u8(token_type_byte);
2290
2291 let token = match token_type {
2292 Some(TokenType::Done) => {
2293 let done = Done::decode(&mut buf)?;
2294 Token::Done(done)
2295 }
2296 Some(TokenType::DoneProc) => {
2297 let done = DoneProc::decode(&mut buf)?;
2298 Token::DoneProc(done)
2299 }
2300 Some(TokenType::DoneInProc) => {
2301 let done = DoneInProc::decode(&mut buf)?;
2302 Token::DoneInProc(done)
2303 }
2304 Some(TokenType::Error) => {
2305 let error = ServerError::decode(&mut buf)?;
2306 Token::Error(error)
2307 }
2308 Some(TokenType::Info) => {
2309 let info = ServerInfo::decode(&mut buf)?;
2310 Token::Info(info)
2311 }
2312 Some(TokenType::LoginAck) => {
2313 let login_ack = LoginAck::decode(&mut buf)?;
2314 Token::LoginAck(login_ack)
2315 }
2316 Some(TokenType::EnvChange) => {
2317 let env_change = EnvChange::decode(&mut buf)?;
2318 Token::EnvChange(env_change)
2319 }
2320 Some(TokenType::Order) => {
2321 let order = Order::decode(&mut buf)?;
2322 Token::Order(order)
2323 }
2324 Some(TokenType::FeatureExtAck) => {
2325 let ack = FeatureExtAck::decode(&mut buf)?;
2326 Token::FeatureExtAck(ack)
2327 }
2328 Some(TokenType::Sspi) => {
2329 let sspi = SspiToken::decode(&mut buf)?;
2330 Token::Sspi(sspi)
2331 }
2332 Some(TokenType::FedAuthInfo) => {
2333 let info = FedAuthInfo::decode(&mut buf)?;
2334 Token::FedAuthInfo(info)
2335 }
2336 Some(TokenType::ReturnStatus) => {
2337 if buf.remaining() < 4 {
2338 return Err(ProtocolError::UnexpectedEof);
2339 }
2340 let status = buf.get_i32_le();
2341 Token::ReturnStatus(status)
2342 }
2343 Some(TokenType::ColMetaData) => {
2344 let col_meta = if self.encryption_enabled {
2345 ColMetaData::decode_encrypted(&mut buf)?
2346 } else {
2347 ColMetaData::decode(&mut buf)?
2348 };
2349 Token::ColMetaData(col_meta)
2350 }
2351 Some(TokenType::Row) => {
2352 let meta = metadata.ok_or_else(|| {
2353 ProtocolError::StringEncoding(
2354 #[cfg(feature = "std")]
2355 "Row token requires column metadata".to_string(),
2356 #[cfg(not(feature = "std"))]
2357 "Row token requires column metadata",
2358 )
2359 })?;
2360 let row = RawRow::decode(&mut buf, meta)?;
2361 Token::Row(row)
2362 }
2363 Some(TokenType::NbcRow) => {
2364 let meta = metadata.ok_or_else(|| {
2365 ProtocolError::StringEncoding(
2366 #[cfg(feature = "std")]
2367 "NbcRow token requires column metadata".to_string(),
2368 #[cfg(not(feature = "std"))]
2369 "NbcRow token requires column metadata",
2370 )
2371 })?;
2372 let row = NbcRow::decode(&mut buf, meta)?;
2373 Token::NbcRow(row)
2374 }
2375 Some(TokenType::ReturnValue) => {
2376 let ret_val = ReturnValue::decode(&mut buf)?;
2377 Token::ReturnValue(ret_val)
2378 }
2379 Some(TokenType::SessionState) => {
2380 let session = SessionState::decode(&mut buf)?;
2381 Token::SessionState(session)
2382 }
2383 Some(TokenType::ColInfo) | Some(TokenType::TabName) | Some(TokenType::Offset) => {
2384 if buf.remaining() < 2 {
2387 return Err(ProtocolError::UnexpectedEof);
2388 }
2389 let length = buf.get_u16_le() as usize;
2390 if buf.remaining() < length {
2391 return Err(ProtocolError::IncompletePacket {
2392 expected: length,
2393 actual: buf.remaining(),
2394 });
2395 }
2396 buf.advance(length);
2398 self.position = start_pos + (self.data.len() - start_pos - buf.remaining());
2400 return self.next_token_with_metadata(metadata);
2401 }
2402 None => {
2403 return Err(ProtocolError::InvalidTokenType(token_type_byte));
2404 }
2405 };
2406
2407 let consumed = self.data.len() - start_pos - buf.remaining();
2409 self.position = start_pos + consumed;
2410
2411 Ok(Some(token))
2412 }
2413
2414 pub fn skip_token(&mut self) -> Result<(), ProtocolError> {
2418 if !self.has_remaining() {
2419 return Ok(());
2420 }
2421
2422 let token_type_byte = self.data[self.position];
2423 let token_type = TokenType::from_u8(token_type_byte);
2424
2425 let skip_amount = match token_type {
2427 Some(TokenType::Done) | Some(TokenType::DoneProc) | Some(TokenType::DoneInProc) => {
2429 1 + Done::SIZE }
2431 Some(TokenType::ReturnStatus) => {
2432 1 + 4 }
2434 Some(TokenType::Error)
2436 | Some(TokenType::Info)
2437 | Some(TokenType::LoginAck)
2438 | Some(TokenType::EnvChange)
2439 | Some(TokenType::Order)
2440 | Some(TokenType::Sspi)
2441 | Some(TokenType::ColInfo)
2442 | Some(TokenType::TabName)
2443 | Some(TokenType::Offset)
2444 | Some(TokenType::ReturnValue) => {
2445 if self.remaining() < 3 {
2446 return Err(ProtocolError::UnexpectedEof);
2447 }
2448 let length = u16::from_le_bytes([
2449 self.data[self.position + 1],
2450 self.data[self.position + 2],
2451 ]) as usize;
2452 1 + 2 + length }
2454 Some(TokenType::SessionState) | Some(TokenType::FedAuthInfo) => {
2456 if self.remaining() < 5 {
2457 return Err(ProtocolError::UnexpectedEof);
2458 }
2459 let length = u32::from_le_bytes([
2460 self.data[self.position + 1],
2461 self.data[self.position + 2],
2462 self.data[self.position + 3],
2463 self.data[self.position + 4],
2464 ]) as usize;
2465 1 + 4 + length
2466 }
2467 Some(TokenType::FeatureExtAck) => {
2469 let mut buf = &self.data[self.position + 1..];
2471 let _ = FeatureExtAck::decode(&mut buf)?;
2472 self.data.len() - self.position - buf.remaining()
2473 }
2474 Some(TokenType::ColMetaData) | Some(TokenType::Row) | Some(TokenType::NbcRow) => {
2476 return Err(ProtocolError::InvalidTokenType(token_type_byte));
2477 }
2478 None => {
2479 return Err(ProtocolError::InvalidTokenType(token_type_byte));
2480 }
2481 };
2482
2483 if self.remaining() < skip_amount {
2484 return Err(ProtocolError::UnexpectedEof);
2485 }
2486
2487 self.position += skip_amount;
2488 Ok(())
2489 }
2490
2491 #[must_use]
2493 pub fn position(&self) -> usize {
2494 self.position
2495 }
2496
2497 pub fn reset(&mut self) {
2499 self.position = 0;
2500 }
2501}
2502
2503#[cfg(test)]
2508#[allow(clippy::unwrap_used, clippy::panic)]
2509mod tests {
2510 use super::*;
2511 use bytes::BytesMut;
2512
2513 #[test]
2514 fn test_done_roundtrip() {
2515 let done = Done {
2516 status: DoneStatus {
2517 more: false,
2518 error: false,
2519 in_xact: false,
2520 count: true,
2521 attn: false,
2522 srverror: false,
2523 },
2524 cur_cmd: 193, row_count: 42,
2526 };
2527
2528 let mut buf = BytesMut::new();
2529 done.encode(&mut buf);
2530
2531 let mut cursor = &buf[1..];
2533 let decoded = Done::decode(&mut cursor).unwrap();
2534
2535 assert_eq!(decoded.status.count, done.status.count);
2536 assert_eq!(decoded.cur_cmd, done.cur_cmd);
2537 assert_eq!(decoded.row_count, done.row_count);
2538 }
2539
2540 #[test]
2541 fn test_done_status_bits() {
2542 let status = DoneStatus {
2543 more: true,
2544 error: true,
2545 in_xact: true,
2546 count: true,
2547 attn: false,
2548 srverror: false,
2549 };
2550
2551 let bits = status.to_bits();
2552 let restored = DoneStatus::from_bits(bits);
2553
2554 assert_eq!(status.more, restored.more);
2555 assert_eq!(status.error, restored.error);
2556 assert_eq!(status.in_xact, restored.in_xact);
2557 assert_eq!(status.count, restored.count);
2558 }
2559
2560 #[test]
2561 fn test_token_parser_done() {
2562 let data = Bytes::from_static(&[
2564 0xFD, 0x10, 0x00, 0xC1, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ]);
2569
2570 let mut parser = TokenParser::new(data);
2571 let token = parser.next_token().unwrap().unwrap();
2572
2573 match token {
2574 Token::Done(done) => {
2575 assert!(done.status.count);
2576 assert!(!done.status.more);
2577 assert_eq!(done.cur_cmd, 193);
2578 assert_eq!(done.row_count, 5);
2579 }
2580 _ => panic!("Expected Done token"),
2581 }
2582
2583 assert!(parser.next_token().unwrap().is_none());
2585 }
2586
2587 #[test]
2588 fn test_env_change_type_from_u8() {
2589 assert_eq!(EnvChangeType::from_u8(1), Some(EnvChangeType::Database));
2590 assert_eq!(EnvChangeType::from_u8(20), Some(EnvChangeType::Routing));
2591 assert_eq!(EnvChangeType::from_u8(100), None);
2592 }
2593
2594 #[test]
2601 fn test_env_change_routing_consumes_declared_length() {
2602 let host = "redirect.example";
2603 let host_utf16: Vec<u16> = host.encode_utf16().collect();
2604
2605 let mut data = BytesMut::new();
2606 let routing_len = 1 + 2 + 2 + host_utf16.len() * 2;
2608 let env_len = 1 + 2 + routing_len + 2;
2611 data.put_u16_le(env_len as u16);
2612 data.put_u8(20); data.put_u16_le(routing_len as u16);
2614 data.put_u8(0); data.put_u16_le(11000); data.put_u16_le(host_utf16.len() as u16);
2617 for c in &host_utf16 {
2618 data.put_u16_le(*c);
2619 }
2620 data.put_u16_le(0); data.put_u8(0xFD);
2623
2624 let mut buf: &[u8] = &data;
2625 let env = EnvChange::decode(&mut buf).unwrap();
2626 assert_eq!(env.routing_info(), Some((host, 11000)));
2627 assert_eq!(
2628 buf,
2629 &[0xFD],
2630 "decode must consume exactly the declared ENVCHANGE frame"
2631 );
2632 }
2633
2634 #[test]
2635 fn hostile_env_change_binary_truncated_is_not_panic() {
2636 let data = [0x01, 0x00, 0x08];
2641 let mut buf: &[u8] = &data;
2642 let env = EnvChange::decode(&mut buf).unwrap();
2643 assert_eq!(env.env_type, EnvChangeType::BeginTransaction);
2644 }
2645
2646 #[test]
2647 fn test_colmetadata_no_columns() {
2648 let data = Bytes::from_static(&[0xFF, 0xFF]);
2650 let mut cursor: &[u8] = &data;
2651 let meta = ColMetaData::decode(&mut cursor).unwrap();
2652 assert!(meta.is_empty());
2653 assert_eq!(meta.column_count(), 0);
2654 }
2655
2656 #[test]
2657 fn test_colmetadata_single_int_column() {
2658 let mut data = BytesMut::new();
2661 data.extend_from_slice(&[0x01, 0x00]); data.extend_from_slice(&[0x00, 0x00, 0x00, 0x00]); data.extend_from_slice(&[0x01, 0x00]); data.extend_from_slice(&[0x38]); data.extend_from_slice(&[0x02]); data.extend_from_slice(&[b'i', 0x00, b'd', 0x00]); let mut cursor: &[u8] = &data;
2670 let meta = ColMetaData::decode(&mut cursor).unwrap();
2671
2672 assert_eq!(meta.column_count(), 1);
2673 assert_eq!(meta.columns[0].name, "id");
2674 assert_eq!(meta.columns[0].type_id, TypeId::Int4);
2675 assert!(meta.columns[0].is_nullable());
2676 }
2677
2678 #[test]
2679 fn test_colmetadata_nvarchar_column() {
2680 let mut data = BytesMut::new();
2682 data.extend_from_slice(&[0x01, 0x00]); data.extend_from_slice(&[0x00, 0x00, 0x00, 0x00]); data.extend_from_slice(&[0x01, 0x00]); data.extend_from_slice(&[0xE7]); data.extend_from_slice(&[0x64, 0x00]); data.extend_from_slice(&[0x09, 0x04, 0xD0, 0x00, 0x34]); data.extend_from_slice(&[0x04]); data.extend_from_slice(&[b'n', 0x00, b'a', 0x00, b'm', 0x00, b'e', 0x00]);
2692
2693 let mut cursor: &[u8] = &data;
2694 let meta = ColMetaData::decode(&mut cursor).unwrap();
2695
2696 assert_eq!(meta.column_count(), 1);
2697 assert_eq!(meta.columns[0].name, "name");
2698 assert_eq!(meta.columns[0].type_id, TypeId::NVarChar);
2699 assert_eq!(meta.columns[0].type_info.max_length, Some(100));
2700 assert!(meta.columns[0].type_info.collation.is_some());
2701 }
2702
2703 #[test]
2704 fn test_raw_row_decode_int() {
2705 let metadata = ColMetaData {
2707 cek_table: None,
2708 columns: vec![ColumnData {
2709 name: "id".to_string(),
2710 type_id: TypeId::Int4,
2711 col_type: 0x38,
2712 flags: 0,
2713 user_type: 0,
2714 type_info: TypeInfo::default(),
2715 crypto_metadata: None,
2716 }],
2717 };
2718
2719 let data = Bytes::from_static(&[0x2A, 0x00, 0x00, 0x00]); let mut cursor: &[u8] = &data;
2722 let row = RawRow::decode(&mut cursor, &metadata).unwrap();
2723
2724 assert_eq!(row.data.len(), 4);
2726 assert_eq!(&row.data[..], &[0x2A, 0x00, 0x00, 0x00]);
2727 }
2728
2729 #[test]
2730 fn test_raw_row_decode_nullable_int() {
2731 let metadata = ColMetaData {
2733 cek_table: None,
2734 columns: vec![ColumnData {
2735 name: "id".to_string(),
2736 type_id: TypeId::IntN,
2737 col_type: 0x26,
2738 flags: 0x01, user_type: 0,
2740 type_info: TypeInfo {
2741 max_length: Some(4),
2742 ..Default::default()
2743 },
2744 crypto_metadata: None,
2745 }],
2746 };
2747
2748 let data = Bytes::from_static(&[0x04, 0x2A, 0x00, 0x00, 0x00]); let mut cursor: &[u8] = &data;
2751 let row = RawRow::decode(&mut cursor, &metadata).unwrap();
2752
2753 assert_eq!(row.data.len(), 5);
2754 assert_eq!(row.data[0], 4); assert_eq!(&row.data[1..], &[0x2A, 0x00, 0x00, 0x00]);
2756 }
2757
2758 #[test]
2759 fn test_raw_row_decode_null_value() {
2760 let metadata = ColMetaData {
2762 cek_table: None,
2763 columns: vec![ColumnData {
2764 name: "id".to_string(),
2765 type_id: TypeId::IntN,
2766 col_type: 0x26,
2767 flags: 0x01, user_type: 0,
2769 type_info: TypeInfo {
2770 max_length: Some(4),
2771 ..Default::default()
2772 },
2773 crypto_metadata: None,
2774 }],
2775 };
2776
2777 let data = Bytes::from_static(&[0xFF]);
2779 let mut cursor: &[u8] = &data;
2780 let row = RawRow::decode(&mut cursor, &metadata).unwrap();
2781
2782 assert_eq!(row.data.len(), 1);
2783 assert_eq!(row.data[0], 0xFF); }
2785
2786 #[test]
2787 fn test_nbcrow_null_bitmap() {
2788 let row = NbcRow {
2789 null_bitmap: vec![0b00000101], data: Bytes::new(),
2791 };
2792
2793 assert!(row.is_null(0));
2794 assert!(!row.is_null(1));
2795 assert!(row.is_null(2));
2796 assert!(!row.is_null(3));
2797 }
2798
2799 #[test]
2800 fn test_token_parser_colmetadata() {
2801 let mut data = BytesMut::new();
2803 data.extend_from_slice(&[0x81]); data.extend_from_slice(&[0x01, 0x00]); data.extend_from_slice(&[0x00, 0x00, 0x00, 0x00]); data.extend_from_slice(&[0x01, 0x00]); data.extend_from_slice(&[0x38]); data.extend_from_slice(&[0x02]); data.extend_from_slice(&[b'i', 0x00, b'd', 0x00]); let mut parser = TokenParser::new(data.freeze());
2812 let token = parser.next_token().unwrap().unwrap();
2813
2814 match token {
2815 Token::ColMetaData(meta) => {
2816 assert_eq!(meta.column_count(), 1);
2817 assert_eq!(meta.columns[0].name, "id");
2818 assert_eq!(meta.columns[0].type_id, TypeId::Int4);
2819 }
2820 _ => panic!("Expected ColMetaData token"),
2821 }
2822 }
2823
2824 #[test]
2825 fn test_token_parser_row_with_metadata() {
2826 let metadata = ColMetaData {
2828 cek_table: None,
2829 columns: vec![ColumnData {
2830 name: "id".to_string(),
2831 type_id: TypeId::Int4,
2832 col_type: 0x38,
2833 flags: 0,
2834 user_type: 0,
2835 type_info: TypeInfo::default(),
2836 crypto_metadata: None,
2837 }],
2838 };
2839
2840 let mut data = BytesMut::new();
2842 data.extend_from_slice(&[0xD1]); data.extend_from_slice(&[0x2A, 0x00, 0x00, 0x00]); let mut parser = TokenParser::new(data.freeze());
2846 let token = parser
2847 .next_token_with_metadata(Some(&metadata))
2848 .unwrap()
2849 .unwrap();
2850
2851 match token {
2852 Token::Row(row) => {
2853 assert_eq!(row.data.len(), 4);
2854 }
2855 _ => panic!("Expected Row token"),
2856 }
2857 }
2858
2859 #[test]
2860 fn test_token_parser_row_without_metadata_fails() {
2861 let mut data = BytesMut::new();
2863 data.extend_from_slice(&[0xD1]); data.extend_from_slice(&[0x2A, 0x00, 0x00, 0x00]); let mut parser = TokenParser::new(data.freeze());
2867 let result = parser.next_token(); assert!(result.is_err());
2870 }
2871
2872 #[test]
2873 fn test_token_parser_peek() {
2874 let data = Bytes::from_static(&[
2875 0xFD, 0x10, 0x00, 0xC1, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ]);
2880
2881 let parser = TokenParser::new(data);
2882 assert_eq!(parser.peek_token_type(), Some(TokenType::Done));
2883 }
2884
2885 #[test]
2886 fn test_column_data_fixed_size() {
2887 let col = ColumnData {
2888 name: String::new(),
2889 type_id: TypeId::Int4,
2890 col_type: 0x38,
2891 flags: 0,
2892 user_type: 0,
2893 type_info: TypeInfo::default(),
2894 crypto_metadata: None,
2895 };
2896 assert_eq!(col.fixed_size(), Some(4));
2897
2898 let col2 = ColumnData {
2899 name: String::new(),
2900 type_id: TypeId::NVarChar,
2901 col_type: 0xE7,
2902 flags: 0,
2903 user_type: 0,
2904 type_info: TypeInfo::default(),
2905 crypto_metadata: None,
2906 };
2907 assert_eq!(col2.fixed_size(), None);
2908 }
2909
2910 #[test]
2918 fn test_decode_nvarchar_then_intn_roundtrip() {
2919 let mut wire_data = BytesMut::new();
2924
2925 let word = "World";
2928 let utf16: Vec<u16> = word.encode_utf16().collect();
2929 wire_data.put_u16_le((utf16.len() * 2) as u16); for code_unit in &utf16 {
2931 wire_data.put_u16_le(*code_unit);
2932 }
2933
2934 wire_data.put_u8(4); wire_data.put_i32_le(42);
2937
2938 let metadata = ColMetaData {
2940 cek_table: None,
2941 columns: vec![
2942 ColumnData {
2943 name: "greeting".to_string(),
2944 type_id: TypeId::NVarChar,
2945 col_type: 0xE7,
2946 flags: 0x01,
2947 user_type: 0,
2948 type_info: TypeInfo {
2949 max_length: Some(10), precision: None,
2951 scale: None,
2952 collation: None,
2953 },
2954 crypto_metadata: None,
2955 },
2956 ColumnData {
2957 name: "number".to_string(),
2958 type_id: TypeId::IntN,
2959 col_type: 0x26,
2960 flags: 0x01,
2961 user_type: 0,
2962 type_info: TypeInfo {
2963 max_length: Some(4),
2964 precision: None,
2965 scale: None,
2966 collation: None,
2967 },
2968 crypto_metadata: None,
2969 },
2970 ],
2971 };
2972
2973 let mut wire_cursor = wire_data.freeze();
2975 let raw_row = RawRow::decode(&mut wire_cursor, &metadata).unwrap();
2976
2977 assert_eq!(
2979 wire_cursor.remaining(),
2980 0,
2981 "wire data should be fully consumed"
2982 );
2983
2984 let mut stored_cursor: &[u8] = &raw_row.data;
2986
2987 assert!(
2990 stored_cursor.remaining() >= 2,
2991 "need at least 2 bytes for length"
2992 );
2993 let len0 = stored_cursor.get_u16_le() as usize;
2994 assert_eq!(len0, 10, "NVarChar length should be 10 bytes");
2995 assert!(
2996 stored_cursor.remaining() >= len0,
2997 "need {len0} bytes for data"
2998 );
2999
3000 let mut utf16_read = Vec::new();
3002 for _ in 0..(len0 / 2) {
3003 utf16_read.push(stored_cursor.get_u16_le());
3004 }
3005 let string0 = String::from_utf16(&utf16_read).unwrap();
3006 assert_eq!(string0, "World", "column 0 should be 'World'");
3007
3008 assert!(
3011 stored_cursor.remaining() >= 1,
3012 "need at least 1 byte for length"
3013 );
3014 let len1 = stored_cursor.get_u8();
3015 assert_eq!(len1, 4, "IntN length should be 4");
3016 assert!(stored_cursor.remaining() >= 4, "need 4 bytes for INT data");
3017 let int1 = stored_cursor.get_i32_le();
3018 assert_eq!(int1, 42, "column 1 should be 42");
3019
3020 assert_eq!(
3022 stored_cursor.remaining(),
3023 0,
3024 "stored data should be fully consumed"
3025 );
3026 }
3027
3028 #[test]
3029 fn test_decode_nvarchar_max_then_intn_roundtrip() {
3030 let mut wire_data = BytesMut::new();
3034
3035 let word = "Hello";
3038 let utf16: Vec<u16> = word.encode_utf16().collect();
3039 let byte_len = (utf16.len() * 2) as u64;
3040
3041 wire_data.put_u64_le(byte_len); wire_data.put_u32_le(byte_len as u32); for code_unit in &utf16 {
3044 wire_data.put_u16_le(*code_unit);
3045 }
3046 wire_data.put_u32_le(0); wire_data.put_u8(4);
3050 wire_data.put_i32_le(99);
3051
3052 let metadata = ColMetaData {
3054 cek_table: None,
3055 columns: vec![
3056 ColumnData {
3057 name: "text".to_string(),
3058 type_id: TypeId::NVarChar,
3059 col_type: 0xE7,
3060 flags: 0x01,
3061 user_type: 0,
3062 type_info: TypeInfo {
3063 max_length: Some(0xFFFF), precision: None,
3065 scale: None,
3066 collation: None,
3067 },
3068 crypto_metadata: None,
3069 },
3070 ColumnData {
3071 name: "num".to_string(),
3072 type_id: TypeId::IntN,
3073 col_type: 0x26,
3074 flags: 0x01,
3075 user_type: 0,
3076 type_info: TypeInfo {
3077 max_length: Some(4),
3078 precision: None,
3079 scale: None,
3080 collation: None,
3081 },
3082 crypto_metadata: None,
3083 },
3084 ],
3085 };
3086
3087 let mut wire_cursor = wire_data.freeze();
3089 let raw_row = RawRow::decode(&mut wire_cursor, &metadata).unwrap();
3090
3091 assert_eq!(
3093 wire_cursor.remaining(),
3094 0,
3095 "wire data should be fully consumed"
3096 );
3097
3098 let mut stored_cursor: &[u8] = &raw_row.data;
3100
3101 let total_len = stored_cursor.get_u64_le();
3103 assert_eq!(total_len, 10, "PLP total length should be 10");
3104
3105 let chunk_len = stored_cursor.get_u32_le();
3106 assert_eq!(chunk_len, 10, "PLP chunk length should be 10");
3107
3108 let mut utf16_read = Vec::new();
3109 for _ in 0..(chunk_len / 2) {
3110 utf16_read.push(stored_cursor.get_u16_le());
3111 }
3112 let string0 = String::from_utf16(&utf16_read).unwrap();
3113 assert_eq!(string0, "Hello", "column 0 should be 'Hello'");
3114
3115 let terminator = stored_cursor.get_u32_le();
3116 assert_eq!(terminator, 0, "PLP should end with 0");
3117
3118 let len1 = stored_cursor.get_u8();
3120 assert_eq!(len1, 4);
3121 let int1 = stored_cursor.get_i32_le();
3122 assert_eq!(int1, 99, "column 1 should be 99");
3123
3124 assert_eq!(
3126 stored_cursor.remaining(),
3127 0,
3128 "stored data should be fully consumed"
3129 );
3130 }
3131
3132 #[test]
3137 fn test_return_status_via_parser() {
3138 let data = Bytes::from_static(&[
3140 0x79, 0x00, 0x00, 0x00, 0x00, ]);
3143
3144 let mut parser = TokenParser::new(data);
3145 let token = parser.next_token().unwrap().unwrap();
3146
3147 match token {
3148 Token::ReturnStatus(status) => {
3149 assert_eq!(status, 0);
3150 }
3151 _ => panic!("Expected ReturnStatus token, got {token:?}"),
3152 }
3153
3154 assert!(parser.next_token().unwrap().is_none());
3155 }
3156
3157 #[test]
3158 fn test_return_status_nonzero() {
3159 let mut buf = BytesMut::new();
3161 buf.put_u8(0x79); buf.put_i32_le(-6);
3163
3164 let mut parser = TokenParser::new(buf.freeze());
3165 let token = parser.next_token().unwrap().unwrap();
3166
3167 match token {
3168 Token::ReturnStatus(status) => {
3169 assert_eq!(status, -6);
3170 }
3171 _ => panic!("Expected ReturnStatus token"),
3172 }
3173 }
3174
3175 #[test]
3180 fn test_done_proc_roundtrip() {
3181 let done = DoneProc {
3182 status: DoneStatus {
3183 more: false,
3184 error: false,
3185 in_xact: false,
3186 count: true,
3187 attn: false,
3188 srverror: false,
3189 },
3190 cur_cmd: 0x00C6, row_count: 100,
3192 };
3193
3194 let mut buf = BytesMut::new();
3195 done.encode(&mut buf);
3196
3197 assert_eq!(buf[0], 0xFE);
3199
3200 let mut cursor = &buf[1..];
3202 let decoded = DoneProc::decode(&mut cursor).unwrap();
3203
3204 assert!(decoded.status.count);
3205 assert!(!decoded.status.more);
3206 assert!(!decoded.status.error);
3207 assert_eq!(decoded.cur_cmd, 0x00C6);
3208 assert_eq!(decoded.row_count, 100);
3209 }
3210
3211 #[test]
3212 fn test_done_proc_via_parser() {
3213 let data = Bytes::from_static(&[
3214 0xFE, 0x00, 0x00, 0xC6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ]);
3219
3220 let mut parser = TokenParser::new(data);
3221 let token = parser.next_token().unwrap().unwrap();
3222
3223 match token {
3224 Token::DoneProc(done) => {
3225 assert!(!done.status.count);
3226 assert!(!done.status.more);
3227 assert_eq!(done.cur_cmd, 198);
3228 assert_eq!(done.row_count, 0);
3229 }
3230 _ => panic!("Expected DoneProc token"),
3231 }
3232 }
3233
3234 #[test]
3235 fn test_done_proc_with_error_flag() {
3236 let mut buf = BytesMut::new();
3237 buf.put_u8(0xFE); buf.put_u16_le(0x0002); buf.put_u16_le(0x00C6); buf.put_u64_le(0); let mut parser = TokenParser::new(buf.freeze());
3243 let token = parser.next_token().unwrap().unwrap();
3244
3245 match token {
3246 Token::DoneProc(done) => {
3247 assert!(done.status.error);
3248 assert!(!done.status.count);
3249 assert!(!done.status.more);
3250 }
3251 _ => panic!("Expected DoneProc token"),
3252 }
3253 }
3254
3255 #[test]
3260 fn test_done_in_proc_roundtrip() {
3261 let done = DoneInProc {
3262 status: DoneStatus {
3263 more: true,
3264 error: false,
3265 in_xact: false,
3266 count: true,
3267 attn: false,
3268 srverror: false,
3269 },
3270 cur_cmd: 193, row_count: 7,
3272 };
3273
3274 let mut buf = BytesMut::new();
3275 done.encode(&mut buf);
3276
3277 assert_eq!(buf[0], 0xFF);
3278
3279 let mut cursor = &buf[1..];
3280 let decoded = DoneInProc::decode(&mut cursor).unwrap();
3281
3282 assert!(decoded.status.more);
3283 assert!(decoded.status.count);
3284 assert!(!decoded.status.error);
3285 assert_eq!(decoded.cur_cmd, 193);
3286 assert_eq!(decoded.row_count, 7);
3287 }
3288
3289 #[test]
3290 fn test_done_in_proc_via_parser() {
3291 let data = Bytes::from_static(&[
3292 0xFF, 0x11, 0x00, 0xC1, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ]);
3297
3298 let mut parser = TokenParser::new(data);
3299 let token = parser.next_token().unwrap().unwrap();
3300
3301 match token {
3302 Token::DoneInProc(done) => {
3303 assert!(done.status.more);
3304 assert!(done.status.count);
3305 assert_eq!(done.cur_cmd, 193);
3306 assert_eq!(done.row_count, 3);
3307 }
3308 _ => panic!("Expected DoneInProc token"),
3309 }
3310 }
3311
3312 #[test]
3317 fn test_server_error_decode() {
3318 let mut buf = BytesMut::new();
3321
3322 let msg_utf16: Vec<u16> = "Invalid column name 'foo'.".encode_utf16().collect();
3324 let srv_utf16: Vec<u16> = "SQLDB01".encode_utf16().collect();
3325 let proc_utf16: Vec<u16> = "".encode_utf16().collect();
3326
3327 let length: u16 = (4
3333 + 1
3334 + 1
3335 + 2
3336 + (msg_utf16.len() * 2)
3337 + 1
3338 + (srv_utf16.len() * 2)
3339 + 1
3340 + (proc_utf16.len() * 2)
3341 + 4) as u16;
3342
3343 buf.put_u16_le(length);
3344 buf.put_i32_le(207); buf.put_u8(1); buf.put_u8(16); buf.put_u16_le(msg_utf16.len() as u16);
3350 for &c in &msg_utf16 {
3351 buf.put_u16_le(c);
3352 }
3353
3354 buf.put_u8(srv_utf16.len() as u8);
3356 for &c in &srv_utf16 {
3357 buf.put_u16_le(c);
3358 }
3359
3360 buf.put_u8(proc_utf16.len() as u8);
3362
3363 buf.put_i32_le(42);
3365
3366 let mut cursor = buf.freeze();
3367 let error = ServerError::decode(&mut cursor).unwrap();
3368
3369 assert_eq!(error.number, 207);
3370 assert_eq!(error.state, 1);
3371 assert_eq!(error.class, 16);
3372 assert_eq!(error.message, "Invalid column name 'foo'.");
3373 assert_eq!(error.server, "SQLDB01");
3374 assert_eq!(error.procedure, "");
3375 assert_eq!(error.line, 42);
3376 }
3377
3378 #[test]
3379 fn test_server_error_severity_helpers() {
3380 let fatal = ServerError {
3381 number: 4014,
3382 state: 1,
3383 class: 20,
3384 message: "Fatal error".to_string(),
3385 server: String::new(),
3386 procedure: String::new(),
3387 line: 0,
3388 };
3389 assert!(fatal.is_fatal());
3390 assert!(fatal.is_batch_abort());
3391
3392 let batch_abort = ServerError {
3393 number: 547,
3394 state: 0,
3395 class: 16,
3396 message: "Constraint violation".to_string(),
3397 server: String::new(),
3398 procedure: String::new(),
3399 line: 1,
3400 };
3401 assert!(!batch_abort.is_fatal());
3402 assert!(batch_abort.is_batch_abort());
3403
3404 let informational = ServerError {
3405 number: 5701,
3406 state: 2,
3407 class: 10,
3408 message: "Changed db context".to_string(),
3409 server: String::new(),
3410 procedure: String::new(),
3411 line: 0,
3412 };
3413 assert!(!informational.is_fatal());
3414 assert!(!informational.is_batch_abort());
3415 }
3416
3417 #[test]
3418 fn test_server_error_via_parser() {
3419 let mut buf = BytesMut::new();
3421 buf.put_u8(0xAA); let msg_utf16: Vec<u16> = "Syntax error".encode_utf16().collect();
3424 let srv_utf16: Vec<u16> = "SRV".encode_utf16().collect();
3425 let proc_utf16: Vec<u16> = "sp_test".encode_utf16().collect();
3426
3427 let length: u16 = (4
3428 + 1
3429 + 1
3430 + 2
3431 + (msg_utf16.len() * 2)
3432 + 1
3433 + (srv_utf16.len() * 2)
3434 + 1
3435 + (proc_utf16.len() * 2)
3436 + 4) as u16;
3437
3438 buf.put_u16_le(length);
3439 buf.put_i32_le(102); buf.put_u8(1);
3441 buf.put_u8(15);
3442
3443 buf.put_u16_le(msg_utf16.len() as u16);
3444 for &c in &msg_utf16 {
3445 buf.put_u16_le(c);
3446 }
3447 buf.put_u8(srv_utf16.len() as u8);
3448 for &c in &srv_utf16 {
3449 buf.put_u16_le(c);
3450 }
3451 buf.put_u8(proc_utf16.len() as u8);
3452 for &c in &proc_utf16 {
3453 buf.put_u16_le(c);
3454 }
3455 buf.put_i32_le(5);
3456
3457 let mut parser = TokenParser::new(buf.freeze());
3458 let token = parser.next_token().unwrap().unwrap();
3459
3460 match token {
3461 Token::Error(err) => {
3462 assert_eq!(err.number, 102);
3463 assert_eq!(err.class, 15);
3464 assert_eq!(err.message, "Syntax error");
3465 assert_eq!(err.server, "SRV");
3466 assert_eq!(err.procedure, "sp_test");
3467 assert_eq!(err.line, 5);
3468 }
3469 _ => panic!("Expected Error token"),
3470 }
3471 }
3472
3473 fn build_return_value_intn(
3480 ordinal: u16,
3481 name: &str,
3482 status: u8,
3483 value: Option<i32>,
3484 ) -> BytesMut {
3485 let mut inner = BytesMut::new();
3486
3487 inner.put_u16_le(ordinal);
3489
3490 let name_utf16: Vec<u16> = name.encode_utf16().collect();
3492 inner.put_u8(name_utf16.len() as u8);
3493 for &c in &name_utf16 {
3494 inner.put_u16_le(c);
3495 }
3496
3497 inner.put_u8(status);
3499
3500 inner.put_u32_le(0);
3502
3503 inner.put_u16_le(0x0001); inner.put_u8(0x26);
3508
3509 inner.put_u8(4);
3511
3512 match value {
3514 Some(v) => {
3515 inner.put_u8(4); inner.put_i32_le(v);
3517 }
3518 None => {
3519 inner.put_u8(0); }
3521 }
3522
3523 inner
3526 }
3527
3528 #[test]
3529 fn test_return_value_int_output() {
3530 let buf = build_return_value_intn(1, "@result", 0x01, Some(42));
3531 let mut cursor = buf.freeze();
3532 let rv = ReturnValue::decode(&mut cursor).unwrap();
3533
3534 assert_eq!(rv.param_ordinal, 1);
3535 assert_eq!(rv.param_name, "@result");
3536 assert_eq!(rv.status, 0x01); assert_eq!(rv.col_type, 0x26); assert_eq!(rv.type_info.max_length, Some(4));
3539 assert_eq!(rv.value.len(), 5);
3541 assert_eq!(rv.value[0], 4);
3542 assert_eq!(
3543 i32::from_le_bytes([rv.value[1], rv.value[2], rv.value[3], rv.value[4]]),
3544 42
3545 );
3546 }
3547
3548 #[test]
3549 fn test_return_value_null_output() {
3550 let buf = build_return_value_intn(2, "@count", 0x01, None);
3551 let mut cursor = buf.freeze();
3552 let rv = ReturnValue::decode(&mut cursor).unwrap();
3553
3554 assert_eq!(rv.param_ordinal, 2);
3555 assert_eq!(rv.param_name, "@count");
3556 assert_eq!(rv.status, 0x01);
3557 assert_eq!(rv.col_type, 0x26);
3558 assert_eq!(rv.value.len(), 1);
3560 assert_eq!(rv.value[0], 0);
3561 }
3562
3563 #[test]
3564 fn test_return_value_udf_status() {
3565 let buf = build_return_value_intn(0, "@RETURN_VALUE", 0x02, Some(-1));
3567 let mut cursor = buf.freeze();
3568 let rv = ReturnValue::decode(&mut cursor).unwrap();
3569
3570 assert_eq!(rv.param_ordinal, 0);
3571 assert_eq!(rv.param_name, "@RETURN_VALUE");
3572 assert_eq!(rv.status, 0x02); assert_eq!(rv.value[0], 4);
3574 assert_eq!(
3575 i32::from_le_bytes([rv.value[1], rv.value[2], rv.value[3], rv.value[4]]),
3576 -1
3577 );
3578 }
3579
3580 #[test]
3581 fn test_return_value_nvarchar_output() {
3582 let mut inner = BytesMut::new();
3584
3585 inner.put_u16_le(1);
3587
3588 let name_utf16: Vec<u16> = "@name".encode_utf16().collect();
3590 inner.put_u8(name_utf16.len() as u8);
3591 for &c in &name_utf16 {
3592 inner.put_u16_le(c);
3593 }
3594
3595 inner.put_u8(0x01);
3597 inner.put_u32_le(0);
3599 inner.put_u16_le(0x0001);
3601 inner.put_u8(0xE7);
3603 inner.put_u16_le(200); inner.put_u32_le(0x0904D000); inner.put_u8(0x34); let val_utf16: Vec<u16> = "Hello".encode_utf16().collect();
3610 let byte_len = (val_utf16.len() * 2) as u16;
3611 inner.put_u16_le(byte_len);
3612 for &c in &val_utf16 {
3613 inner.put_u16_le(c);
3614 }
3615
3616 let mut cursor = inner.freeze();
3617 let rv = ReturnValue::decode(&mut cursor).unwrap();
3618
3619 assert_eq!(rv.param_ordinal, 1);
3620 assert_eq!(rv.param_name, "@name");
3621 assert_eq!(rv.status, 0x01);
3622 assert_eq!(rv.col_type, 0xE7); assert_eq!(rv.type_info.max_length, Some(200));
3624 assert!(rv.type_info.collation.is_some());
3625
3626 assert_eq!(rv.value.len(), 12); let val_len = u16::from_le_bytes([rv.value[0], rv.value[1]]);
3629 assert_eq!(val_len, 10);
3630 }
3631
3632 #[test]
3633 fn test_return_value_via_parser() {
3634 let mut data = BytesMut::new();
3636 data.put_u8(0xAC); data.extend_from_slice(&build_return_value_intn(0, "@out", 0x01, Some(99)));
3638
3639 let mut parser = TokenParser::new(data.freeze());
3640 let token = parser.next_token().unwrap().unwrap();
3641
3642 match token {
3643 Token::ReturnValue(rv) => {
3644 assert_eq!(rv.param_name, "@out");
3645 assert_eq!(rv.param_ordinal, 0);
3646 assert_eq!(rv.status, 0x01);
3647 assert_eq!(rv.col_type, 0x26);
3648 }
3649 _ => panic!("Expected ReturnValue token"),
3650 }
3651 }
3652
3653 #[test]
3658 fn test_multi_token_stored_proc_response() {
3659 let mut data = BytesMut::new();
3662
3663 data.put_u8(0xFF); data.put_u16_le(0x0010); data.put_u16_le(0x00C1); data.put_u64_le(3); data.put_u8(0x79); data.put_i32_le(0);
3672
3673 data.put_u8(0xFE); data.put_u16_le(0x0000); data.put_u16_le(0x00C6); data.put_u64_le(0);
3678
3679 let mut parser = TokenParser::new(data.freeze());
3680
3681 let t1 = parser.next_token().unwrap().unwrap();
3683 match t1 {
3684 Token::DoneInProc(done) => {
3685 assert!(done.status.count);
3686 assert_eq!(done.row_count, 3);
3687 assert_eq!(done.cur_cmd, 193);
3688 }
3689 _ => panic!("Expected DoneInProc, got {t1:?}"),
3690 }
3691
3692 let t2 = parser.next_token().unwrap().unwrap();
3694 match t2 {
3695 Token::ReturnStatus(status) => {
3696 assert_eq!(status, 0);
3697 }
3698 _ => panic!("Expected ReturnStatus, got {t2:?}"),
3699 }
3700
3701 let t3 = parser.next_token().unwrap().unwrap();
3703 match t3 {
3704 Token::DoneProc(done) => {
3705 assert!(!done.status.count);
3706 assert!(!done.status.more);
3707 assert_eq!(done.cur_cmd, 198);
3708 }
3709 _ => panic!("Expected DoneProc, got {t3:?}"),
3710 }
3711
3712 assert!(parser.next_token().unwrap().is_none());
3714 }
3715
3716 #[test]
3717 fn test_multi_token_error_in_stream() {
3718 let mut data = BytesMut::new();
3720
3721 data.put_u8(0xAA);
3723
3724 let msg_utf16: Vec<u16> = "Deadlock".encode_utf16().collect();
3725 let srv_utf16: Vec<u16> = "DB1".encode_utf16().collect();
3726
3727 let length: u16 = (4 + 1 + 1
3728 + 2 + (msg_utf16.len() * 2)
3729 + 1 + (srv_utf16.len() * 2)
3730 + 1 + 4) as u16;
3732
3733 data.put_u16_le(length);
3734 data.put_i32_le(1205); data.put_u8(51); data.put_u8(13); data.put_u16_le(msg_utf16.len() as u16);
3739 for &c in &msg_utf16 {
3740 data.put_u16_le(c);
3741 }
3742 data.put_u8(srv_utf16.len() as u8);
3743 for &c in &srv_utf16 {
3744 data.put_u16_le(c);
3745 }
3746 data.put_u8(0); data.put_i32_le(0);
3748
3749 data.put_u8(0xFD);
3751 data.put_u16_le(0x0002); data.put_u16_le(0x00C1); data.put_u64_le(0);
3754
3755 let mut parser = TokenParser::new(data.freeze());
3756
3757 let t1 = parser.next_token().unwrap().unwrap();
3759 match t1 {
3760 Token::Error(err) => {
3761 assert_eq!(err.number, 1205);
3762 assert_eq!(err.class, 13);
3763 assert_eq!(err.message, "Deadlock");
3764 assert_eq!(err.server, "DB1");
3765 }
3766 _ => panic!("Expected Error token, got {t1:?}"),
3767 }
3768
3769 let t2 = parser.next_token().unwrap().unwrap();
3771 match t2 {
3772 Token::Done(done) => {
3773 assert!(done.status.error);
3774 assert!(!done.status.count);
3775 }
3776 _ => panic!("Expected Done token, got {t2:?}"),
3777 }
3778
3779 assert!(parser.next_token().unwrap().is_none());
3780 }
3781
3782 #[test]
3783 fn test_multi_token_proc_with_return_value() {
3784 let mut data = BytesMut::new();
3786
3787 data.put_u8(0xAC);
3789 data.extend_from_slice(&build_return_value_intn(1, "@result", 0x01, Some(42)));
3790
3791 data.put_u8(0x79);
3793 data.put_i32_le(0);
3794
3795 data.put_u8(0xFE);
3797 data.put_u16_le(0x0000);
3798 data.put_u16_le(0x00C6);
3799 data.put_u64_le(0);
3800
3801 let mut parser = TokenParser::new(data.freeze());
3802
3803 let t1 = parser.next_token().unwrap().unwrap();
3804 match t1 {
3805 Token::ReturnValue(rv) => {
3806 assert_eq!(rv.param_name, "@result");
3807 assert_eq!(rv.param_ordinal, 1);
3808 }
3809 _ => panic!("Expected ReturnValue, got {t1:?}"),
3810 }
3811
3812 let t2 = parser.next_token().unwrap().unwrap();
3813 assert!(matches!(t2, Token::ReturnStatus(0)));
3814
3815 let t3 = parser.next_token().unwrap().unwrap();
3816 assert!(matches!(t3, Token::DoneProc(_)));
3817
3818 assert!(parser.next_token().unwrap().is_none());
3819 }
3820
3821 #[test]
3826 fn test_return_status_truncated() {
3827 let data = Bytes::from_static(&[0x79, 0x01, 0x02, 0x03]);
3829 let mut parser = TokenParser::new(data);
3830 assert!(parser.next_token().is_err());
3831 }
3832
3833 #[test]
3834 fn test_done_proc_truncated() {
3835 let data = Bytes::from_static(&[0xFE, 0x00, 0x00, 0xC1, 0x00, 0x01, 0x00, 0x00, 0x00]);
3837 let mut parser = TokenParser::new(data);
3838 assert!(parser.next_token().is_err());
3839 }
3840
3841 #[test]
3842 fn test_server_error_truncated() {
3843 let data = Bytes::from_static(&[0xAA, 0x20, 0x00]);
3845 let mut parser = TokenParser::new(data);
3846 assert!(parser.next_token().is_err());
3847 }
3848}