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 if self.sort_id != 0 {
289 return crate::collation::encoding_for_sort_id(self.sort_id);
290 }
291 crate::collation::encoding_for_lcid(self.lcid)
292 }
293
294 #[cfg(feature = "encoding")]
299 pub fn is_utf8(&self) -> bool {
300 crate::collation::is_utf8_collation(self.lcid)
301 }
302
303 #[cfg(feature = "encoding")]
311 pub fn code_page(&self) -> Option<u16> {
312 if self.sort_id != 0 {
315 return crate::collation::code_page_for_sort_id(self.sort_id);
316 }
317 crate::collation::code_page_for_lcid(self.lcid)
318 }
319
320 #[cfg(feature = "encoding")]
324 pub fn encoding_name(&self) -> &'static str {
325 if self.sort_id != 0 {
326 return match crate::collation::encoding_for_sort_id(self.sort_id) {
327 Some(enc) => enc.name(),
328 None => "unsupported",
329 };
330 }
331 crate::collation::encoding_name_for_lcid(self.lcid)
332 }
333}
334
335#[derive(Debug, Clone)]
337pub struct RawRow {
338 pub data: bytes::Bytes,
340}
341
342#[derive(Debug, Clone)]
344pub struct NbcRow {
345 pub null_bitmap: Vec<u8>,
347 pub data: bytes::Bytes,
349}
350
351#[derive(Debug, Clone, Copy)]
353pub struct Done {
354 pub status: DoneStatus,
356 pub cur_cmd: u16,
358 pub row_count: u64,
360}
361
362#[derive(Debug, Clone, Copy, Default)]
364#[non_exhaustive]
365pub struct DoneStatus {
366 pub more: bool,
368 pub error: bool,
370 pub in_xact: bool,
372 pub count: bool,
374 pub attn: bool,
376 pub srverror: bool,
378}
379
380#[derive(Debug, Clone, Copy)]
382pub struct DoneInProc {
383 pub status: DoneStatus,
385 pub cur_cmd: u16,
387 pub row_count: u64,
389}
390
391#[derive(Debug, Clone, Copy)]
393pub struct DoneProc {
394 pub status: DoneStatus,
396 pub cur_cmd: u16,
398 pub row_count: u64,
400}
401
402#[derive(Debug, Clone)]
404#[non_exhaustive]
405pub struct ReturnValue {
406 pub param_ordinal: u16,
408 pub param_name: String,
410 pub status: u8,
412 pub user_type: u32,
414 pub flags: u16,
416 pub col_type: u8,
418 pub type_info: TypeInfo,
420 pub value: bytes::Bytes,
422}
423
424#[derive(Debug, Clone)]
426pub struct ServerError {
427 pub number: i32,
429 pub state: u8,
431 pub class: u8,
433 pub message: String,
435 pub server: String,
437 pub procedure: String,
439 pub line: i32,
441}
442
443#[derive(Debug, Clone)]
445pub struct ServerInfo {
446 pub number: i32,
448 pub state: u8,
450 pub class: u8,
452 pub message: String,
454 pub server: String,
456 pub procedure: String,
458 pub line: i32,
460}
461
462#[derive(Debug, Clone)]
464pub struct LoginAck {
465 pub interface: u8,
467 pub tds_version: u32,
469 pub prog_name: String,
471 pub prog_version: u32,
473}
474
475#[derive(Debug, Clone)]
477pub struct EnvChange {
478 pub env_type: EnvChangeType,
480 pub new_value: EnvChangeValue,
482 pub old_value: EnvChangeValue,
484}
485
486#[derive(Debug, Clone, Copy, PartialEq, Eq)]
488#[repr(u8)]
489#[non_exhaustive]
490pub enum EnvChangeType {
491 Database = 1,
493 Language = 2,
495 CharacterSet = 3,
497 PacketSize = 4,
499 UnicodeSortingLocalId = 5,
501 UnicodeComparisonFlags = 6,
503 SqlCollation = 7,
505 BeginTransaction = 8,
507 CommitTransaction = 9,
509 RollbackTransaction = 10,
511 EnlistDtcTransaction = 11,
513 DefectTransaction = 12,
515 RealTimeLogShipping = 13,
517 PromoteTransaction = 15,
519 TransactionManagerAddress = 16,
521 TransactionEnded = 17,
523 ResetConnectionCompletionAck = 18,
525 UserInstanceStarted = 19,
527 Routing = 20,
529}
530
531#[derive(Debug, Clone)]
533#[non_exhaustive]
534pub enum EnvChangeValue {
535 String(String),
537 Binary(bytes::Bytes),
539 Routing {
541 host: String,
543 port: u16,
545 },
546}
547
548#[derive(Debug, Clone)]
550pub struct Order {
551 pub columns: Vec<u16>,
553}
554
555#[derive(Debug, Clone)]
557pub struct FeatureExtAck {
558 pub features: Vec<FeatureAck>,
560}
561
562#[derive(Debug, Clone)]
564pub struct FeatureAck {
565 pub feature_id: u8,
567 pub data: bytes::Bytes,
569}
570
571#[derive(Debug, Clone)]
573pub struct SspiToken {
574 pub data: bytes::Bytes,
576}
577
578#[derive(Debug, Clone)]
580pub struct SessionState {
581 pub data: bytes::Bytes,
583}
584
585#[derive(Debug, Clone)]
587pub struct FedAuthInfo {
588 pub sts_url: String,
590 pub spn: String,
592}
593
594pub(crate) fn decode_collation(src: &mut impl Buf) -> Result<Collation, ProtocolError> {
602 if src.remaining() < 5 {
603 return Err(ProtocolError::UnexpectedEof);
604 }
605 let lcid = src.get_u32_le();
607 let sort_id = src.get_u8();
608 Ok(Collation { lcid, sort_id })
609}
610
611pub(crate) fn decode_type_info(
615 src: &mut impl Buf,
616 type_id: TypeId,
617 col_type: u8,
618) -> Result<TypeInfo, ProtocolError> {
619 match type_id {
620 TypeId::Null => Ok(TypeInfo::default()),
622 TypeId::Int1 | TypeId::Bit => Ok(TypeInfo::default()),
623 TypeId::Int2 => Ok(TypeInfo::default()),
624 TypeId::Int4 => Ok(TypeInfo::default()),
625 TypeId::Int8 => Ok(TypeInfo::default()),
626 TypeId::Float4 => Ok(TypeInfo::default()),
627 TypeId::Float8 => Ok(TypeInfo::default()),
628 TypeId::Money => Ok(TypeInfo::default()),
629 TypeId::Money4 => Ok(TypeInfo::default()),
630 TypeId::DateTime => Ok(TypeInfo::default()),
631 TypeId::DateTime4 => Ok(TypeInfo::default()),
632
633 TypeId::IntN | TypeId::BitN | TypeId::FloatN | TypeId::MoneyN | TypeId::DateTimeN => {
635 if src.remaining() < 1 {
636 return Err(ProtocolError::UnexpectedEof);
637 }
638 let max_length = src.get_u8() as u32;
639 Ok(TypeInfo {
640 max_length: Some(max_length),
641 ..Default::default()
642 })
643 }
644
645 TypeId::Guid => {
647 if src.remaining() < 1 {
648 return Err(ProtocolError::UnexpectedEof);
649 }
650 let max_length = src.get_u8() as u32;
651 Ok(TypeInfo {
652 max_length: Some(max_length),
653 ..Default::default()
654 })
655 }
656
657 TypeId::Decimal | TypeId::Numeric | TypeId::DecimalN | TypeId::NumericN => {
659 if src.remaining() < 3 {
660 return Err(ProtocolError::UnexpectedEof);
661 }
662 let max_length = src.get_u8() as u32;
663 let precision = src.get_u8();
664 let scale = src.get_u8();
665 Ok(TypeInfo {
666 max_length: Some(max_length),
667 precision: Some(precision),
668 scale: Some(scale),
669 ..Default::default()
670 })
671 }
672
673 TypeId::Char | TypeId::VarChar | TypeId::Binary | TypeId::VarBinary => {
675 if src.remaining() < 1 {
676 return Err(ProtocolError::UnexpectedEof);
677 }
678 let max_length = src.get_u8() as u32;
679 Ok(TypeInfo {
680 max_length: Some(max_length),
681 ..Default::default()
682 })
683 }
684
685 TypeId::BigVarChar | TypeId::BigChar => {
687 if src.remaining() < 7 {
688 return Err(ProtocolError::UnexpectedEof);
690 }
691 let max_length = src.get_u16_le() as u32;
692 let collation = decode_collation(src)?;
693 Ok(TypeInfo {
694 max_length: Some(max_length),
695 collation: Some(collation),
696 ..Default::default()
697 })
698 }
699
700 TypeId::BigVarBinary | TypeId::BigBinary => {
702 if src.remaining() < 2 {
703 return Err(ProtocolError::UnexpectedEof);
704 }
705 let max_length = src.get_u16_le() as u32;
706 Ok(TypeInfo {
707 max_length: Some(max_length),
708 ..Default::default()
709 })
710 }
711
712 TypeId::NChar | TypeId::NVarChar => {
714 if src.remaining() < 7 {
715 return Err(ProtocolError::UnexpectedEof);
717 }
718 let max_length = src.get_u16_le() as u32;
719 let collation = decode_collation(src)?;
720 Ok(TypeInfo {
721 max_length: Some(max_length),
722 collation: Some(collation),
723 ..Default::default()
724 })
725 }
726
727 TypeId::Date => Ok(TypeInfo::default()),
729
730 TypeId::Time | TypeId::DateTime2 | TypeId::DateTimeOffset => {
732 if src.remaining() < 1 {
733 return Err(ProtocolError::UnexpectedEof);
734 }
735 let scale = src.get_u8();
736 Ok(TypeInfo {
737 scale: Some(scale),
738 ..Default::default()
739 })
740 }
741
742 TypeId::Text | TypeId::NText | TypeId::Image => {
744 if src.remaining() < 4 {
746 return Err(ProtocolError::UnexpectedEof);
747 }
748 let max_length = src.get_u32_le();
749
750 let collation = if type_id == TypeId::Text || type_id == TypeId::NText {
752 if src.remaining() < 5 {
753 return Err(ProtocolError::UnexpectedEof);
754 }
755 Some(decode_collation(src)?)
756 } else {
757 None
758 };
759
760 if src.remaining() < 1 {
763 return Err(ProtocolError::UnexpectedEof);
764 }
765 let num_parts = src.get_u8();
766 for _ in 0..num_parts {
767 let _ = read_us_varchar(src).ok_or(ProtocolError::UnexpectedEof)?;
769 }
770
771 Ok(TypeInfo {
772 max_length: Some(max_length),
773 collation,
774 ..Default::default()
775 })
776 }
777
778 TypeId::Xml => {
780 if src.remaining() < 1 {
781 return Err(ProtocolError::UnexpectedEof);
782 }
783 let schema_present = src.get_u8();
784
785 if schema_present != 0 {
786 let _ = read_b_varchar(src).ok_or(ProtocolError::UnexpectedEof)?; let _ = read_b_varchar(src).ok_or(ProtocolError::UnexpectedEof)?; let _ = read_us_varchar(src).ok_or(ProtocolError::UnexpectedEof)?; }
793
794 Ok(TypeInfo::default())
795 }
796
797 TypeId::Udt => {
799 if src.remaining() < 2 {
801 return Err(ProtocolError::UnexpectedEof);
802 }
803 let max_length = src.get_u16_le() as u32;
804
805 let _ = read_b_varchar(src).ok_or(ProtocolError::UnexpectedEof)?; let _ = read_b_varchar(src).ok_or(ProtocolError::UnexpectedEof)?; let _ = read_b_varchar(src).ok_or(ProtocolError::UnexpectedEof)?; let _ = read_us_varchar(src).ok_or(ProtocolError::UnexpectedEof)?; Ok(TypeInfo {
814 max_length: Some(max_length),
815 ..Default::default()
816 })
817 }
818
819 TypeId::Tvp => {
821 Err(ProtocolError::InvalidTokenType(col_type))
824 }
825
826 TypeId::Variant => {
828 if src.remaining() < 4 {
829 return Err(ProtocolError::UnexpectedEof);
830 }
831 let max_length = src.get_u32_le();
832 Ok(TypeInfo {
833 max_length: Some(max_length),
834 ..Default::default()
835 })
836 }
837 }
838}
839
840impl ColMetaData {
841 pub const NO_METADATA: u16 = 0xFFFF;
843
844 pub fn decode(src: &mut impl Buf) -> Result<Self, ProtocolError> {
846 if src.remaining() < 2 {
847 return Err(ProtocolError::UnexpectedEof);
848 }
849
850 let column_count = src.get_u16_le();
851
852 if column_count == Self::NO_METADATA {
854 return Ok(Self {
855 columns: Vec::new(),
856 cek_table: None,
857 });
858 }
859
860 let mut columns = Vec::with_capacity(column_count as usize);
861
862 for _ in 0..column_count {
863 let column = Self::decode_column(src)?;
864 columns.push(column);
865 }
866
867 Ok(Self {
868 columns,
869 cek_table: None,
870 })
871 }
872
873 fn decode_column(src: &mut impl Buf) -> Result<ColumnData, ProtocolError> {
875 if src.remaining() < 7 {
877 return Err(ProtocolError::UnexpectedEof);
878 }
879
880 let user_type = src.get_u32_le();
881 let flags = src.get_u16_le();
882 let col_type = src.get_u8();
883
884 let type_id = TypeId::from_u8(col_type).ok_or(ProtocolError::InvalidDataType(col_type))?;
888
889 let type_info = decode_type_info(src, type_id, col_type)?;
891
892 let name = read_b_varchar(src).ok_or(ProtocolError::UnexpectedEof)?;
894
895 Ok(ColumnData {
896 name,
897 type_id,
898 col_type,
899 flags,
900 user_type,
901 type_info,
902 crypto_metadata: None,
903 })
904 }
905
906 pub fn decode_encrypted(src: &mut impl Buf) -> Result<Self, ProtocolError> {
919 if src.remaining() < 2 {
920 return Err(ProtocolError::UnexpectedEof);
921 }
922
923 let column_count = src.get_u16_le();
924
925 if column_count == Self::NO_METADATA {
926 return Ok(Self {
927 columns: Vec::new(),
928 cek_table: None,
929 });
930 }
931
932 let cek_table = crate::crypto::CekTable::decode(src)?;
934
935 let mut columns = Vec::with_capacity(column_count as usize);
936
937 for _ in 0..column_count {
938 let column = Self::decode_column_encrypted(src)?;
939 columns.push(column);
940 }
941
942 Ok(Self {
943 columns,
944 cek_table: Some(cek_table),
945 })
946 }
947
948 fn decode_column_encrypted(src: &mut impl Buf) -> Result<ColumnData, ProtocolError> {
952 if src.remaining() < 7 {
953 return Err(ProtocolError::UnexpectedEof);
954 }
955
956 let user_type = src.get_u32_le();
957 let flags = src.get_u16_le();
958 let col_type = src.get_u8();
959
960 let type_id = TypeId::from_u8(col_type).ok_or(ProtocolError::InvalidDataType(col_type))?;
961
962 let type_info = decode_type_info(src, type_id, col_type)?;
964
965 let crypto_metadata = if crate::crypto::is_column_encrypted(flags) {
967 Some(crate::crypto::CryptoMetadata::decode(src)?)
968 } else {
969 None
970 };
971
972 let name = read_b_varchar(src).ok_or(ProtocolError::UnexpectedEof)?;
974
975 Ok(ColumnData {
976 name,
977 type_id,
978 col_type,
979 flags,
980 user_type,
981 type_info,
982 crypto_metadata,
983 })
984 }
985
986 #[must_use]
988 pub fn column_count(&self) -> usize {
989 self.columns.len()
990 }
991
992 #[must_use]
994 pub fn is_empty(&self) -> bool {
995 self.columns.is_empty()
996 }
997}
998
999impl ColumnData {
1000 #[must_use]
1002 pub fn is_nullable(&self) -> bool {
1003 (self.flags & 0x0001) != 0
1004 }
1005
1006 #[must_use]
1010 pub fn fixed_size(&self) -> Option<usize> {
1011 match self.type_id {
1012 TypeId::Null => Some(0),
1013 TypeId::Int1 | TypeId::Bit => Some(1),
1014 TypeId::Int2 => Some(2),
1015 TypeId::Int4 => Some(4),
1016 TypeId::Int8 => Some(8),
1017 TypeId::Float4 => Some(4),
1018 TypeId::Float8 => Some(8),
1019 TypeId::Money => Some(8),
1020 TypeId::Money4 => Some(4),
1021 TypeId::DateTime => Some(8),
1022 TypeId::DateTime4 => Some(4),
1023 TypeId::Date => Some(3),
1024 _ => None,
1025 }
1026 }
1027}
1028
1029impl RawRow {
1034 pub fn decode(src: &mut impl Buf, metadata: &ColMetaData) -> Result<Self, ProtocolError> {
1039 let mut data = bytes::BytesMut::new();
1040
1041 for col in &metadata.columns {
1042 Self::decode_column_value(src, col, &mut data)?;
1043 }
1044
1045 Ok(Self {
1046 data: data.freeze(),
1047 })
1048 }
1049
1050 fn decode_column_value(
1052 src: &mut impl Buf,
1053 col: &ColumnData,
1054 dst: &mut bytes::BytesMut,
1055 ) -> Result<(), ProtocolError> {
1056 match col.type_id {
1057 TypeId::Null => {
1059 }
1061 TypeId::Int1 | TypeId::Bit => {
1062 if src.remaining() < 1 {
1063 return Err(ProtocolError::UnexpectedEof);
1064 }
1065 dst.extend_from_slice(&[src.get_u8()]);
1066 }
1067 TypeId::Int2 => {
1068 if src.remaining() < 2 {
1069 return Err(ProtocolError::UnexpectedEof);
1070 }
1071 dst.extend_from_slice(&src.get_u16_le().to_le_bytes());
1072 }
1073 TypeId::Int4 => {
1074 if src.remaining() < 4 {
1075 return Err(ProtocolError::UnexpectedEof);
1076 }
1077 dst.extend_from_slice(&src.get_u32_le().to_le_bytes());
1078 }
1079 TypeId::Int8 => {
1080 if src.remaining() < 8 {
1081 return Err(ProtocolError::UnexpectedEof);
1082 }
1083 dst.extend_from_slice(&src.get_u64_le().to_le_bytes());
1084 }
1085 TypeId::Float4 => {
1086 if src.remaining() < 4 {
1087 return Err(ProtocolError::UnexpectedEof);
1088 }
1089 dst.extend_from_slice(&src.get_u32_le().to_le_bytes());
1090 }
1091 TypeId::Float8 => {
1092 if src.remaining() < 8 {
1093 return Err(ProtocolError::UnexpectedEof);
1094 }
1095 dst.extend_from_slice(&src.get_u64_le().to_le_bytes());
1096 }
1097 TypeId::Money => {
1098 if src.remaining() < 8 {
1099 return Err(ProtocolError::UnexpectedEof);
1100 }
1101 let hi = src.get_u32_le();
1102 let lo = src.get_u32_le();
1103 dst.extend_from_slice(&hi.to_le_bytes());
1104 dst.extend_from_slice(&lo.to_le_bytes());
1105 }
1106 TypeId::Money4 => {
1107 if src.remaining() < 4 {
1108 return Err(ProtocolError::UnexpectedEof);
1109 }
1110 dst.extend_from_slice(&src.get_u32_le().to_le_bytes());
1111 }
1112 TypeId::DateTime => {
1113 if src.remaining() < 8 {
1114 return Err(ProtocolError::UnexpectedEof);
1115 }
1116 let days = src.get_u32_le();
1117 let time = src.get_u32_le();
1118 dst.extend_from_slice(&days.to_le_bytes());
1119 dst.extend_from_slice(&time.to_le_bytes());
1120 }
1121 TypeId::DateTime4 => {
1122 if src.remaining() < 4 {
1123 return Err(ProtocolError::UnexpectedEof);
1124 }
1125 dst.extend_from_slice(&src.get_u32_le().to_le_bytes());
1126 }
1127 TypeId::Date => {
1129 Self::decode_bytelen_type(src, dst)?;
1130 }
1131
1132 TypeId::IntN | TypeId::BitN | TypeId::FloatN | TypeId::MoneyN | TypeId::DateTimeN => {
1134 Self::decode_bytelen_type(src, dst)?;
1135 }
1136
1137 TypeId::Guid => {
1138 Self::decode_bytelen_type(src, dst)?;
1139 }
1140
1141 TypeId::Decimal | TypeId::Numeric | TypeId::DecimalN | TypeId::NumericN => {
1142 Self::decode_bytelen_type(src, dst)?;
1143 }
1144
1145 TypeId::Char | TypeId::VarChar | TypeId::Binary | TypeId::VarBinary => {
1147 Self::decode_bytelen_type(src, dst)?;
1148 }
1149
1150 TypeId::BigVarChar | TypeId::BigVarBinary => {
1152 if col.type_info.max_length == Some(0xFFFF) {
1154 Self::decode_plp_type(src, dst)?;
1155 } else {
1156 Self::decode_ushortlen_type(src, dst)?;
1157 }
1158 }
1159
1160 TypeId::BigChar | TypeId::BigBinary => {
1162 Self::decode_ushortlen_type(src, dst)?;
1163 }
1164
1165 TypeId::NVarChar => {
1167 if col.type_info.max_length == Some(0xFFFF) {
1169 Self::decode_plp_type(src, dst)?;
1170 } else {
1171 Self::decode_ushortlen_type(src, dst)?;
1172 }
1173 }
1174
1175 TypeId::NChar => {
1177 Self::decode_ushortlen_type(src, dst)?;
1178 }
1179
1180 TypeId::Time | TypeId::DateTime2 | TypeId::DateTimeOffset => {
1182 Self::decode_bytelen_type(src, dst)?;
1183 }
1184
1185 TypeId::Text | TypeId::NText | TypeId::Image => {
1187 Self::decode_textptr_type(src, dst)?;
1188 }
1189
1190 TypeId::Xml => {
1192 Self::decode_plp_type(src, dst)?;
1193 }
1194
1195 TypeId::Variant => {
1197 Self::decode_intlen_type(src, dst)?;
1198 }
1199
1200 TypeId::Udt => {
1201 Self::decode_plp_type(src, dst)?;
1203 }
1204
1205 TypeId::Tvp => {
1206 return Err(ProtocolError::InvalidTokenType(col.col_type));
1208 }
1209 }
1210
1211 Ok(())
1212 }
1213
1214 fn decode_bytelen_type(
1216 src: &mut impl Buf,
1217 dst: &mut bytes::BytesMut,
1218 ) -> Result<(), ProtocolError> {
1219 if src.remaining() < 1 {
1220 return Err(ProtocolError::UnexpectedEof);
1221 }
1222 let len = src.get_u8() as usize;
1223 if len == 0xFF {
1224 dst.extend_from_slice(&[0xFF]);
1226 } else if len == 0 {
1227 dst.extend_from_slice(&[0x00]);
1229 } else {
1230 if src.remaining() < len {
1231 return Err(ProtocolError::UnexpectedEof);
1232 }
1233 dst.extend_from_slice(&[len as u8]);
1234 for _ in 0..len {
1235 dst.extend_from_slice(&[src.get_u8()]);
1236 }
1237 }
1238 Ok(())
1239 }
1240
1241 fn decode_ushortlen_type(
1243 src: &mut impl Buf,
1244 dst: &mut bytes::BytesMut,
1245 ) -> Result<(), ProtocolError> {
1246 if src.remaining() < 2 {
1247 return Err(ProtocolError::UnexpectedEof);
1248 }
1249 let len = src.get_u16_le() as usize;
1250 if len == 0xFFFF {
1251 dst.extend_from_slice(&0xFFFFu16.to_le_bytes());
1253 } else if len == 0 {
1254 dst.extend_from_slice(&0u16.to_le_bytes());
1256 } else {
1257 if src.remaining() < len {
1258 return Err(ProtocolError::UnexpectedEof);
1259 }
1260 dst.extend_from_slice(&(len as u16).to_le_bytes());
1261 for _ in 0..len {
1262 dst.extend_from_slice(&[src.get_u8()]);
1263 }
1264 }
1265 Ok(())
1266 }
1267
1268 fn decode_intlen_type(
1270 src: &mut impl Buf,
1271 dst: &mut bytes::BytesMut,
1272 ) -> Result<(), ProtocolError> {
1273 if src.remaining() < 4 {
1274 return Err(ProtocolError::UnexpectedEof);
1275 }
1276 let len = src.get_u32_le() as usize;
1277 if len == 0xFFFFFFFF {
1278 dst.extend_from_slice(&0xFFFFFFFFu32.to_le_bytes());
1280 } else if len == 0 {
1281 dst.extend_from_slice(&0u32.to_le_bytes());
1283 } else {
1284 if src.remaining() < len {
1285 return Err(ProtocolError::UnexpectedEof);
1286 }
1287 dst.extend_from_slice(&(len as u32).to_le_bytes());
1288 for _ in 0..len {
1289 dst.extend_from_slice(&[src.get_u8()]);
1290 }
1291 }
1292 Ok(())
1293 }
1294
1295 fn decode_textptr_type(
1310 src: &mut impl Buf,
1311 dst: &mut bytes::BytesMut,
1312 ) -> Result<(), ProtocolError> {
1313 if src.remaining() < 1 {
1314 return Err(ProtocolError::UnexpectedEof);
1315 }
1316
1317 let textptr_len = src.get_u8() as usize;
1318
1319 if textptr_len == 0 {
1320 dst.extend_from_slice(&0xFFFFFFFFFFFFFFFFu64.to_le_bytes());
1322 return Ok(());
1323 }
1324
1325 if src.remaining() < textptr_len {
1327 return Err(ProtocolError::UnexpectedEof);
1328 }
1329 src.advance(textptr_len);
1330
1331 if src.remaining() < 8 {
1333 return Err(ProtocolError::UnexpectedEof);
1334 }
1335 src.advance(8);
1336
1337 if src.remaining() < 4 {
1339 return Err(ProtocolError::UnexpectedEof);
1340 }
1341 let data_len = src.get_u32_le() as usize;
1342
1343 if src.remaining() < data_len {
1344 return Err(ProtocolError::UnexpectedEof);
1345 }
1346
1347 dst.extend_from_slice(&(data_len as u64).to_le_bytes());
1353 dst.extend_from_slice(&(data_len as u32).to_le_bytes());
1354 for _ in 0..data_len {
1355 dst.extend_from_slice(&[src.get_u8()]);
1356 }
1357 dst.extend_from_slice(&0u32.to_le_bytes()); Ok(())
1360 }
1361
1362 fn decode_plp_type(src: &mut impl Buf, dst: &mut bytes::BytesMut) -> Result<(), ProtocolError> {
1368 if src.remaining() < 8 {
1369 return Err(ProtocolError::UnexpectedEof);
1370 }
1371
1372 let total_len = src.get_u64_le();
1373
1374 dst.extend_from_slice(&total_len.to_le_bytes());
1376
1377 if total_len == 0xFFFFFFFFFFFFFFFF {
1378 return Ok(());
1380 }
1381
1382 loop {
1384 if src.remaining() < 4 {
1385 return Err(ProtocolError::UnexpectedEof);
1386 }
1387 let chunk_len = src.get_u32_le() as usize;
1388 dst.extend_from_slice(&(chunk_len as u32).to_le_bytes());
1389
1390 if chunk_len == 0 {
1391 break;
1393 }
1394
1395 if src.remaining() < chunk_len {
1396 return Err(ProtocolError::UnexpectedEof);
1397 }
1398
1399 for _ in 0..chunk_len {
1400 dst.extend_from_slice(&[src.get_u8()]);
1401 }
1402 }
1403
1404 Ok(())
1405 }
1406}
1407
1408impl NbcRow {
1413 pub fn decode(src: &mut impl Buf, metadata: &ColMetaData) -> Result<Self, ProtocolError> {
1418 let col_count = metadata.columns.len();
1419 let bitmap_len = col_count.div_ceil(8);
1420
1421 if src.remaining() < bitmap_len {
1422 return Err(ProtocolError::UnexpectedEof);
1423 }
1424
1425 let mut null_bitmap = vec![0u8; bitmap_len];
1427 for byte in &mut null_bitmap {
1428 *byte = src.get_u8();
1429 }
1430
1431 let mut data = bytes::BytesMut::new();
1433
1434 for (i, col) in metadata.columns.iter().enumerate() {
1435 let byte_idx = i / 8;
1436 let bit_idx = i % 8;
1437 let is_null = (null_bitmap[byte_idx] & (1 << bit_idx)) != 0;
1438
1439 if !is_null {
1440 RawRow::decode_column_value(src, col, &mut data)?;
1443 }
1444 }
1445
1446 Ok(Self {
1447 null_bitmap,
1448 data: data.freeze(),
1449 })
1450 }
1451
1452 #[must_use]
1454 pub fn is_null(&self, column_index: usize) -> bool {
1455 let byte_idx = column_index / 8;
1456 let bit_idx = column_index % 8;
1457 if byte_idx < self.null_bitmap.len() {
1458 (self.null_bitmap[byte_idx] & (1 << bit_idx)) != 0
1459 } else {
1460 true }
1462 }
1463}
1464
1465impl ReturnValue {
1470 pub fn decode(src: &mut impl Buf) -> Result<Self, ProtocolError> {
1472 if src.remaining() < 2 {
1479 return Err(ProtocolError::UnexpectedEof);
1480 }
1481 let param_ordinal = src.get_u16_le();
1482
1483 let param_name = read_b_varchar(src).ok_or(ProtocolError::UnexpectedEof)?;
1485
1486 if src.remaining() < 1 {
1488 return Err(ProtocolError::UnexpectedEof);
1489 }
1490 let status = src.get_u8();
1491
1492 if src.remaining() < 7 {
1494 return Err(ProtocolError::UnexpectedEof);
1495 }
1496 let user_type = src.get_u32_le();
1497 let flags = src.get_u16_le();
1498 let col_type = src.get_u8();
1499
1500 let type_id = TypeId::from_u8(col_type).ok_or(ProtocolError::InvalidDataType(col_type))?;
1501
1502 let type_info = decode_type_info(src, type_id, col_type)?;
1504
1505 let mut value_buf = bytes::BytesMut::new();
1507
1508 let temp_col = ColumnData {
1510 name: String::new(),
1511 type_id,
1512 col_type,
1513 flags,
1514 user_type,
1515 type_info: type_info.clone(),
1516 crypto_metadata: None,
1517 };
1518
1519 RawRow::decode_column_value(src, &temp_col, &mut value_buf)?;
1520
1521 Ok(Self {
1522 param_ordinal,
1523 param_name,
1524 status,
1525 user_type,
1526 flags,
1527 col_type,
1528 type_info,
1529 value: value_buf.freeze(),
1530 })
1531 }
1532}
1533
1534impl SessionState {
1539 pub fn decode(src: &mut impl Buf) -> Result<Self, ProtocolError> {
1541 if src.remaining() < 4 {
1542 return Err(ProtocolError::UnexpectedEof);
1543 }
1544
1545 let length = src.get_u32_le() as usize;
1546
1547 if src.remaining() < length {
1548 return Err(ProtocolError::IncompletePacket {
1549 expected: length,
1550 actual: src.remaining(),
1551 });
1552 }
1553
1554 let data = src.copy_to_bytes(length);
1555
1556 Ok(Self { data })
1557 }
1558}
1559
1560mod done_status_bits {
1566 pub const DONE_MORE: u16 = 0x0001;
1567 pub const DONE_ERROR: u16 = 0x0002;
1568 pub const DONE_INXACT: u16 = 0x0004;
1569 pub const DONE_COUNT: u16 = 0x0010;
1570 pub const DONE_ATTN: u16 = 0x0020;
1571 pub const DONE_SRVERROR: u16 = 0x0100;
1572}
1573
1574impl DoneStatus {
1575 #[must_use]
1577 pub fn from_bits(bits: u16) -> Self {
1578 use done_status_bits::*;
1579 Self {
1580 more: (bits & DONE_MORE) != 0,
1581 error: (bits & DONE_ERROR) != 0,
1582 in_xact: (bits & DONE_INXACT) != 0,
1583 count: (bits & DONE_COUNT) != 0,
1584 attn: (bits & DONE_ATTN) != 0,
1585 srverror: (bits & DONE_SRVERROR) != 0,
1586 }
1587 }
1588
1589 #[must_use]
1591 pub fn to_bits(&self) -> u16 {
1592 use done_status_bits::*;
1593 let mut bits = 0u16;
1594 if self.more {
1595 bits |= DONE_MORE;
1596 }
1597 if self.error {
1598 bits |= DONE_ERROR;
1599 }
1600 if self.in_xact {
1601 bits |= DONE_INXACT;
1602 }
1603 if self.count {
1604 bits |= DONE_COUNT;
1605 }
1606 if self.attn {
1607 bits |= DONE_ATTN;
1608 }
1609 if self.srverror {
1610 bits |= DONE_SRVERROR;
1611 }
1612 bits
1613 }
1614}
1615
1616impl Done {
1617 pub const SIZE: usize = 12; pub fn decode(src: &mut impl Buf) -> Result<Self, ProtocolError> {
1622 if src.remaining() < Self::SIZE {
1623 return Err(ProtocolError::IncompletePacket {
1624 expected: Self::SIZE,
1625 actual: src.remaining(),
1626 });
1627 }
1628
1629 let status = DoneStatus::from_bits(src.get_u16_le());
1630 let cur_cmd = src.get_u16_le();
1631 let row_count = src.get_u64_le();
1632
1633 Ok(Self {
1634 status,
1635 cur_cmd,
1636 row_count,
1637 })
1638 }
1639
1640 pub fn encode(&self, dst: &mut impl BufMut) {
1642 dst.put_u8(TokenType::Done as u8);
1643 dst.put_u16_le(self.status.to_bits());
1644 dst.put_u16_le(self.cur_cmd);
1645 dst.put_u64_le(self.row_count);
1646 }
1647
1648 #[must_use]
1650 pub const fn has_more(&self) -> bool {
1651 self.status.more
1652 }
1653
1654 #[must_use]
1656 pub const fn has_error(&self) -> bool {
1657 self.status.error
1658 }
1659
1660 #[must_use]
1662 pub const fn has_count(&self) -> bool {
1663 self.status.count
1664 }
1665}
1666
1667impl DoneProc {
1668 pub const SIZE: usize = 12;
1670
1671 pub fn decode(src: &mut impl Buf) -> Result<Self, ProtocolError> {
1673 if src.remaining() < Self::SIZE {
1674 return Err(ProtocolError::IncompletePacket {
1675 expected: Self::SIZE,
1676 actual: src.remaining(),
1677 });
1678 }
1679
1680 let status = DoneStatus::from_bits(src.get_u16_le());
1681 let cur_cmd = src.get_u16_le();
1682 let row_count = src.get_u64_le();
1683
1684 Ok(Self {
1685 status,
1686 cur_cmd,
1687 row_count,
1688 })
1689 }
1690
1691 pub fn encode(&self, dst: &mut impl BufMut) {
1693 dst.put_u8(TokenType::DoneProc as u8);
1694 dst.put_u16_le(self.status.to_bits());
1695 dst.put_u16_le(self.cur_cmd);
1696 dst.put_u64_le(self.row_count);
1697 }
1698}
1699
1700impl DoneInProc {
1701 pub const SIZE: usize = 12;
1703
1704 pub fn decode(src: &mut impl Buf) -> Result<Self, ProtocolError> {
1706 if src.remaining() < Self::SIZE {
1707 return Err(ProtocolError::IncompletePacket {
1708 expected: Self::SIZE,
1709 actual: src.remaining(),
1710 });
1711 }
1712
1713 let status = DoneStatus::from_bits(src.get_u16_le());
1714 let cur_cmd = src.get_u16_le();
1715 let row_count = src.get_u64_le();
1716
1717 Ok(Self {
1718 status,
1719 cur_cmd,
1720 row_count,
1721 })
1722 }
1723
1724 pub fn encode(&self, dst: &mut impl BufMut) {
1726 dst.put_u8(TokenType::DoneInProc as u8);
1727 dst.put_u16_le(self.status.to_bits());
1728 dst.put_u16_le(self.cur_cmd);
1729 dst.put_u64_le(self.row_count);
1730 }
1731}
1732
1733impl ServerError {
1734 pub fn decode(src: &mut impl Buf) -> Result<Self, ProtocolError> {
1736 if src.remaining() < 2 {
1739 return Err(ProtocolError::UnexpectedEof);
1740 }
1741
1742 let _length = src.get_u16_le();
1743
1744 if src.remaining() < 6 {
1745 return Err(ProtocolError::UnexpectedEof);
1746 }
1747
1748 let number = src.get_i32_le();
1749 let state = src.get_u8();
1750 let class = src.get_u8();
1751
1752 let message = read_us_varchar(src).ok_or(ProtocolError::UnexpectedEof)?;
1753 let server = read_b_varchar(src).ok_or(ProtocolError::UnexpectedEof)?;
1754 let procedure = read_b_varchar(src).ok_or(ProtocolError::UnexpectedEof)?;
1755
1756 if src.remaining() < 4 {
1757 return Err(ProtocolError::UnexpectedEof);
1758 }
1759 let line = src.get_i32_le();
1760
1761 Ok(Self {
1762 number,
1763 state,
1764 class,
1765 message,
1766 server,
1767 procedure,
1768 line,
1769 })
1770 }
1771
1772 #[must_use]
1774 pub const fn is_fatal(&self) -> bool {
1775 self.class >= 20
1776 }
1777
1778 #[must_use]
1780 pub const fn is_batch_abort(&self) -> bool {
1781 self.class >= 16
1782 }
1783}
1784
1785impl ServerInfo {
1786 pub fn decode(src: &mut impl Buf) -> Result<Self, ProtocolError> {
1790 if src.remaining() < 2 {
1791 return Err(ProtocolError::UnexpectedEof);
1792 }
1793
1794 let _length = src.get_u16_le();
1795
1796 if src.remaining() < 6 {
1797 return Err(ProtocolError::UnexpectedEof);
1798 }
1799
1800 let number = src.get_i32_le();
1801 let state = src.get_u8();
1802 let class = src.get_u8();
1803
1804 let message = read_us_varchar(src).ok_or(ProtocolError::UnexpectedEof)?;
1805 let server = read_b_varchar(src).ok_or(ProtocolError::UnexpectedEof)?;
1806 let procedure = read_b_varchar(src).ok_or(ProtocolError::UnexpectedEof)?;
1807
1808 if src.remaining() < 4 {
1809 return Err(ProtocolError::UnexpectedEof);
1810 }
1811 let line = src.get_i32_le();
1812
1813 Ok(Self {
1814 number,
1815 state,
1816 class,
1817 message,
1818 server,
1819 procedure,
1820 line,
1821 })
1822 }
1823}
1824
1825impl LoginAck {
1826 pub fn decode(src: &mut impl Buf) -> Result<Self, ProtocolError> {
1828 if src.remaining() < 2 {
1830 return Err(ProtocolError::UnexpectedEof);
1831 }
1832
1833 let _length = src.get_u16_le();
1834
1835 if src.remaining() < 5 {
1836 return Err(ProtocolError::UnexpectedEof);
1837 }
1838
1839 let interface = src.get_u8();
1840 let tds_version = src.get_u32_le();
1841 let prog_name = read_b_varchar(src).ok_or(ProtocolError::UnexpectedEof)?;
1842
1843 if src.remaining() < 4 {
1844 return Err(ProtocolError::UnexpectedEof);
1845 }
1846 let prog_version = src.get_u32_le();
1847
1848 Ok(Self {
1849 interface,
1850 tds_version,
1851 prog_name,
1852 prog_version,
1853 })
1854 }
1855
1856 #[must_use]
1858 pub fn tds_version(&self) -> crate::version::TdsVersion {
1859 crate::version::TdsVersion::new(self.tds_version)
1860 }
1861}
1862
1863impl EnvChangeType {
1864 pub fn from_u8(value: u8) -> Option<Self> {
1866 match value {
1867 1 => Some(Self::Database),
1868 2 => Some(Self::Language),
1869 3 => Some(Self::CharacterSet),
1870 4 => Some(Self::PacketSize),
1871 5 => Some(Self::UnicodeSortingLocalId),
1872 6 => Some(Self::UnicodeComparisonFlags),
1873 7 => Some(Self::SqlCollation),
1874 8 => Some(Self::BeginTransaction),
1875 9 => Some(Self::CommitTransaction),
1876 10 => Some(Self::RollbackTransaction),
1877 11 => Some(Self::EnlistDtcTransaction),
1878 12 => Some(Self::DefectTransaction),
1879 13 => Some(Self::RealTimeLogShipping),
1880 15 => Some(Self::PromoteTransaction),
1881 16 => Some(Self::TransactionManagerAddress),
1882 17 => Some(Self::TransactionEnded),
1883 18 => Some(Self::ResetConnectionCompletionAck),
1884 19 => Some(Self::UserInstanceStarted),
1885 20 => Some(Self::Routing),
1886 _ => None,
1887 }
1888 }
1889}
1890
1891impl EnvChange {
1892 pub fn decode(src: &mut impl Buf) -> Result<Self, ProtocolError> {
1894 if src.remaining() < 3 {
1895 return Err(ProtocolError::UnexpectedEof);
1896 }
1897
1898 let length = src.get_u16_le() as usize;
1899 if src.remaining() < length {
1900 return Err(ProtocolError::IncompletePacket {
1901 expected: length,
1902 actual: src.remaining(),
1903 });
1904 }
1905 let remaining_before = src.remaining();
1906
1907 let env_type_byte = src.get_u8();
1908 let env_type = EnvChangeType::from_u8(env_type_byte)
1909 .ok_or(ProtocolError::InvalidTokenType(env_type_byte))?;
1910
1911 let (new_value, old_value) = match env_type {
1912 EnvChangeType::Routing => {
1913 let new_value = Self::decode_routing_value(src)?;
1915 let old_value = EnvChangeValue::Binary(Bytes::new());
1916 (new_value, old_value)
1917 }
1918 EnvChangeType::BeginTransaction
1919 | EnvChangeType::CommitTransaction
1920 | EnvChangeType::RollbackTransaction
1921 | EnvChangeType::EnlistDtcTransaction
1922 | EnvChangeType::SqlCollation => {
1923 let new_len = if src.has_remaining() {
1932 src.get_u8() as usize
1933 } else {
1934 0
1935 };
1936 let new_value = if new_len > 0 && src.remaining() >= new_len {
1937 EnvChangeValue::Binary(src.copy_to_bytes(new_len))
1938 } else {
1939 EnvChangeValue::Binary(Bytes::new())
1940 };
1941
1942 let old_len = if src.has_remaining() {
1943 src.get_u8() as usize
1944 } else {
1945 0
1946 };
1947 let old_value = if old_len > 0 && src.remaining() >= old_len {
1948 EnvChangeValue::Binary(src.copy_to_bytes(old_len))
1949 } else {
1950 EnvChangeValue::Binary(Bytes::new())
1951 };
1952
1953 (new_value, old_value)
1954 }
1955 _ => {
1956 let new_value = read_b_varchar(src)
1958 .map(EnvChangeValue::String)
1959 .unwrap_or(EnvChangeValue::String(String::new()));
1960
1961 let old_value = read_b_varchar(src)
1962 .map(EnvChangeValue::String)
1963 .unwrap_or(EnvChangeValue::String(String::new()));
1964
1965 (new_value, old_value)
1966 }
1967 };
1968
1969 let consumed = remaining_before - src.remaining();
1977 if consumed < length {
1978 src.advance(length - consumed);
1979 }
1980
1981 Ok(Self {
1982 env_type,
1983 new_value,
1984 old_value,
1985 })
1986 }
1987
1988 fn decode_routing_value(src: &mut impl Buf) -> Result<EnvChangeValue, ProtocolError> {
1989 if src.remaining() < 2 {
1991 return Err(ProtocolError::UnexpectedEof);
1992 }
1993
1994 let _routing_len = src.get_u16_le();
1995
1996 if src.remaining() < 5 {
1997 return Err(ProtocolError::UnexpectedEof);
1998 }
1999
2000 let _protocol = src.get_u8();
2001 let port = src.get_u16_le();
2002 let server_len = src.get_u16_le() as usize;
2003
2004 if src.remaining() < server_len * 2 {
2006 return Err(ProtocolError::UnexpectedEof);
2007 }
2008
2009 let mut chars = Vec::with_capacity(server_len);
2010 for _ in 0..server_len {
2011 chars.push(src.get_u16_le());
2012 }
2013
2014 let host = String::from_utf16(&chars).map_err(|_| {
2015 ProtocolError::StringEncoding(
2016 #[cfg(feature = "std")]
2017 "invalid UTF-16 in routing hostname".to_string(),
2018 #[cfg(not(feature = "std"))]
2019 "invalid UTF-16 in routing hostname",
2020 )
2021 })?;
2022
2023 Ok(EnvChangeValue::Routing { host, port })
2024 }
2025
2026 #[must_use]
2028 pub fn is_routing(&self) -> bool {
2029 self.env_type == EnvChangeType::Routing
2030 }
2031
2032 #[must_use]
2034 pub fn routing_info(&self) -> Option<(&str, u16)> {
2035 if let EnvChangeValue::Routing { host, port } = &self.new_value {
2036 Some((host, *port))
2037 } else {
2038 None
2039 }
2040 }
2041
2042 #[must_use]
2044 pub fn new_database(&self) -> Option<&str> {
2045 if self.env_type == EnvChangeType::Database {
2046 if let EnvChangeValue::String(s) = &self.new_value {
2047 return Some(s);
2048 }
2049 }
2050 None
2051 }
2052}
2053
2054impl Order {
2055 pub fn decode(src: &mut impl Buf) -> Result<Self, ProtocolError> {
2057 if src.remaining() < 2 {
2058 return Err(ProtocolError::UnexpectedEof);
2059 }
2060
2061 let length = src.get_u16_le() as usize;
2062 let column_count = length / 2;
2063
2064 if src.remaining() < length {
2065 return Err(ProtocolError::IncompletePacket {
2066 expected: length,
2067 actual: src.remaining(),
2068 });
2069 }
2070
2071 let mut columns = Vec::with_capacity(column_count);
2072 for _ in 0..column_count {
2073 columns.push(src.get_u16_le());
2074 }
2075
2076 Ok(Self { columns })
2077 }
2078}
2079
2080impl FeatureExtAck {
2081 pub const TERMINATOR: u8 = 0xFF;
2083
2084 pub fn decode(src: &mut impl Buf) -> Result<Self, ProtocolError> {
2086 let mut features = Vec::new();
2087
2088 loop {
2089 if !src.has_remaining() {
2090 return Err(ProtocolError::UnexpectedEof);
2091 }
2092
2093 let feature_id = src.get_u8();
2094 if feature_id == Self::TERMINATOR {
2095 break;
2096 }
2097
2098 if src.remaining() < 4 {
2099 return Err(ProtocolError::UnexpectedEof);
2100 }
2101
2102 let data_len = src.get_u32_le() as usize;
2103
2104 if src.remaining() < data_len {
2105 return Err(ProtocolError::IncompletePacket {
2106 expected: data_len,
2107 actual: src.remaining(),
2108 });
2109 }
2110
2111 let data = src.copy_to_bytes(data_len);
2112 features.push(FeatureAck { feature_id, data });
2113 }
2114
2115 Ok(Self { features })
2116 }
2117}
2118
2119impl SspiToken {
2120 pub fn decode(src: &mut impl Buf) -> Result<Self, ProtocolError> {
2122 if src.remaining() < 2 {
2123 return Err(ProtocolError::UnexpectedEof);
2124 }
2125
2126 let length = src.get_u16_le() as usize;
2127
2128 if src.remaining() < length {
2129 return Err(ProtocolError::IncompletePacket {
2130 expected: length,
2131 actual: src.remaining(),
2132 });
2133 }
2134
2135 let data = src.copy_to_bytes(length);
2136 Ok(Self { data })
2137 }
2138}
2139
2140impl FedAuthInfo {
2141 pub fn decode(src: &mut impl Buf) -> Result<Self, ProtocolError> {
2143 if src.remaining() < 4 {
2144 return Err(ProtocolError::UnexpectedEof);
2145 }
2146
2147 let _length = src.get_u32_le();
2148
2149 if src.remaining() < 5 {
2150 return Err(ProtocolError::UnexpectedEof);
2151 }
2152
2153 let _count = src.get_u8();
2154
2155 let mut sts_url = String::new();
2157 let mut spn = String::new();
2158
2159 while src.has_remaining() {
2161 if src.remaining() < 9 {
2162 break;
2163 }
2164
2165 let info_id = src.get_u8();
2166 let info_len = src.get_u32_le() as usize;
2167 let _info_offset = src.get_u32_le();
2168
2169 if src.remaining() < info_len {
2170 break;
2171 }
2172
2173 let char_count = info_len / 2;
2175 let mut chars = Vec::with_capacity(char_count);
2176 for _ in 0..char_count {
2177 chars.push(src.get_u16_le());
2178 }
2179
2180 if let Ok(value) = String::from_utf16(&chars) {
2181 match info_id {
2182 0x01 => spn = value,
2183 0x02 => sts_url = value,
2184 _ => {}
2185 }
2186 }
2187 }
2188
2189 Ok(Self { sts_url, spn })
2190 }
2191}
2192
2193pub struct TokenParser {
2234 data: Bytes,
2235 position: usize,
2236 encryption_enabled: bool,
2239}
2240
2241impl TokenParser {
2242 #[must_use]
2244 pub fn new(data: Bytes) -> Self {
2245 Self {
2246 data,
2247 position: 0,
2248 encryption_enabled: false,
2249 }
2250 }
2251
2252 #[must_use]
2257 pub fn with_encryption(mut self, enabled: bool) -> Self {
2258 self.encryption_enabled = enabled;
2259 self
2260 }
2261
2262 #[must_use]
2264 pub fn remaining(&self) -> usize {
2265 self.data.len().saturating_sub(self.position)
2266 }
2267
2268 #[must_use]
2270 pub fn has_remaining(&self) -> bool {
2271 self.position < self.data.len()
2272 }
2273
2274 #[must_use]
2276 pub fn peek_token_type(&self) -> Option<TokenType> {
2277 if self.position < self.data.len() {
2278 TokenType::from_u8(self.data[self.position])
2279 } else {
2280 None
2281 }
2282 }
2283
2284 pub fn next_token(&mut self) -> Result<Option<Token>, ProtocolError> {
2292 self.next_token_with_metadata(None)
2293 }
2294
2295 pub fn next_token_with_metadata(
2302 &mut self,
2303 metadata: Option<&ColMetaData>,
2304 ) -> Result<Option<Token>, ProtocolError> {
2305 if !self.has_remaining() {
2306 return Ok(None);
2307 }
2308
2309 let mut buf = &self.data[self.position..];
2310 let start_pos = self.position;
2311
2312 let token_type_byte = buf.get_u8();
2313 let token_type = TokenType::from_u8(token_type_byte);
2314
2315 let token = match token_type {
2316 Some(TokenType::Done) => {
2317 let done = Done::decode(&mut buf)?;
2318 Token::Done(done)
2319 }
2320 Some(TokenType::DoneProc) => {
2321 let done = DoneProc::decode(&mut buf)?;
2322 Token::DoneProc(done)
2323 }
2324 Some(TokenType::DoneInProc) => {
2325 let done = DoneInProc::decode(&mut buf)?;
2326 Token::DoneInProc(done)
2327 }
2328 Some(TokenType::Error) => {
2329 let error = ServerError::decode(&mut buf)?;
2330 Token::Error(error)
2331 }
2332 Some(TokenType::Info) => {
2333 let info = ServerInfo::decode(&mut buf)?;
2334 Token::Info(info)
2335 }
2336 Some(TokenType::LoginAck) => {
2337 let login_ack = LoginAck::decode(&mut buf)?;
2338 Token::LoginAck(login_ack)
2339 }
2340 Some(TokenType::EnvChange) => {
2341 let env_change = EnvChange::decode(&mut buf)?;
2342 Token::EnvChange(env_change)
2343 }
2344 Some(TokenType::Order) => {
2345 let order = Order::decode(&mut buf)?;
2346 Token::Order(order)
2347 }
2348 Some(TokenType::FeatureExtAck) => {
2349 let ack = FeatureExtAck::decode(&mut buf)?;
2350 Token::FeatureExtAck(ack)
2351 }
2352 Some(TokenType::Sspi) => {
2353 let sspi = SspiToken::decode(&mut buf)?;
2354 Token::Sspi(sspi)
2355 }
2356 Some(TokenType::FedAuthInfo) => {
2357 let info = FedAuthInfo::decode(&mut buf)?;
2358 Token::FedAuthInfo(info)
2359 }
2360 Some(TokenType::ReturnStatus) => {
2361 if buf.remaining() < 4 {
2362 return Err(ProtocolError::UnexpectedEof);
2363 }
2364 let status = buf.get_i32_le();
2365 Token::ReturnStatus(status)
2366 }
2367 Some(TokenType::ColMetaData) => {
2368 let col_meta = if self.encryption_enabled {
2369 ColMetaData::decode_encrypted(&mut buf)?
2370 } else {
2371 ColMetaData::decode(&mut buf)?
2372 };
2373 Token::ColMetaData(col_meta)
2374 }
2375 Some(TokenType::Row) => {
2376 let meta = metadata.ok_or_else(|| {
2377 ProtocolError::StringEncoding(
2378 #[cfg(feature = "std")]
2379 "Row token requires column metadata".to_string(),
2380 #[cfg(not(feature = "std"))]
2381 "Row token requires column metadata",
2382 )
2383 })?;
2384 let row = RawRow::decode(&mut buf, meta)?;
2385 Token::Row(row)
2386 }
2387 Some(TokenType::NbcRow) => {
2388 let meta = metadata.ok_or_else(|| {
2389 ProtocolError::StringEncoding(
2390 #[cfg(feature = "std")]
2391 "NbcRow token requires column metadata".to_string(),
2392 #[cfg(not(feature = "std"))]
2393 "NbcRow token requires column metadata",
2394 )
2395 })?;
2396 let row = NbcRow::decode(&mut buf, meta)?;
2397 Token::NbcRow(row)
2398 }
2399 Some(TokenType::ReturnValue) => {
2400 let ret_val = ReturnValue::decode(&mut buf)?;
2401 Token::ReturnValue(ret_val)
2402 }
2403 Some(TokenType::SessionState) => {
2404 let session = SessionState::decode(&mut buf)?;
2405 Token::SessionState(session)
2406 }
2407 Some(TokenType::ColInfo) | Some(TokenType::TabName) | Some(TokenType::Offset) => {
2408 if buf.remaining() < 2 {
2411 return Err(ProtocolError::UnexpectedEof);
2412 }
2413 let length = buf.get_u16_le() as usize;
2414 if buf.remaining() < length {
2415 return Err(ProtocolError::IncompletePacket {
2416 expected: length,
2417 actual: buf.remaining(),
2418 });
2419 }
2420 buf.advance(length);
2422 self.position = start_pos + (self.data.len() - start_pos - buf.remaining());
2424 return self.next_token_with_metadata(metadata);
2425 }
2426 None => {
2427 return Err(ProtocolError::InvalidTokenType(token_type_byte));
2428 }
2429 };
2430
2431 let consumed = self.data.len() - start_pos - buf.remaining();
2433 self.position = start_pos + consumed;
2434
2435 Ok(Some(token))
2436 }
2437
2438 pub fn skip_token(&mut self) -> Result<(), ProtocolError> {
2442 if !self.has_remaining() {
2443 return Ok(());
2444 }
2445
2446 let token_type_byte = self.data[self.position];
2447 let token_type = TokenType::from_u8(token_type_byte);
2448
2449 let skip_amount = match token_type {
2451 Some(TokenType::Done) | Some(TokenType::DoneProc) | Some(TokenType::DoneInProc) => {
2453 1 + Done::SIZE }
2455 Some(TokenType::ReturnStatus) => {
2456 1 + 4 }
2458 Some(TokenType::Error)
2460 | Some(TokenType::Info)
2461 | Some(TokenType::LoginAck)
2462 | Some(TokenType::EnvChange)
2463 | Some(TokenType::Order)
2464 | Some(TokenType::Sspi)
2465 | Some(TokenType::ColInfo)
2466 | Some(TokenType::TabName)
2467 | Some(TokenType::Offset)
2468 | Some(TokenType::ReturnValue) => {
2469 if self.remaining() < 3 {
2470 return Err(ProtocolError::UnexpectedEof);
2471 }
2472 let length = u16::from_le_bytes([
2473 self.data[self.position + 1],
2474 self.data[self.position + 2],
2475 ]) as usize;
2476 1 + 2 + length }
2478 Some(TokenType::SessionState) | Some(TokenType::FedAuthInfo) => {
2480 if self.remaining() < 5 {
2481 return Err(ProtocolError::UnexpectedEof);
2482 }
2483 let length = u32::from_le_bytes([
2484 self.data[self.position + 1],
2485 self.data[self.position + 2],
2486 self.data[self.position + 3],
2487 self.data[self.position + 4],
2488 ]) as usize;
2489 1 + 4 + length
2490 }
2491 Some(TokenType::FeatureExtAck) => {
2493 let mut buf = &self.data[self.position + 1..];
2495 let _ = FeatureExtAck::decode(&mut buf)?;
2496 self.data.len() - self.position - buf.remaining()
2497 }
2498 Some(TokenType::ColMetaData) | Some(TokenType::Row) | Some(TokenType::NbcRow) => {
2500 return Err(ProtocolError::InvalidTokenType(token_type_byte));
2501 }
2502 None => {
2503 return Err(ProtocolError::InvalidTokenType(token_type_byte));
2504 }
2505 };
2506
2507 if self.remaining() < skip_amount {
2508 return Err(ProtocolError::UnexpectedEof);
2509 }
2510
2511 self.position += skip_amount;
2512 Ok(())
2513 }
2514
2515 #[must_use]
2517 pub fn position(&self) -> usize {
2518 self.position
2519 }
2520
2521 pub fn reset(&mut self) {
2523 self.position = 0;
2524 }
2525}
2526
2527#[cfg(test)]
2532#[allow(clippy::unwrap_used, clippy::panic)]
2533mod tests {
2534 use super::*;
2535 use bytes::BytesMut;
2536
2537 #[test]
2538 fn test_done_roundtrip() {
2539 let done = Done {
2540 status: DoneStatus {
2541 more: false,
2542 error: false,
2543 in_xact: false,
2544 count: true,
2545 attn: false,
2546 srverror: false,
2547 },
2548 cur_cmd: 193, row_count: 42,
2550 };
2551
2552 let mut buf = BytesMut::new();
2553 done.encode(&mut buf);
2554
2555 let mut cursor = &buf[1..];
2557 let decoded = Done::decode(&mut cursor).unwrap();
2558
2559 assert_eq!(decoded.status.count, done.status.count);
2560 assert_eq!(decoded.cur_cmd, done.cur_cmd);
2561 assert_eq!(decoded.row_count, done.row_count);
2562 }
2563
2564 #[test]
2565 fn test_done_status_bits() {
2566 let status = DoneStatus {
2567 more: true,
2568 error: true,
2569 in_xact: true,
2570 count: true,
2571 attn: false,
2572 srverror: false,
2573 };
2574
2575 let bits = status.to_bits();
2576 let restored = DoneStatus::from_bits(bits);
2577
2578 assert_eq!(status.more, restored.more);
2579 assert_eq!(status.error, restored.error);
2580 assert_eq!(status.in_xact, restored.in_xact);
2581 assert_eq!(status.count, restored.count);
2582 }
2583
2584 #[test]
2585 fn test_token_parser_done() {
2586 let data = Bytes::from_static(&[
2588 0xFD, 0x10, 0x00, 0xC1, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ]);
2593
2594 let mut parser = TokenParser::new(data);
2595 let token = parser.next_token().unwrap().unwrap();
2596
2597 match token {
2598 Token::Done(done) => {
2599 assert!(done.status.count);
2600 assert!(!done.status.more);
2601 assert_eq!(done.cur_cmd, 193);
2602 assert_eq!(done.row_count, 5);
2603 }
2604 _ => panic!("Expected Done token"),
2605 }
2606
2607 assert!(parser.next_token().unwrap().is_none());
2609 }
2610
2611 #[test]
2612 fn test_env_change_type_from_u8() {
2613 assert_eq!(EnvChangeType::from_u8(1), Some(EnvChangeType::Database));
2614 assert_eq!(EnvChangeType::from_u8(20), Some(EnvChangeType::Routing));
2615 assert_eq!(EnvChangeType::from_u8(100), None);
2616 }
2617
2618 #[test]
2625 fn test_env_change_routing_consumes_declared_length() {
2626 let host = "redirect.example";
2627 let host_utf16: Vec<u16> = host.encode_utf16().collect();
2628
2629 let mut data = BytesMut::new();
2630 let routing_len = 1 + 2 + 2 + host_utf16.len() * 2;
2632 let env_len = 1 + 2 + routing_len + 2;
2635 data.put_u16_le(env_len as u16);
2636 data.put_u8(20); data.put_u16_le(routing_len as u16);
2638 data.put_u8(0); data.put_u16_le(11000); data.put_u16_le(host_utf16.len() as u16);
2641 for c in &host_utf16 {
2642 data.put_u16_le(*c);
2643 }
2644 data.put_u16_le(0); data.put_u8(0xFD);
2647
2648 let mut buf: &[u8] = &data;
2649 let env = EnvChange::decode(&mut buf).unwrap();
2650 assert_eq!(env.routing_info(), Some((host, 11000)));
2651 assert_eq!(
2652 buf,
2653 &[0xFD],
2654 "decode must consume exactly the declared ENVCHANGE frame"
2655 );
2656 }
2657
2658 fn put_b_varchar(buf: &mut BytesMut, s: &str) {
2659 let utf16: Vec<u16> = s.encode_utf16().collect();
2660 buf.put_u8(utf16.len() as u8);
2661 for c in utf16 {
2662 buf.put_u16_le(c);
2663 }
2664 }
2665
2666 fn put_us_varchar(buf: &mut BytesMut, s: &str) {
2667 let utf16: Vec<u16> = s.encode_utf16().collect();
2668 buf.put_u16_le(utf16.len() as u16);
2669 for c in utf16 {
2670 buf.put_u16_le(c);
2671 }
2672 }
2673
2674 #[test]
2681 fn test_udt_info_metadata_uses_b_varchar_names() {
2682 let mut data = BytesMut::new();
2683 data.put_u16_le(0xFFFF); put_b_varchar(&mut data, "master");
2685 put_b_varchar(&mut data, "dbo");
2686 put_b_varchar(&mut data, "hierarchyid");
2687 put_us_varchar(
2688 &mut data,
2689 "Microsoft.SqlServer.Types.SqlHierarchyId, Microsoft.SqlServer.Types",
2690 );
2691 data.put_u8(0xFD);
2693
2694 let mut buf: &[u8] = &data;
2695 let info = decode_type_info(&mut buf, TypeId::Udt, TypeId::Udt as u8).unwrap();
2696 assert_eq!(info.max_length, Some(0xFFFF));
2697 assert_eq!(
2698 buf,
2699 &[0xFD],
2700 "decode must consume exactly the UDT_INFO frame"
2701 );
2702 }
2703
2704 #[test]
2708 fn test_xml_info_schema_bound_uses_b_varchar_names() {
2709 let mut data = BytesMut::new();
2710 data.put_u8(1); put_b_varchar(&mut data, "master");
2712 put_b_varchar(&mut data, "dbo");
2713 put_us_varchar(&mut data, "MyXmlSchemaCollection");
2714 data.put_u8(0xFD);
2715
2716 let mut buf: &[u8] = &data;
2717 decode_type_info(&mut buf, TypeId::Xml, TypeId::Xml as u8).unwrap();
2718 assert_eq!(
2719 buf,
2720 &[0xFD],
2721 "decode must consume exactly the XML_INFO frame"
2722 );
2723 }
2724
2725 #[test]
2726 fn hostile_env_change_binary_truncated_is_not_panic() {
2727 let data = [0x01, 0x00, 0x08];
2732 let mut buf: &[u8] = &data;
2733 let env = EnvChange::decode(&mut buf).unwrap();
2734 assert_eq!(env.env_type, EnvChangeType::BeginTransaction);
2735 }
2736
2737 #[test]
2738 fn test_colmetadata_no_columns() {
2739 let data = Bytes::from_static(&[0xFF, 0xFF]);
2741 let mut cursor: &[u8] = &data;
2742 let meta = ColMetaData::decode(&mut cursor).unwrap();
2743 assert!(meta.is_empty());
2744 assert_eq!(meta.column_count(), 0);
2745 }
2746
2747 #[test]
2748 fn test_colmetadata_single_int_column() {
2749 let mut data = BytesMut::new();
2752 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;
2761 let meta = ColMetaData::decode(&mut cursor).unwrap();
2762
2763 assert_eq!(meta.column_count(), 1);
2764 assert_eq!(meta.columns[0].name, "id");
2765 assert_eq!(meta.columns[0].type_id, TypeId::Int4);
2766 assert!(meta.columns[0].is_nullable());
2767 }
2768
2769 #[test]
2770 fn test_colmetadata_nvarchar_column() {
2771 let mut data = BytesMut::new();
2773 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]);
2783
2784 let mut cursor: &[u8] = &data;
2785 let meta = ColMetaData::decode(&mut cursor).unwrap();
2786
2787 assert_eq!(meta.column_count(), 1);
2788 assert_eq!(meta.columns[0].name, "name");
2789 assert_eq!(meta.columns[0].type_id, TypeId::NVarChar);
2790 assert_eq!(meta.columns[0].type_info.max_length, Some(100));
2791 assert!(meta.columns[0].type_info.collation.is_some());
2792 }
2793
2794 #[test]
2795 fn test_raw_row_decode_int() {
2796 let metadata = ColMetaData {
2798 cek_table: None,
2799 columns: vec![ColumnData {
2800 name: "id".to_string(),
2801 type_id: TypeId::Int4,
2802 col_type: 0x38,
2803 flags: 0,
2804 user_type: 0,
2805 type_info: TypeInfo::default(),
2806 crypto_metadata: None,
2807 }],
2808 };
2809
2810 let data = Bytes::from_static(&[0x2A, 0x00, 0x00, 0x00]); let mut cursor: &[u8] = &data;
2813 let row = RawRow::decode(&mut cursor, &metadata).unwrap();
2814
2815 assert_eq!(row.data.len(), 4);
2817 assert_eq!(&row.data[..], &[0x2A, 0x00, 0x00, 0x00]);
2818 }
2819
2820 #[test]
2821 fn test_raw_row_decode_nullable_int() {
2822 let metadata = ColMetaData {
2824 cek_table: None,
2825 columns: vec![ColumnData {
2826 name: "id".to_string(),
2827 type_id: TypeId::IntN,
2828 col_type: 0x26,
2829 flags: 0x01, user_type: 0,
2831 type_info: TypeInfo {
2832 max_length: Some(4),
2833 ..Default::default()
2834 },
2835 crypto_metadata: None,
2836 }],
2837 };
2838
2839 let data = Bytes::from_static(&[0x04, 0x2A, 0x00, 0x00, 0x00]); let mut cursor: &[u8] = &data;
2842 let row = RawRow::decode(&mut cursor, &metadata).unwrap();
2843
2844 assert_eq!(row.data.len(), 5);
2845 assert_eq!(row.data[0], 4); assert_eq!(&row.data[1..], &[0x2A, 0x00, 0x00, 0x00]);
2847 }
2848
2849 #[test]
2850 fn test_raw_row_decode_null_value() {
2851 let metadata = ColMetaData {
2853 cek_table: None,
2854 columns: vec![ColumnData {
2855 name: "id".to_string(),
2856 type_id: TypeId::IntN,
2857 col_type: 0x26,
2858 flags: 0x01, user_type: 0,
2860 type_info: TypeInfo {
2861 max_length: Some(4),
2862 ..Default::default()
2863 },
2864 crypto_metadata: None,
2865 }],
2866 };
2867
2868 let data = Bytes::from_static(&[0xFF]);
2870 let mut cursor: &[u8] = &data;
2871 let row = RawRow::decode(&mut cursor, &metadata).unwrap();
2872
2873 assert_eq!(row.data.len(), 1);
2874 assert_eq!(row.data[0], 0xFF); }
2876
2877 #[test]
2878 fn test_nbcrow_null_bitmap() {
2879 let row = NbcRow {
2880 null_bitmap: vec![0b00000101], data: Bytes::new(),
2882 };
2883
2884 assert!(row.is_null(0));
2885 assert!(!row.is_null(1));
2886 assert!(row.is_null(2));
2887 assert!(!row.is_null(3));
2888 }
2889
2890 #[test]
2891 fn test_token_parser_colmetadata() {
2892 let mut data = BytesMut::new();
2894 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());
2903 let token = parser.next_token().unwrap().unwrap();
2904
2905 match token {
2906 Token::ColMetaData(meta) => {
2907 assert_eq!(meta.column_count(), 1);
2908 assert_eq!(meta.columns[0].name, "id");
2909 assert_eq!(meta.columns[0].type_id, TypeId::Int4);
2910 }
2911 _ => panic!("Expected ColMetaData token"),
2912 }
2913 }
2914
2915 #[test]
2916 fn test_token_parser_row_with_metadata() {
2917 let metadata = ColMetaData {
2919 cek_table: None,
2920 columns: vec![ColumnData {
2921 name: "id".to_string(),
2922 type_id: TypeId::Int4,
2923 col_type: 0x38,
2924 flags: 0,
2925 user_type: 0,
2926 type_info: TypeInfo::default(),
2927 crypto_metadata: None,
2928 }],
2929 };
2930
2931 let mut data = BytesMut::new();
2933 data.extend_from_slice(&[0xD1]); data.extend_from_slice(&[0x2A, 0x00, 0x00, 0x00]); let mut parser = TokenParser::new(data.freeze());
2937 let token = parser
2938 .next_token_with_metadata(Some(&metadata))
2939 .unwrap()
2940 .unwrap();
2941
2942 match token {
2943 Token::Row(row) => {
2944 assert_eq!(row.data.len(), 4);
2945 }
2946 _ => panic!("Expected Row token"),
2947 }
2948 }
2949
2950 #[test]
2951 fn test_token_parser_row_without_metadata_fails() {
2952 let mut data = BytesMut::new();
2954 data.extend_from_slice(&[0xD1]); data.extend_from_slice(&[0x2A, 0x00, 0x00, 0x00]); let mut parser = TokenParser::new(data.freeze());
2958 let result = parser.next_token(); assert!(result.is_err());
2961 }
2962
2963 #[test]
2964 fn test_token_parser_peek() {
2965 let data = Bytes::from_static(&[
2966 0xFD, 0x10, 0x00, 0xC1, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ]);
2971
2972 let parser = TokenParser::new(data);
2973 assert_eq!(parser.peek_token_type(), Some(TokenType::Done));
2974 }
2975
2976 #[test]
2977 fn test_column_data_fixed_size() {
2978 let col = ColumnData {
2979 name: String::new(),
2980 type_id: TypeId::Int4,
2981 col_type: 0x38,
2982 flags: 0,
2983 user_type: 0,
2984 type_info: TypeInfo::default(),
2985 crypto_metadata: None,
2986 };
2987 assert_eq!(col.fixed_size(), Some(4));
2988
2989 let col2 = ColumnData {
2990 name: String::new(),
2991 type_id: TypeId::NVarChar,
2992 col_type: 0xE7,
2993 flags: 0,
2994 user_type: 0,
2995 type_info: TypeInfo::default(),
2996 crypto_metadata: None,
2997 };
2998 assert_eq!(col2.fixed_size(), None);
2999 }
3000
3001 #[test]
3009 fn test_decode_nvarchar_then_intn_roundtrip() {
3010 let mut wire_data = BytesMut::new();
3015
3016 let word = "World";
3019 let utf16: Vec<u16> = word.encode_utf16().collect();
3020 wire_data.put_u16_le((utf16.len() * 2) as u16); for code_unit in &utf16 {
3022 wire_data.put_u16_le(*code_unit);
3023 }
3024
3025 wire_data.put_u8(4); wire_data.put_i32_le(42);
3028
3029 let metadata = ColMetaData {
3031 cek_table: None,
3032 columns: vec![
3033 ColumnData {
3034 name: "greeting".to_string(),
3035 type_id: TypeId::NVarChar,
3036 col_type: 0xE7,
3037 flags: 0x01,
3038 user_type: 0,
3039 type_info: TypeInfo {
3040 max_length: Some(10), precision: None,
3042 scale: None,
3043 collation: None,
3044 },
3045 crypto_metadata: None,
3046 },
3047 ColumnData {
3048 name: "number".to_string(),
3049 type_id: TypeId::IntN,
3050 col_type: 0x26,
3051 flags: 0x01,
3052 user_type: 0,
3053 type_info: TypeInfo {
3054 max_length: Some(4),
3055 precision: None,
3056 scale: None,
3057 collation: None,
3058 },
3059 crypto_metadata: None,
3060 },
3061 ],
3062 };
3063
3064 let mut wire_cursor = wire_data.freeze();
3066 let raw_row = RawRow::decode(&mut wire_cursor, &metadata).unwrap();
3067
3068 assert_eq!(
3070 wire_cursor.remaining(),
3071 0,
3072 "wire data should be fully consumed"
3073 );
3074
3075 let mut stored_cursor: &[u8] = &raw_row.data;
3077
3078 assert!(
3081 stored_cursor.remaining() >= 2,
3082 "need at least 2 bytes for length"
3083 );
3084 let len0 = stored_cursor.get_u16_le() as usize;
3085 assert_eq!(len0, 10, "NVarChar length should be 10 bytes");
3086 assert!(
3087 stored_cursor.remaining() >= len0,
3088 "need {len0} bytes for data"
3089 );
3090
3091 let mut utf16_read = Vec::new();
3093 for _ in 0..(len0 / 2) {
3094 utf16_read.push(stored_cursor.get_u16_le());
3095 }
3096 let string0 = String::from_utf16(&utf16_read).unwrap();
3097 assert_eq!(string0, "World", "column 0 should be 'World'");
3098
3099 assert!(
3102 stored_cursor.remaining() >= 1,
3103 "need at least 1 byte for length"
3104 );
3105 let len1 = stored_cursor.get_u8();
3106 assert_eq!(len1, 4, "IntN length should be 4");
3107 assert!(stored_cursor.remaining() >= 4, "need 4 bytes for INT data");
3108 let int1 = stored_cursor.get_i32_le();
3109 assert_eq!(int1, 42, "column 1 should be 42");
3110
3111 assert_eq!(
3113 stored_cursor.remaining(),
3114 0,
3115 "stored data should be fully consumed"
3116 );
3117 }
3118
3119 #[test]
3120 fn test_decode_nvarchar_max_then_intn_roundtrip() {
3121 let mut wire_data = BytesMut::new();
3125
3126 let word = "Hello";
3129 let utf16: Vec<u16> = word.encode_utf16().collect();
3130 let byte_len = (utf16.len() * 2) as u64;
3131
3132 wire_data.put_u64_le(byte_len); wire_data.put_u32_le(byte_len as u32); for code_unit in &utf16 {
3135 wire_data.put_u16_le(*code_unit);
3136 }
3137 wire_data.put_u32_le(0); wire_data.put_u8(4);
3141 wire_data.put_i32_le(99);
3142
3143 let metadata = ColMetaData {
3145 cek_table: None,
3146 columns: vec![
3147 ColumnData {
3148 name: "text".to_string(),
3149 type_id: TypeId::NVarChar,
3150 col_type: 0xE7,
3151 flags: 0x01,
3152 user_type: 0,
3153 type_info: TypeInfo {
3154 max_length: Some(0xFFFF), precision: None,
3156 scale: None,
3157 collation: None,
3158 },
3159 crypto_metadata: None,
3160 },
3161 ColumnData {
3162 name: "num".to_string(),
3163 type_id: TypeId::IntN,
3164 col_type: 0x26,
3165 flags: 0x01,
3166 user_type: 0,
3167 type_info: TypeInfo {
3168 max_length: Some(4),
3169 precision: None,
3170 scale: None,
3171 collation: None,
3172 },
3173 crypto_metadata: None,
3174 },
3175 ],
3176 };
3177
3178 let mut wire_cursor = wire_data.freeze();
3180 let raw_row = RawRow::decode(&mut wire_cursor, &metadata).unwrap();
3181
3182 assert_eq!(
3184 wire_cursor.remaining(),
3185 0,
3186 "wire data should be fully consumed"
3187 );
3188
3189 let mut stored_cursor: &[u8] = &raw_row.data;
3191
3192 let total_len = stored_cursor.get_u64_le();
3194 assert_eq!(total_len, 10, "PLP total length should be 10");
3195
3196 let chunk_len = stored_cursor.get_u32_le();
3197 assert_eq!(chunk_len, 10, "PLP chunk length should be 10");
3198
3199 let mut utf16_read = Vec::new();
3200 for _ in 0..(chunk_len / 2) {
3201 utf16_read.push(stored_cursor.get_u16_le());
3202 }
3203 let string0 = String::from_utf16(&utf16_read).unwrap();
3204 assert_eq!(string0, "Hello", "column 0 should be 'Hello'");
3205
3206 let terminator = stored_cursor.get_u32_le();
3207 assert_eq!(terminator, 0, "PLP should end with 0");
3208
3209 let len1 = stored_cursor.get_u8();
3211 assert_eq!(len1, 4);
3212 let int1 = stored_cursor.get_i32_le();
3213 assert_eq!(int1, 99, "column 1 should be 99");
3214
3215 assert_eq!(
3217 stored_cursor.remaining(),
3218 0,
3219 "stored data should be fully consumed"
3220 );
3221 }
3222
3223 #[test]
3228 fn test_return_status_via_parser() {
3229 let data = Bytes::from_static(&[
3231 0x79, 0x00, 0x00, 0x00, 0x00, ]);
3234
3235 let mut parser = TokenParser::new(data);
3236 let token = parser.next_token().unwrap().unwrap();
3237
3238 match token {
3239 Token::ReturnStatus(status) => {
3240 assert_eq!(status, 0);
3241 }
3242 _ => panic!("Expected ReturnStatus token, got {token:?}"),
3243 }
3244
3245 assert!(parser.next_token().unwrap().is_none());
3246 }
3247
3248 #[test]
3249 fn test_return_status_nonzero() {
3250 let mut buf = BytesMut::new();
3252 buf.put_u8(0x79); buf.put_i32_le(-6);
3254
3255 let mut parser = TokenParser::new(buf.freeze());
3256 let token = parser.next_token().unwrap().unwrap();
3257
3258 match token {
3259 Token::ReturnStatus(status) => {
3260 assert_eq!(status, -6);
3261 }
3262 _ => panic!("Expected ReturnStatus token"),
3263 }
3264 }
3265
3266 #[test]
3271 fn test_done_proc_roundtrip() {
3272 let done = DoneProc {
3273 status: DoneStatus {
3274 more: false,
3275 error: false,
3276 in_xact: false,
3277 count: true,
3278 attn: false,
3279 srverror: false,
3280 },
3281 cur_cmd: 0x00C6, row_count: 100,
3283 };
3284
3285 let mut buf = BytesMut::new();
3286 done.encode(&mut buf);
3287
3288 assert_eq!(buf[0], 0xFE);
3290
3291 let mut cursor = &buf[1..];
3293 let decoded = DoneProc::decode(&mut cursor).unwrap();
3294
3295 assert!(decoded.status.count);
3296 assert!(!decoded.status.more);
3297 assert!(!decoded.status.error);
3298 assert_eq!(decoded.cur_cmd, 0x00C6);
3299 assert_eq!(decoded.row_count, 100);
3300 }
3301
3302 #[test]
3303 fn test_done_proc_via_parser() {
3304 let data = Bytes::from_static(&[
3305 0xFE, 0x00, 0x00, 0xC6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ]);
3310
3311 let mut parser = TokenParser::new(data);
3312 let token = parser.next_token().unwrap().unwrap();
3313
3314 match token {
3315 Token::DoneProc(done) => {
3316 assert!(!done.status.count);
3317 assert!(!done.status.more);
3318 assert_eq!(done.cur_cmd, 198);
3319 assert_eq!(done.row_count, 0);
3320 }
3321 _ => panic!("Expected DoneProc token"),
3322 }
3323 }
3324
3325 #[test]
3326 fn test_done_proc_with_error_flag() {
3327 let mut buf = BytesMut::new();
3328 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());
3334 let token = parser.next_token().unwrap().unwrap();
3335
3336 match token {
3337 Token::DoneProc(done) => {
3338 assert!(done.status.error);
3339 assert!(!done.status.count);
3340 assert!(!done.status.more);
3341 }
3342 _ => panic!("Expected DoneProc token"),
3343 }
3344 }
3345
3346 #[test]
3351 fn test_done_in_proc_roundtrip() {
3352 let done = DoneInProc {
3353 status: DoneStatus {
3354 more: true,
3355 error: false,
3356 in_xact: false,
3357 count: true,
3358 attn: false,
3359 srverror: false,
3360 },
3361 cur_cmd: 193, row_count: 7,
3363 };
3364
3365 let mut buf = BytesMut::new();
3366 done.encode(&mut buf);
3367
3368 assert_eq!(buf[0], 0xFF);
3369
3370 let mut cursor = &buf[1..];
3371 let decoded = DoneInProc::decode(&mut cursor).unwrap();
3372
3373 assert!(decoded.status.more);
3374 assert!(decoded.status.count);
3375 assert!(!decoded.status.error);
3376 assert_eq!(decoded.cur_cmd, 193);
3377 assert_eq!(decoded.row_count, 7);
3378 }
3379
3380 #[test]
3381 fn test_done_in_proc_via_parser() {
3382 let data = Bytes::from_static(&[
3383 0xFF, 0x11, 0x00, 0xC1, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ]);
3388
3389 let mut parser = TokenParser::new(data);
3390 let token = parser.next_token().unwrap().unwrap();
3391
3392 match token {
3393 Token::DoneInProc(done) => {
3394 assert!(done.status.more);
3395 assert!(done.status.count);
3396 assert_eq!(done.cur_cmd, 193);
3397 assert_eq!(done.row_count, 3);
3398 }
3399 _ => panic!("Expected DoneInProc token"),
3400 }
3401 }
3402
3403 #[test]
3408 fn test_server_error_decode() {
3409 let mut buf = BytesMut::new();
3412
3413 let msg_utf16: Vec<u16> = "Invalid column name 'foo'.".encode_utf16().collect();
3415 let srv_utf16: Vec<u16> = "SQLDB01".encode_utf16().collect();
3416 let proc_utf16: Vec<u16> = "".encode_utf16().collect();
3417
3418 let length: u16 = (4
3424 + 1
3425 + 1
3426 + 2
3427 + (msg_utf16.len() * 2)
3428 + 1
3429 + (srv_utf16.len() * 2)
3430 + 1
3431 + (proc_utf16.len() * 2)
3432 + 4) as u16;
3433
3434 buf.put_u16_le(length);
3435 buf.put_i32_le(207); buf.put_u8(1); buf.put_u8(16); buf.put_u16_le(msg_utf16.len() as u16);
3441 for &c in &msg_utf16 {
3442 buf.put_u16_le(c);
3443 }
3444
3445 buf.put_u8(srv_utf16.len() as u8);
3447 for &c in &srv_utf16 {
3448 buf.put_u16_le(c);
3449 }
3450
3451 buf.put_u8(proc_utf16.len() as u8);
3453
3454 buf.put_i32_le(42);
3456
3457 let mut cursor = buf.freeze();
3458 let error = ServerError::decode(&mut cursor).unwrap();
3459
3460 assert_eq!(error.number, 207);
3461 assert_eq!(error.state, 1);
3462 assert_eq!(error.class, 16);
3463 assert_eq!(error.message, "Invalid column name 'foo'.");
3464 assert_eq!(error.server, "SQLDB01");
3465 assert_eq!(error.procedure, "");
3466 assert_eq!(error.line, 42);
3467 }
3468
3469 #[test]
3470 fn test_server_error_severity_helpers() {
3471 let fatal = ServerError {
3472 number: 4014,
3473 state: 1,
3474 class: 20,
3475 message: "Fatal error".to_string(),
3476 server: String::new(),
3477 procedure: String::new(),
3478 line: 0,
3479 };
3480 assert!(fatal.is_fatal());
3481 assert!(fatal.is_batch_abort());
3482
3483 let batch_abort = ServerError {
3484 number: 547,
3485 state: 0,
3486 class: 16,
3487 message: "Constraint violation".to_string(),
3488 server: String::new(),
3489 procedure: String::new(),
3490 line: 1,
3491 };
3492 assert!(!batch_abort.is_fatal());
3493 assert!(batch_abort.is_batch_abort());
3494
3495 let informational = ServerError {
3496 number: 5701,
3497 state: 2,
3498 class: 10,
3499 message: "Changed db context".to_string(),
3500 server: String::new(),
3501 procedure: String::new(),
3502 line: 0,
3503 };
3504 assert!(!informational.is_fatal());
3505 assert!(!informational.is_batch_abort());
3506 }
3507
3508 #[test]
3509 fn test_server_error_via_parser() {
3510 let mut buf = BytesMut::new();
3512 buf.put_u8(0xAA); let msg_utf16: Vec<u16> = "Syntax error".encode_utf16().collect();
3515 let srv_utf16: Vec<u16> = "SRV".encode_utf16().collect();
3516 let proc_utf16: Vec<u16> = "sp_test".encode_utf16().collect();
3517
3518 let length: u16 = (4
3519 + 1
3520 + 1
3521 + 2
3522 + (msg_utf16.len() * 2)
3523 + 1
3524 + (srv_utf16.len() * 2)
3525 + 1
3526 + (proc_utf16.len() * 2)
3527 + 4) as u16;
3528
3529 buf.put_u16_le(length);
3530 buf.put_i32_le(102); buf.put_u8(1);
3532 buf.put_u8(15);
3533
3534 buf.put_u16_le(msg_utf16.len() as u16);
3535 for &c in &msg_utf16 {
3536 buf.put_u16_le(c);
3537 }
3538 buf.put_u8(srv_utf16.len() as u8);
3539 for &c in &srv_utf16 {
3540 buf.put_u16_le(c);
3541 }
3542 buf.put_u8(proc_utf16.len() as u8);
3543 for &c in &proc_utf16 {
3544 buf.put_u16_le(c);
3545 }
3546 buf.put_i32_le(5);
3547
3548 let mut parser = TokenParser::new(buf.freeze());
3549 let token = parser.next_token().unwrap().unwrap();
3550
3551 match token {
3552 Token::Error(err) => {
3553 assert_eq!(err.number, 102);
3554 assert_eq!(err.class, 15);
3555 assert_eq!(err.message, "Syntax error");
3556 assert_eq!(err.server, "SRV");
3557 assert_eq!(err.procedure, "sp_test");
3558 assert_eq!(err.line, 5);
3559 }
3560 _ => panic!("Expected Error token"),
3561 }
3562 }
3563
3564 fn build_return_value_intn(
3571 ordinal: u16,
3572 name: &str,
3573 status: u8,
3574 value: Option<i32>,
3575 ) -> BytesMut {
3576 let mut inner = BytesMut::new();
3577
3578 inner.put_u16_le(ordinal);
3580
3581 let name_utf16: Vec<u16> = name.encode_utf16().collect();
3583 inner.put_u8(name_utf16.len() as u8);
3584 for &c in &name_utf16 {
3585 inner.put_u16_le(c);
3586 }
3587
3588 inner.put_u8(status);
3590
3591 inner.put_u32_le(0);
3593
3594 inner.put_u16_le(0x0001); inner.put_u8(0x26);
3599
3600 inner.put_u8(4);
3602
3603 match value {
3605 Some(v) => {
3606 inner.put_u8(4); inner.put_i32_le(v);
3608 }
3609 None => {
3610 inner.put_u8(0); }
3612 }
3613
3614 inner
3617 }
3618
3619 #[test]
3620 fn test_return_value_int_output() {
3621 let buf = build_return_value_intn(1, "@result", 0x01, Some(42));
3622 let mut cursor = buf.freeze();
3623 let rv = ReturnValue::decode(&mut cursor).unwrap();
3624
3625 assert_eq!(rv.param_ordinal, 1);
3626 assert_eq!(rv.param_name, "@result");
3627 assert_eq!(rv.status, 0x01); assert_eq!(rv.col_type, 0x26); assert_eq!(rv.type_info.max_length, Some(4));
3630 assert_eq!(rv.value.len(), 5);
3632 assert_eq!(rv.value[0], 4);
3633 assert_eq!(
3634 i32::from_le_bytes([rv.value[1], rv.value[2], rv.value[3], rv.value[4]]),
3635 42
3636 );
3637 }
3638
3639 #[test]
3640 fn test_return_value_null_output() {
3641 let buf = build_return_value_intn(2, "@count", 0x01, None);
3642 let mut cursor = buf.freeze();
3643 let rv = ReturnValue::decode(&mut cursor).unwrap();
3644
3645 assert_eq!(rv.param_ordinal, 2);
3646 assert_eq!(rv.param_name, "@count");
3647 assert_eq!(rv.status, 0x01);
3648 assert_eq!(rv.col_type, 0x26);
3649 assert_eq!(rv.value.len(), 1);
3651 assert_eq!(rv.value[0], 0);
3652 }
3653
3654 #[test]
3655 fn test_return_value_udf_status() {
3656 let buf = build_return_value_intn(0, "@RETURN_VALUE", 0x02, Some(-1));
3658 let mut cursor = buf.freeze();
3659 let rv = ReturnValue::decode(&mut cursor).unwrap();
3660
3661 assert_eq!(rv.param_ordinal, 0);
3662 assert_eq!(rv.param_name, "@RETURN_VALUE");
3663 assert_eq!(rv.status, 0x02); assert_eq!(rv.value[0], 4);
3665 assert_eq!(
3666 i32::from_le_bytes([rv.value[1], rv.value[2], rv.value[3], rv.value[4]]),
3667 -1
3668 );
3669 }
3670
3671 #[test]
3672 fn test_return_value_nvarchar_output() {
3673 let mut inner = BytesMut::new();
3675
3676 inner.put_u16_le(1);
3678
3679 let name_utf16: Vec<u16> = "@name".encode_utf16().collect();
3681 inner.put_u8(name_utf16.len() as u8);
3682 for &c in &name_utf16 {
3683 inner.put_u16_le(c);
3684 }
3685
3686 inner.put_u8(0x01);
3688 inner.put_u32_le(0);
3690 inner.put_u16_le(0x0001);
3692 inner.put_u8(0xE7);
3694 inner.put_u16_le(200); inner.put_u32_le(0x0904D000); inner.put_u8(0x34); let val_utf16: Vec<u16> = "Hello".encode_utf16().collect();
3701 let byte_len = (val_utf16.len() * 2) as u16;
3702 inner.put_u16_le(byte_len);
3703 for &c in &val_utf16 {
3704 inner.put_u16_le(c);
3705 }
3706
3707 let mut cursor = inner.freeze();
3708 let rv = ReturnValue::decode(&mut cursor).unwrap();
3709
3710 assert_eq!(rv.param_ordinal, 1);
3711 assert_eq!(rv.param_name, "@name");
3712 assert_eq!(rv.status, 0x01);
3713 assert_eq!(rv.col_type, 0xE7); assert_eq!(rv.type_info.max_length, Some(200));
3715 assert!(rv.type_info.collation.is_some());
3716
3717 assert_eq!(rv.value.len(), 12); let val_len = u16::from_le_bytes([rv.value[0], rv.value[1]]);
3720 assert_eq!(val_len, 10);
3721 }
3722
3723 #[test]
3724 fn test_return_value_via_parser() {
3725 let mut data = BytesMut::new();
3727 data.put_u8(0xAC); data.extend_from_slice(&build_return_value_intn(0, "@out", 0x01, Some(99)));
3729
3730 let mut parser = TokenParser::new(data.freeze());
3731 let token = parser.next_token().unwrap().unwrap();
3732
3733 match token {
3734 Token::ReturnValue(rv) => {
3735 assert_eq!(rv.param_name, "@out");
3736 assert_eq!(rv.param_ordinal, 0);
3737 assert_eq!(rv.status, 0x01);
3738 assert_eq!(rv.col_type, 0x26);
3739 }
3740 _ => panic!("Expected ReturnValue token"),
3741 }
3742 }
3743
3744 #[test]
3749 fn test_multi_token_stored_proc_response() {
3750 let mut data = BytesMut::new();
3753
3754 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);
3763
3764 data.put_u8(0xFE); data.put_u16_le(0x0000); data.put_u16_le(0x00C6); data.put_u64_le(0);
3769
3770 let mut parser = TokenParser::new(data.freeze());
3771
3772 let t1 = parser.next_token().unwrap().unwrap();
3774 match t1 {
3775 Token::DoneInProc(done) => {
3776 assert!(done.status.count);
3777 assert_eq!(done.row_count, 3);
3778 assert_eq!(done.cur_cmd, 193);
3779 }
3780 _ => panic!("Expected DoneInProc, got {t1:?}"),
3781 }
3782
3783 let t2 = parser.next_token().unwrap().unwrap();
3785 match t2 {
3786 Token::ReturnStatus(status) => {
3787 assert_eq!(status, 0);
3788 }
3789 _ => panic!("Expected ReturnStatus, got {t2:?}"),
3790 }
3791
3792 let t3 = parser.next_token().unwrap().unwrap();
3794 match t3 {
3795 Token::DoneProc(done) => {
3796 assert!(!done.status.count);
3797 assert!(!done.status.more);
3798 assert_eq!(done.cur_cmd, 198);
3799 }
3800 _ => panic!("Expected DoneProc, got {t3:?}"),
3801 }
3802
3803 assert!(parser.next_token().unwrap().is_none());
3805 }
3806
3807 #[test]
3808 fn test_multi_token_error_in_stream() {
3809 let mut data = BytesMut::new();
3811
3812 data.put_u8(0xAA);
3814
3815 let msg_utf16: Vec<u16> = "Deadlock".encode_utf16().collect();
3816 let srv_utf16: Vec<u16> = "DB1".encode_utf16().collect();
3817
3818 let length: u16 = (4 + 1 + 1
3819 + 2 + (msg_utf16.len() * 2)
3820 + 1 + (srv_utf16.len() * 2)
3821 + 1 + 4) as u16;
3823
3824 data.put_u16_le(length);
3825 data.put_i32_le(1205); data.put_u8(51); data.put_u8(13); data.put_u16_le(msg_utf16.len() as u16);
3830 for &c in &msg_utf16 {
3831 data.put_u16_le(c);
3832 }
3833 data.put_u8(srv_utf16.len() as u8);
3834 for &c in &srv_utf16 {
3835 data.put_u16_le(c);
3836 }
3837 data.put_u8(0); data.put_i32_le(0);
3839
3840 data.put_u8(0xFD);
3842 data.put_u16_le(0x0002); data.put_u16_le(0x00C1); data.put_u64_le(0);
3845
3846 let mut parser = TokenParser::new(data.freeze());
3847
3848 let t1 = parser.next_token().unwrap().unwrap();
3850 match t1 {
3851 Token::Error(err) => {
3852 assert_eq!(err.number, 1205);
3853 assert_eq!(err.class, 13);
3854 assert_eq!(err.message, "Deadlock");
3855 assert_eq!(err.server, "DB1");
3856 }
3857 _ => panic!("Expected Error token, got {t1:?}"),
3858 }
3859
3860 let t2 = parser.next_token().unwrap().unwrap();
3862 match t2 {
3863 Token::Done(done) => {
3864 assert!(done.status.error);
3865 assert!(!done.status.count);
3866 }
3867 _ => panic!("Expected Done token, got {t2:?}"),
3868 }
3869
3870 assert!(parser.next_token().unwrap().is_none());
3871 }
3872
3873 #[test]
3874 fn test_multi_token_proc_with_return_value() {
3875 let mut data = BytesMut::new();
3877
3878 data.put_u8(0xAC);
3880 data.extend_from_slice(&build_return_value_intn(1, "@result", 0x01, Some(42)));
3881
3882 data.put_u8(0x79);
3884 data.put_i32_le(0);
3885
3886 data.put_u8(0xFE);
3888 data.put_u16_le(0x0000);
3889 data.put_u16_le(0x00C6);
3890 data.put_u64_le(0);
3891
3892 let mut parser = TokenParser::new(data.freeze());
3893
3894 let t1 = parser.next_token().unwrap().unwrap();
3895 match t1 {
3896 Token::ReturnValue(rv) => {
3897 assert_eq!(rv.param_name, "@result");
3898 assert_eq!(rv.param_ordinal, 1);
3899 }
3900 _ => panic!("Expected ReturnValue, got {t1:?}"),
3901 }
3902
3903 let t2 = parser.next_token().unwrap().unwrap();
3904 assert!(matches!(t2, Token::ReturnStatus(0)));
3905
3906 let t3 = parser.next_token().unwrap().unwrap();
3907 assert!(matches!(t3, Token::DoneProc(_)));
3908
3909 assert!(parser.next_token().unwrap().is_none());
3910 }
3911
3912 #[test]
3917 fn test_return_status_truncated() {
3918 let data = Bytes::from_static(&[0x79, 0x01, 0x02, 0x03]);
3920 let mut parser = TokenParser::new(data);
3921 assert!(parser.next_token().is_err());
3922 }
3923
3924 #[test]
3925 fn test_done_proc_truncated() {
3926 let data = Bytes::from_static(&[0xFE, 0x00, 0x00, 0xC1, 0x00, 0x01, 0x00, 0x00, 0x00]);
3928 let mut parser = TokenParser::new(data);
3929 assert!(parser.next_token().is_err());
3930 }
3931
3932 #[test]
3933 fn test_server_error_truncated() {
3934 let data = Bytes::from_static(&[0xAA, 0x20, 0x00]);
3936 let mut parser = TokenParser::new(data);
3937 assert!(parser.next_token().is_err());
3938 }
3939}