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 AltMetaData = 0x88,
86 AltRow = 0xD3,
88}
89
90impl TokenType {
91 pub fn from_u8(value: u8) -> Option<Self> {
93 match value {
94 0x81 => Some(Self::ColMetaData),
95 0xAA => Some(Self::Error),
96 0xAB => Some(Self::Info),
97 0xAD => Some(Self::LoginAck),
98 0xD1 => Some(Self::Row),
99 0xD2 => Some(Self::NbcRow),
100 0xE3 => Some(Self::EnvChange),
101 0xED => Some(Self::Sspi),
102 0xFD => Some(Self::Done),
103 0xFF => Some(Self::DoneInProc),
104 0xFE => Some(Self::DoneProc),
105 0x79 => Some(Self::ReturnStatus),
106 0xAC => Some(Self::ReturnValue),
107 0xA9 => Some(Self::Order),
108 0xAE => Some(Self::FeatureExtAck),
109 0xE4 => Some(Self::SessionState),
110 0xEE => Some(Self::FedAuthInfo),
111 0xA5 => Some(Self::ColInfo),
112 0xA4 => Some(Self::TabName),
113 0x78 => Some(Self::Offset),
114 0x88 => Some(Self::AltMetaData),
115 0xD3 => Some(Self::AltRow),
116 _ => None,
117 }
118 }
119}
120
121#[derive(Debug, Clone)]
126#[non_exhaustive]
127pub enum Token {
128 ColMetaData(ColMetaData),
130 Row(RawRow),
132 NbcRow(NbcRow),
134 Done(Done),
136 DoneProc(DoneProc),
138 DoneInProc(DoneInProc),
140 ReturnStatus(i32),
142 ReturnValue(ReturnValue),
144 Error(ServerError),
146 Info(ServerInfo),
148 LoginAck(LoginAck),
150 EnvChange(EnvChange),
152 Order(Order),
154 FeatureExtAck(FeatureExtAck),
156 Sspi(SspiToken),
158 SessionState(SessionState),
160 FedAuthInfo(FedAuthInfo),
162}
163
164#[derive(Debug, Clone, Default)]
166pub struct ColMetaData {
167 pub columns: Vec<ColumnData>,
169 pub cek_table: Option<crate::crypto::CekTable>,
172}
173
174#[derive(Debug, Clone)]
176pub struct ColumnData {
177 pub name: String,
179 pub type_id: TypeId,
181 pub col_type: u8,
183 pub flags: u16,
185 pub user_type: u32,
187 pub type_info: TypeInfo,
189 pub crypto_metadata: Option<crate::crypto::CryptoMetadata>,
192}
193
194#[derive(Debug, Clone, Default)]
196pub struct TypeInfo {
197 pub max_length: Option<u32>,
199 pub precision: Option<u8>,
201 pub scale: Option<u8>,
203 pub collation: Option<Collation>,
205}
206
207#[derive(Debug, Clone, Copy, Default)]
230pub struct Collation {
231 pub lcid: u32,
239 pub sort_id: u8,
243}
244
245impl Collation {
246 pub fn from_bytes(bytes: &[u8; 5]) -> Self {
250 Self {
251 lcid: u32::from_le_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]),
252 sort_id: bytes[4],
253 }
254 }
255
256 pub fn to_bytes(&self) -> [u8; 5] {
260 let b = self.lcid.to_le_bytes();
261 [b[0], b[1], b[2], b[3], self.sort_id]
262 }
263
264 #[cfg(feature = "encoding")]
290 pub fn encoding(&self) -> Option<&'static encoding_rs::Encoding> {
291 if self.sort_id != 0 {
295 return crate::collation::encoding_for_sort_id(self.sort_id);
296 }
297 crate::collation::encoding_for_lcid(self.lcid)
298 }
299
300 #[cfg(feature = "encoding")]
305 pub fn is_utf8(&self) -> bool {
306 crate::collation::is_utf8_collation(self.lcid)
307 }
308
309 #[cfg(feature = "encoding")]
317 pub fn code_page(&self) -> Option<u16> {
318 if self.sort_id != 0 {
321 return crate::collation::code_page_for_sort_id(self.sort_id);
322 }
323 crate::collation::code_page_for_lcid(self.lcid)
324 }
325
326 #[cfg(feature = "encoding")]
330 pub fn encoding_name(&self) -> &'static str {
331 if self.sort_id != 0 {
332 return match crate::collation::encoding_for_sort_id(self.sort_id) {
333 Some(enc) => enc.name(),
334 None => "unsupported",
335 };
336 }
337 crate::collation::encoding_name_for_lcid(self.lcid)
338 }
339}
340
341#[derive(Debug, Clone)]
343pub struct RawRow {
344 pub data: bytes::Bytes,
346}
347
348#[derive(Debug, Clone)]
350pub struct NbcRow {
351 pub null_bitmap: Vec<u8>,
353 pub data: bytes::Bytes,
355}
356
357#[derive(Debug, Clone, Copy)]
359pub struct Done {
360 pub status: DoneStatus,
362 pub cur_cmd: u16,
364 pub row_count: u64,
366}
367
368#[derive(Debug, Clone, Copy, Default)]
370#[non_exhaustive]
371pub struct DoneStatus {
372 pub more: bool,
374 pub error: bool,
376 pub in_xact: bool,
378 pub count: bool,
380 pub attn: bool,
382 pub srverror: bool,
384}
385
386#[derive(Debug, Clone, Copy)]
388pub struct DoneInProc {
389 pub status: DoneStatus,
391 pub cur_cmd: u16,
393 pub row_count: u64,
395}
396
397#[derive(Debug, Clone, Copy)]
399pub struct DoneProc {
400 pub status: DoneStatus,
402 pub cur_cmd: u16,
404 pub row_count: u64,
406}
407
408#[derive(Debug, Clone)]
410#[non_exhaustive]
411pub struct ReturnValue {
412 pub param_ordinal: u16,
414 pub param_name: String,
416 pub status: u8,
418 pub user_type: u32,
420 pub flags: u16,
422 pub col_type: u8,
424 pub type_info: TypeInfo,
426 pub value: bytes::Bytes,
428}
429
430#[derive(Debug, Clone)]
432pub struct ServerError {
433 pub number: i32,
435 pub state: u8,
437 pub class: u8,
439 pub message: String,
441 pub server: String,
443 pub procedure: String,
445 pub line: i32,
447}
448
449#[derive(Debug, Clone)]
451pub struct ServerInfo {
452 pub number: i32,
454 pub state: u8,
456 pub class: u8,
458 pub message: String,
460 pub server: String,
462 pub procedure: String,
464 pub line: i32,
466}
467
468#[derive(Debug, Clone)]
470pub struct LoginAck {
471 pub interface: u8,
473 pub tds_version: u32,
475 pub prog_name: String,
477 pub prog_version: u32,
479}
480
481#[derive(Debug, Clone)]
483pub struct EnvChange {
484 pub env_type: EnvChangeType,
486 pub new_value: EnvChangeValue,
488 pub old_value: EnvChangeValue,
490}
491
492#[derive(Debug, Clone, Copy, PartialEq, Eq)]
494#[repr(u8)]
495#[non_exhaustive]
496pub enum EnvChangeType {
497 Database = 1,
499 Language = 2,
501 CharacterSet = 3,
503 PacketSize = 4,
505 UnicodeSortingLocalId = 5,
507 UnicodeComparisonFlags = 6,
509 SqlCollation = 7,
511 BeginTransaction = 8,
513 CommitTransaction = 9,
515 RollbackTransaction = 10,
517 EnlistDtcTransaction = 11,
519 DefectTransaction = 12,
521 RealTimeLogShipping = 13,
523 PromoteTransaction = 15,
525 TransactionManagerAddress = 16,
527 TransactionEnded = 17,
529 ResetConnectionCompletionAck = 18,
531 UserInstanceStarted = 19,
533 Routing = 20,
535}
536
537#[derive(Debug, Clone)]
539#[non_exhaustive]
540pub enum EnvChangeValue {
541 String(String),
543 Binary(bytes::Bytes),
545 Routing {
547 host: String,
549 port: u16,
551 },
552}
553
554#[derive(Debug, Clone)]
556pub struct Order {
557 pub columns: Vec<u16>,
559}
560
561#[derive(Debug, Clone)]
563pub struct FeatureExtAck {
564 pub features: Vec<FeatureAck>,
566}
567
568#[derive(Debug, Clone)]
570pub struct FeatureAck {
571 pub feature_id: u8,
573 pub data: bytes::Bytes,
575}
576
577#[derive(Debug, Clone)]
579pub struct SspiToken {
580 pub data: bytes::Bytes,
582}
583
584#[derive(Debug, Clone)]
586pub struct SessionState {
587 pub data: bytes::Bytes,
589}
590
591#[derive(Debug, Clone)]
593pub struct FedAuthInfo {
594 pub sts_url: String,
596 pub spn: String,
598}
599
600pub(crate) fn decode_collation(src: &mut impl Buf) -> Result<Collation, ProtocolError> {
608 if src.remaining() < 5 {
609 return Err(ProtocolError::UnexpectedEof);
610 }
611 let lcid = src.get_u32_le();
613 let sort_id = src.get_u8();
614 Ok(Collation { lcid, sort_id })
615}
616
617pub(crate) fn decode_type_info(
621 src: &mut impl Buf,
622 type_id: TypeId,
623 col_type: u8,
624) -> Result<TypeInfo, ProtocolError> {
625 match type_id {
626 TypeId::Null => Ok(TypeInfo::default()),
628 TypeId::Int1 | TypeId::Bit => Ok(TypeInfo::default()),
629 TypeId::Int2 => Ok(TypeInfo::default()),
630 TypeId::Int4 => Ok(TypeInfo::default()),
631 TypeId::Int8 => Ok(TypeInfo::default()),
632 TypeId::Float4 => Ok(TypeInfo::default()),
633 TypeId::Float8 => Ok(TypeInfo::default()),
634 TypeId::Money => Ok(TypeInfo::default()),
635 TypeId::Money4 => Ok(TypeInfo::default()),
636 TypeId::DateTime => Ok(TypeInfo::default()),
637 TypeId::DateTime4 => Ok(TypeInfo::default()),
638
639 TypeId::IntN | TypeId::BitN | TypeId::FloatN | TypeId::MoneyN | TypeId::DateTimeN => {
641 if src.remaining() < 1 {
642 return Err(ProtocolError::UnexpectedEof);
643 }
644 let max_length = src.get_u8() as u32;
645 Ok(TypeInfo {
646 max_length: Some(max_length),
647 ..Default::default()
648 })
649 }
650
651 TypeId::Guid => {
653 if src.remaining() < 1 {
654 return Err(ProtocolError::UnexpectedEof);
655 }
656 let max_length = src.get_u8() as u32;
657 Ok(TypeInfo {
658 max_length: Some(max_length),
659 ..Default::default()
660 })
661 }
662
663 TypeId::Decimal | TypeId::Numeric | TypeId::DecimalN | TypeId::NumericN => {
665 if src.remaining() < 3 {
666 return Err(ProtocolError::UnexpectedEof);
667 }
668 let max_length = src.get_u8() as u32;
669 let precision = src.get_u8();
670 let scale = src.get_u8();
671 Ok(TypeInfo {
672 max_length: Some(max_length),
673 precision: Some(precision),
674 scale: Some(scale),
675 ..Default::default()
676 })
677 }
678
679 TypeId::Char | TypeId::VarChar | TypeId::Binary | TypeId::VarBinary => {
681 if src.remaining() < 1 {
682 return Err(ProtocolError::UnexpectedEof);
683 }
684 let max_length = src.get_u8() as u32;
685 Ok(TypeInfo {
686 max_length: Some(max_length),
687 ..Default::default()
688 })
689 }
690
691 TypeId::BigVarChar | TypeId::BigChar => {
693 if src.remaining() < 7 {
694 return Err(ProtocolError::UnexpectedEof);
696 }
697 let max_length = src.get_u16_le() as u32;
698 let collation = decode_collation(src)?;
699 Ok(TypeInfo {
700 max_length: Some(max_length),
701 collation: Some(collation),
702 ..Default::default()
703 })
704 }
705
706 TypeId::BigVarBinary | TypeId::BigBinary => {
708 if src.remaining() < 2 {
709 return Err(ProtocolError::UnexpectedEof);
710 }
711 let max_length = src.get_u16_le() as u32;
712 Ok(TypeInfo {
713 max_length: Some(max_length),
714 ..Default::default()
715 })
716 }
717
718 TypeId::NChar | TypeId::NVarChar => {
720 if src.remaining() < 7 {
721 return Err(ProtocolError::UnexpectedEof);
723 }
724 let max_length = src.get_u16_le() as u32;
725 let collation = decode_collation(src)?;
726 Ok(TypeInfo {
727 max_length: Some(max_length),
728 collation: Some(collation),
729 ..Default::default()
730 })
731 }
732
733 TypeId::Date => Ok(TypeInfo::default()),
735
736 TypeId::Time | TypeId::DateTime2 | TypeId::DateTimeOffset => {
738 if src.remaining() < 1 {
739 return Err(ProtocolError::UnexpectedEof);
740 }
741 let scale = src.get_u8();
742 Ok(TypeInfo {
743 scale: Some(scale),
744 ..Default::default()
745 })
746 }
747
748 TypeId::Text | TypeId::NText | TypeId::Image => {
750 if src.remaining() < 4 {
752 return Err(ProtocolError::UnexpectedEof);
753 }
754 let max_length = src.get_u32_le();
755
756 let collation = if type_id == TypeId::Text || type_id == TypeId::NText {
758 if src.remaining() < 5 {
759 return Err(ProtocolError::UnexpectedEof);
760 }
761 Some(decode_collation(src)?)
762 } else {
763 None
764 };
765
766 if src.remaining() < 1 {
769 return Err(ProtocolError::UnexpectedEof);
770 }
771 let num_parts = src.get_u8();
772 for _ in 0..num_parts {
773 let _ = read_us_varchar(src).ok_or(ProtocolError::UnexpectedEof)?;
775 }
776
777 Ok(TypeInfo {
778 max_length: Some(max_length),
779 collation,
780 ..Default::default()
781 })
782 }
783
784 TypeId::Xml => {
786 if src.remaining() < 1 {
787 return Err(ProtocolError::UnexpectedEof);
788 }
789 let schema_present = src.get_u8();
790
791 if schema_present != 0 {
792 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)?; }
799
800 Ok(TypeInfo::default())
801 }
802
803 TypeId::Udt => {
805 if src.remaining() < 2 {
807 return Err(ProtocolError::UnexpectedEof);
808 }
809 let max_length = src.get_u16_le() as u32;
810
811 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 {
820 max_length: Some(max_length),
821 ..Default::default()
822 })
823 }
824
825 TypeId::Tvp => {
827 Err(ProtocolError::InvalidTokenType(col_type))
830 }
831
832 TypeId::Variant => {
834 if src.remaining() < 4 {
835 return Err(ProtocolError::UnexpectedEof);
836 }
837 let max_length = src.get_u32_le();
838 Ok(TypeInfo {
839 max_length: Some(max_length),
840 ..Default::default()
841 })
842 }
843 }
844}
845
846impl ColMetaData {
847 pub const NO_METADATA: u16 = 0xFFFF;
849
850 pub fn decode(src: &mut impl Buf) -> Result<Self, ProtocolError> {
852 if src.remaining() < 2 {
853 return Err(ProtocolError::UnexpectedEof);
854 }
855
856 let column_count = src.get_u16_le();
857
858 if column_count == Self::NO_METADATA {
860 return Ok(Self {
861 columns: Vec::new(),
862 cek_table: None,
863 });
864 }
865
866 let mut columns = Vec::with_capacity(column_count as usize);
867
868 for _ in 0..column_count {
869 let column = Self::decode_column(src)?;
870 columns.push(column);
871 }
872
873 Ok(Self {
874 columns,
875 cek_table: None,
876 })
877 }
878
879 fn decode_alt(src: &mut impl Buf) -> Result<(u16, Self), ProtocolError> {
893 if src.remaining() < 5 {
895 return Err(ProtocolError::UnexpectedEof);
896 }
897 let count = src.get_u16_le();
898 let id = src.get_u16_le();
899 let by_cols = src.get_u8() as usize;
900
901 if src.remaining() < by_cols * 2 {
904 return Err(ProtocolError::UnexpectedEof);
905 }
906 for _ in 0..by_cols {
907 let _ = src.get_u16_le();
908 }
909
910 let mut columns = Vec::with_capacity(count as usize);
911 for _ in 0..count {
912 if src.remaining() < 3 {
914 return Err(ProtocolError::UnexpectedEof);
915 }
916 let _op = src.get_u8();
917 let _operand = src.get_u16_le();
918 columns.push(Self::decode_column(src)?);
919 }
920
921 Ok((
922 id,
923 Self {
924 columns,
925 cek_table: None,
926 },
927 ))
928 }
929
930 fn decode_column(src: &mut impl Buf) -> Result<ColumnData, ProtocolError> {
932 if src.remaining() < 7 {
934 return Err(ProtocolError::UnexpectedEof);
935 }
936
937 let user_type = src.get_u32_le();
938 let flags = src.get_u16_le();
939 let col_type = src.get_u8();
940
941 let type_id = TypeId::from_u8(col_type).ok_or(ProtocolError::InvalidDataType(col_type))?;
945
946 let type_info = decode_type_info(src, type_id, col_type)?;
948
949 let name = read_b_varchar(src).ok_or(ProtocolError::UnexpectedEof)?;
951
952 Ok(ColumnData {
953 name,
954 type_id,
955 col_type,
956 flags,
957 user_type,
958 type_info,
959 crypto_metadata: None,
960 })
961 }
962
963 pub fn decode_encrypted(src: &mut impl Buf) -> Result<Self, ProtocolError> {
976 if src.remaining() < 2 {
977 return Err(ProtocolError::UnexpectedEof);
978 }
979
980 let column_count = src.get_u16_le();
981
982 if column_count == Self::NO_METADATA {
983 return Ok(Self {
984 columns: Vec::new(),
985 cek_table: None,
986 });
987 }
988
989 let cek_table = crate::crypto::CekTable::decode(src)?;
991
992 let mut columns = Vec::with_capacity(column_count as usize);
993
994 for _ in 0..column_count {
995 let column = Self::decode_column_encrypted(src)?;
996 columns.push(column);
997 }
998
999 Ok(Self {
1000 columns,
1001 cek_table: Some(cek_table),
1002 })
1003 }
1004
1005 fn decode_column_encrypted(src: &mut impl Buf) -> Result<ColumnData, ProtocolError> {
1009 if src.remaining() < 7 {
1010 return Err(ProtocolError::UnexpectedEof);
1011 }
1012
1013 let user_type = src.get_u32_le();
1014 let flags = src.get_u16_le();
1015 let col_type = src.get_u8();
1016
1017 let type_id = TypeId::from_u8(col_type).ok_or(ProtocolError::InvalidDataType(col_type))?;
1018
1019 let type_info = decode_type_info(src, type_id, col_type)?;
1021
1022 let crypto_metadata = if crate::crypto::is_column_encrypted(flags) {
1024 Some(crate::crypto::CryptoMetadata::decode(src)?)
1025 } else {
1026 None
1027 };
1028
1029 let name = read_b_varchar(src).ok_or(ProtocolError::UnexpectedEof)?;
1031
1032 Ok(ColumnData {
1033 name,
1034 type_id,
1035 col_type,
1036 flags,
1037 user_type,
1038 type_info,
1039 crypto_metadata,
1040 })
1041 }
1042
1043 #[must_use]
1045 pub fn column_count(&self) -> usize {
1046 self.columns.len()
1047 }
1048
1049 #[must_use]
1051 pub fn is_empty(&self) -> bool {
1052 self.columns.is_empty()
1053 }
1054}
1055
1056impl ColumnData {
1057 #[must_use]
1059 pub fn is_nullable(&self) -> bool {
1060 (self.flags & 0x0001) != 0
1061 }
1062
1063 #[must_use]
1067 pub fn fixed_size(&self) -> Option<usize> {
1068 match self.type_id {
1069 TypeId::Null => Some(0),
1070 TypeId::Int1 | TypeId::Bit => Some(1),
1071 TypeId::Int2 => Some(2),
1072 TypeId::Int4 => Some(4),
1073 TypeId::Int8 => Some(8),
1074 TypeId::Float4 => Some(4),
1075 TypeId::Float8 => Some(8),
1076 TypeId::Money => Some(8),
1077 TypeId::Money4 => Some(4),
1078 TypeId::DateTime => Some(8),
1079 TypeId::DateTime4 => Some(4),
1080 TypeId::Date => Some(3),
1081 _ => None,
1082 }
1083 }
1084}
1085
1086impl RawRow {
1091 pub fn decode(src: &mut impl Buf, metadata: &ColMetaData) -> Result<Self, ProtocolError> {
1096 let mut data = bytes::BytesMut::new();
1097
1098 for col in &metadata.columns {
1099 Self::decode_column_value(src, col, &mut data)?;
1100 }
1101
1102 Ok(Self {
1103 data: data.freeze(),
1104 })
1105 }
1106
1107 pub fn decode_prefix(
1114 src: &mut impl Buf,
1115 metadata: &ColMetaData,
1116 prefix_len: usize,
1117 ) -> Result<Self, ProtocolError> {
1118 let mut data = bytes::BytesMut::new();
1119 for col in metadata.columns.iter().take(prefix_len) {
1120 Self::decode_column_value(src, col, &mut data)?;
1121 }
1122 Ok(Self {
1123 data: data.freeze(),
1124 })
1125 }
1126
1127 fn decode_column_value(
1129 src: &mut impl Buf,
1130 col: &ColumnData,
1131 dst: &mut bytes::BytesMut,
1132 ) -> Result<(), ProtocolError> {
1133 match col.type_id {
1134 TypeId::Null => {
1136 }
1138 TypeId::Int1 | TypeId::Bit => {
1139 if src.remaining() < 1 {
1140 return Err(ProtocolError::UnexpectedEof);
1141 }
1142 dst.extend_from_slice(&[src.get_u8()]);
1143 }
1144 TypeId::Int2 => {
1145 if src.remaining() < 2 {
1146 return Err(ProtocolError::UnexpectedEof);
1147 }
1148 dst.extend_from_slice(&src.get_u16_le().to_le_bytes());
1149 }
1150 TypeId::Int4 => {
1151 if src.remaining() < 4 {
1152 return Err(ProtocolError::UnexpectedEof);
1153 }
1154 dst.extend_from_slice(&src.get_u32_le().to_le_bytes());
1155 }
1156 TypeId::Int8 => {
1157 if src.remaining() < 8 {
1158 return Err(ProtocolError::UnexpectedEof);
1159 }
1160 dst.extend_from_slice(&src.get_u64_le().to_le_bytes());
1161 }
1162 TypeId::Float4 => {
1163 if src.remaining() < 4 {
1164 return Err(ProtocolError::UnexpectedEof);
1165 }
1166 dst.extend_from_slice(&src.get_u32_le().to_le_bytes());
1167 }
1168 TypeId::Float8 => {
1169 if src.remaining() < 8 {
1170 return Err(ProtocolError::UnexpectedEof);
1171 }
1172 dst.extend_from_slice(&src.get_u64_le().to_le_bytes());
1173 }
1174 TypeId::Money => {
1175 if src.remaining() < 8 {
1176 return Err(ProtocolError::UnexpectedEof);
1177 }
1178 let hi = src.get_u32_le();
1179 let lo = src.get_u32_le();
1180 dst.extend_from_slice(&hi.to_le_bytes());
1181 dst.extend_from_slice(&lo.to_le_bytes());
1182 }
1183 TypeId::Money4 => {
1184 if src.remaining() < 4 {
1185 return Err(ProtocolError::UnexpectedEof);
1186 }
1187 dst.extend_from_slice(&src.get_u32_le().to_le_bytes());
1188 }
1189 TypeId::DateTime => {
1190 if src.remaining() < 8 {
1191 return Err(ProtocolError::UnexpectedEof);
1192 }
1193 let days = src.get_u32_le();
1194 let time = src.get_u32_le();
1195 dst.extend_from_slice(&days.to_le_bytes());
1196 dst.extend_from_slice(&time.to_le_bytes());
1197 }
1198 TypeId::DateTime4 => {
1199 if src.remaining() < 4 {
1200 return Err(ProtocolError::UnexpectedEof);
1201 }
1202 dst.extend_from_slice(&src.get_u32_le().to_le_bytes());
1203 }
1204 TypeId::Date => {
1206 Self::decode_bytelen_type(src, dst)?;
1207 }
1208
1209 TypeId::IntN | TypeId::BitN | TypeId::FloatN | TypeId::MoneyN | TypeId::DateTimeN => {
1211 Self::decode_bytelen_type(src, dst)?;
1212 }
1213
1214 TypeId::Guid => {
1215 Self::decode_bytelen_type(src, dst)?;
1216 }
1217
1218 TypeId::Decimal | TypeId::Numeric | TypeId::DecimalN | TypeId::NumericN => {
1219 Self::decode_bytelen_type(src, dst)?;
1220 }
1221
1222 TypeId::Char | TypeId::VarChar | TypeId::Binary | TypeId::VarBinary => {
1224 Self::decode_bytelen_type(src, dst)?;
1225 }
1226
1227 TypeId::BigVarChar | TypeId::BigVarBinary => {
1229 if col.type_info.max_length == Some(0xFFFF) {
1231 Self::decode_plp_type(src, dst)?;
1232 } else {
1233 Self::decode_ushortlen_type(src, dst)?;
1234 }
1235 }
1236
1237 TypeId::BigChar | TypeId::BigBinary => {
1239 Self::decode_ushortlen_type(src, dst)?;
1240 }
1241
1242 TypeId::NVarChar => {
1244 if col.type_info.max_length == Some(0xFFFF) {
1246 Self::decode_plp_type(src, dst)?;
1247 } else {
1248 Self::decode_ushortlen_type(src, dst)?;
1249 }
1250 }
1251
1252 TypeId::NChar => {
1254 Self::decode_ushortlen_type(src, dst)?;
1255 }
1256
1257 TypeId::Time | TypeId::DateTime2 | TypeId::DateTimeOffset => {
1259 Self::decode_bytelen_type(src, dst)?;
1260 }
1261
1262 TypeId::Text | TypeId::NText | TypeId::Image => {
1264 Self::decode_textptr_type(src, dst)?;
1265 }
1266
1267 TypeId::Xml => {
1269 Self::decode_plp_type(src, dst)?;
1270 }
1271
1272 TypeId::Variant => {
1274 Self::decode_intlen_type(src, dst)?;
1275 }
1276
1277 TypeId::Udt => {
1278 Self::decode_plp_type(src, dst)?;
1280 }
1281
1282 TypeId::Tvp => {
1283 return Err(ProtocolError::InvalidTokenType(col.col_type));
1285 }
1286 }
1287
1288 Ok(())
1289 }
1290
1291 fn decode_bytelen_type(
1293 src: &mut impl Buf,
1294 dst: &mut bytes::BytesMut,
1295 ) -> Result<(), ProtocolError> {
1296 if src.remaining() < 1 {
1297 return Err(ProtocolError::UnexpectedEof);
1298 }
1299 let len = src.get_u8() as usize;
1300 if len == 0xFF {
1301 dst.extend_from_slice(&[0xFF]);
1303 } else if len == 0 {
1304 dst.extend_from_slice(&[0x00]);
1306 } else {
1307 if src.remaining() < len {
1308 return Err(ProtocolError::UnexpectedEof);
1309 }
1310 dst.extend_from_slice(&[len as u8]);
1311 for _ in 0..len {
1312 dst.extend_from_slice(&[src.get_u8()]);
1313 }
1314 }
1315 Ok(())
1316 }
1317
1318 fn decode_ushortlen_type(
1320 src: &mut impl Buf,
1321 dst: &mut bytes::BytesMut,
1322 ) -> Result<(), ProtocolError> {
1323 if src.remaining() < 2 {
1324 return Err(ProtocolError::UnexpectedEof);
1325 }
1326 let len = src.get_u16_le() as usize;
1327 if len == 0xFFFF {
1328 dst.extend_from_slice(&0xFFFFu16.to_le_bytes());
1330 } else if len == 0 {
1331 dst.extend_from_slice(&0u16.to_le_bytes());
1333 } else {
1334 if src.remaining() < len {
1335 return Err(ProtocolError::UnexpectedEof);
1336 }
1337 dst.extend_from_slice(&(len as u16).to_le_bytes());
1338 for _ in 0..len {
1339 dst.extend_from_slice(&[src.get_u8()]);
1340 }
1341 }
1342 Ok(())
1343 }
1344
1345 fn decode_intlen_type(
1347 src: &mut impl Buf,
1348 dst: &mut bytes::BytesMut,
1349 ) -> Result<(), ProtocolError> {
1350 if src.remaining() < 4 {
1351 return Err(ProtocolError::UnexpectedEof);
1352 }
1353 let len = src.get_u32_le() as usize;
1354 if len == 0xFFFFFFFF {
1355 dst.extend_from_slice(&0xFFFFFFFFu32.to_le_bytes());
1357 } else if len == 0 {
1358 dst.extend_from_slice(&0u32.to_le_bytes());
1360 } else {
1361 if src.remaining() < len {
1362 return Err(ProtocolError::UnexpectedEof);
1363 }
1364 dst.extend_from_slice(&(len as u32).to_le_bytes());
1365 for _ in 0..len {
1366 dst.extend_from_slice(&[src.get_u8()]);
1367 }
1368 }
1369 Ok(())
1370 }
1371
1372 fn decode_textptr_type(
1387 src: &mut impl Buf,
1388 dst: &mut bytes::BytesMut,
1389 ) -> Result<(), ProtocolError> {
1390 if src.remaining() < 1 {
1391 return Err(ProtocolError::UnexpectedEof);
1392 }
1393
1394 let textptr_len = src.get_u8() as usize;
1395
1396 if textptr_len == 0 {
1397 dst.extend_from_slice(&0xFFFFFFFFFFFFFFFFu64.to_le_bytes());
1399 return Ok(());
1400 }
1401
1402 if src.remaining() < textptr_len {
1404 return Err(ProtocolError::UnexpectedEof);
1405 }
1406 src.advance(textptr_len);
1407
1408 if src.remaining() < 8 {
1410 return Err(ProtocolError::UnexpectedEof);
1411 }
1412 src.advance(8);
1413
1414 if src.remaining() < 4 {
1416 return Err(ProtocolError::UnexpectedEof);
1417 }
1418 let data_len = src.get_u32_le() as usize;
1419
1420 if src.remaining() < data_len {
1421 return Err(ProtocolError::UnexpectedEof);
1422 }
1423
1424 dst.extend_from_slice(&(data_len as u64).to_le_bytes());
1430 dst.extend_from_slice(&(data_len as u32).to_le_bytes());
1431 for _ in 0..data_len {
1432 dst.extend_from_slice(&[src.get_u8()]);
1433 }
1434 dst.extend_from_slice(&0u32.to_le_bytes()); Ok(())
1437 }
1438
1439 fn decode_plp_type(src: &mut impl Buf, dst: &mut bytes::BytesMut) -> Result<(), ProtocolError> {
1445 if src.remaining() < 8 {
1446 return Err(ProtocolError::UnexpectedEof);
1447 }
1448
1449 let total_len = src.get_u64_le();
1450
1451 dst.extend_from_slice(&total_len.to_le_bytes());
1453
1454 if total_len == 0xFFFFFFFFFFFFFFFF {
1455 return Ok(());
1457 }
1458
1459 loop {
1461 if src.remaining() < 4 {
1462 return Err(ProtocolError::UnexpectedEof);
1463 }
1464 let chunk_len = src.get_u32_le() as usize;
1465 dst.extend_from_slice(&(chunk_len as u32).to_le_bytes());
1466
1467 if chunk_len == 0 {
1468 break;
1470 }
1471
1472 if src.remaining() < chunk_len {
1473 return Err(ProtocolError::UnexpectedEof);
1474 }
1475
1476 for _ in 0..chunk_len {
1477 dst.extend_from_slice(&[src.get_u8()]);
1478 }
1479 }
1480
1481 Ok(())
1482 }
1483}
1484
1485impl NbcRow {
1490 pub fn decode(src: &mut impl Buf, metadata: &ColMetaData) -> Result<Self, ProtocolError> {
1495 let col_count = metadata.columns.len();
1496 let bitmap_len = col_count.div_ceil(8);
1497
1498 if src.remaining() < bitmap_len {
1499 return Err(ProtocolError::UnexpectedEof);
1500 }
1501
1502 let mut null_bitmap = vec![0u8; bitmap_len];
1504 for byte in &mut null_bitmap {
1505 *byte = src.get_u8();
1506 }
1507
1508 let mut data = bytes::BytesMut::new();
1510
1511 for (i, col) in metadata.columns.iter().enumerate() {
1512 let byte_idx = i / 8;
1513 let bit_idx = i % 8;
1514 let is_null = (null_bitmap[byte_idx] & (1 << bit_idx)) != 0;
1515
1516 if !is_null {
1517 RawRow::decode_column_value(src, col, &mut data)?;
1520 }
1521 }
1522
1523 Ok(Self {
1524 null_bitmap,
1525 data: data.freeze(),
1526 })
1527 }
1528
1529 pub fn decode_prefix(
1535 src: &mut impl Buf,
1536 metadata: &ColMetaData,
1537 prefix_len: usize,
1538 ) -> Result<Self, ProtocolError> {
1539 let col_count = metadata.columns.len();
1540 let bitmap_len = col_count.div_ceil(8);
1541
1542 if src.remaining() < bitmap_len {
1543 return Err(ProtocolError::UnexpectedEof);
1544 }
1545
1546 let mut null_bitmap = vec![0u8; bitmap_len];
1547 for byte in &mut null_bitmap {
1548 *byte = src.get_u8();
1549 }
1550
1551 let mut data = bytes::BytesMut::new();
1552 for (i, col) in metadata.columns.iter().enumerate().take(prefix_len) {
1553 let is_null = (null_bitmap[i / 8] & (1 << (i % 8))) != 0;
1554 if !is_null {
1555 RawRow::decode_column_value(src, col, &mut data)?;
1556 }
1557 }
1558
1559 Ok(Self {
1560 null_bitmap,
1561 data: data.freeze(),
1562 })
1563 }
1564
1565 #[must_use]
1567 pub fn is_null(&self, column_index: usize) -> bool {
1568 let byte_idx = column_index / 8;
1569 let bit_idx = column_index % 8;
1570 if byte_idx < self.null_bitmap.len() {
1571 (self.null_bitmap[byte_idx] & (1 << bit_idx)) != 0
1572 } else {
1573 true }
1575 }
1576}
1577
1578impl ReturnValue {
1583 pub fn decode(src: &mut impl Buf) -> Result<Self, ProtocolError> {
1585 if src.remaining() < 2 {
1592 return Err(ProtocolError::UnexpectedEof);
1593 }
1594 let param_ordinal = src.get_u16_le();
1595
1596 let param_name = read_b_varchar(src).ok_or(ProtocolError::UnexpectedEof)?;
1598
1599 if src.remaining() < 1 {
1601 return Err(ProtocolError::UnexpectedEof);
1602 }
1603 let status = src.get_u8();
1604
1605 if src.remaining() < 7 {
1607 return Err(ProtocolError::UnexpectedEof);
1608 }
1609 let user_type = src.get_u32_le();
1610 let flags = src.get_u16_le();
1611 let col_type = src.get_u8();
1612
1613 let type_id = TypeId::from_u8(col_type).ok_or(ProtocolError::InvalidDataType(col_type))?;
1614
1615 let type_info = decode_type_info(src, type_id, col_type)?;
1617
1618 let mut value_buf = bytes::BytesMut::new();
1620
1621 let temp_col = ColumnData {
1623 name: String::new(),
1624 type_id,
1625 col_type,
1626 flags,
1627 user_type,
1628 type_info: type_info.clone(),
1629 crypto_metadata: None,
1630 };
1631
1632 RawRow::decode_column_value(src, &temp_col, &mut value_buf)?;
1633
1634 Ok(Self {
1635 param_ordinal,
1636 param_name,
1637 status,
1638 user_type,
1639 flags,
1640 col_type,
1641 type_info,
1642 value: value_buf.freeze(),
1643 })
1644 }
1645}
1646
1647impl SessionState {
1652 pub fn decode(src: &mut impl Buf) -> Result<Self, ProtocolError> {
1654 if src.remaining() < 4 {
1655 return Err(ProtocolError::UnexpectedEof);
1656 }
1657
1658 let length = src.get_u32_le() as usize;
1659
1660 if src.remaining() < length {
1661 return Err(ProtocolError::IncompletePacket {
1662 expected: length,
1663 actual: src.remaining(),
1664 });
1665 }
1666
1667 let data = src.copy_to_bytes(length);
1668
1669 Ok(Self { data })
1670 }
1671}
1672
1673mod done_status_bits {
1679 pub const DONE_MORE: u16 = 0x0001;
1680 pub const DONE_ERROR: u16 = 0x0002;
1681 pub const DONE_INXACT: u16 = 0x0004;
1682 pub const DONE_COUNT: u16 = 0x0010;
1683 pub const DONE_ATTN: u16 = 0x0020;
1684 pub const DONE_SRVERROR: u16 = 0x0100;
1685}
1686
1687impl DoneStatus {
1688 #[must_use]
1690 pub fn from_bits(bits: u16) -> Self {
1691 use done_status_bits::*;
1692 Self {
1693 more: (bits & DONE_MORE) != 0,
1694 error: (bits & DONE_ERROR) != 0,
1695 in_xact: (bits & DONE_INXACT) != 0,
1696 count: (bits & DONE_COUNT) != 0,
1697 attn: (bits & DONE_ATTN) != 0,
1698 srverror: (bits & DONE_SRVERROR) != 0,
1699 }
1700 }
1701
1702 #[must_use]
1704 pub fn to_bits(&self) -> u16 {
1705 use done_status_bits::*;
1706 let mut bits = 0u16;
1707 if self.more {
1708 bits |= DONE_MORE;
1709 }
1710 if self.error {
1711 bits |= DONE_ERROR;
1712 }
1713 if self.in_xact {
1714 bits |= DONE_INXACT;
1715 }
1716 if self.count {
1717 bits |= DONE_COUNT;
1718 }
1719 if self.attn {
1720 bits |= DONE_ATTN;
1721 }
1722 if self.srverror {
1723 bits |= DONE_SRVERROR;
1724 }
1725 bits
1726 }
1727}
1728
1729impl Done {
1730 pub const SIZE: usize = 12; pub fn decode(src: &mut impl Buf) -> Result<Self, ProtocolError> {
1735 if src.remaining() < Self::SIZE {
1736 return Err(ProtocolError::IncompletePacket {
1737 expected: Self::SIZE,
1738 actual: src.remaining(),
1739 });
1740 }
1741
1742 let status = DoneStatus::from_bits(src.get_u16_le());
1743 let cur_cmd = src.get_u16_le();
1744 let row_count = src.get_u64_le();
1745
1746 Ok(Self {
1747 status,
1748 cur_cmd,
1749 row_count,
1750 })
1751 }
1752
1753 pub fn encode(&self, dst: &mut impl BufMut) {
1755 dst.put_u8(TokenType::Done as u8);
1756 dst.put_u16_le(self.status.to_bits());
1757 dst.put_u16_le(self.cur_cmd);
1758 dst.put_u64_le(self.row_count);
1759 }
1760
1761 #[must_use]
1763 pub const fn has_more(&self) -> bool {
1764 self.status.more
1765 }
1766
1767 #[must_use]
1769 pub const fn has_error(&self) -> bool {
1770 self.status.error
1771 }
1772
1773 #[must_use]
1775 pub const fn has_count(&self) -> bool {
1776 self.status.count
1777 }
1778}
1779
1780impl DoneProc {
1781 pub const SIZE: usize = 12;
1783
1784 pub fn decode(src: &mut impl Buf) -> Result<Self, ProtocolError> {
1786 if src.remaining() < Self::SIZE {
1787 return Err(ProtocolError::IncompletePacket {
1788 expected: Self::SIZE,
1789 actual: src.remaining(),
1790 });
1791 }
1792
1793 let status = DoneStatus::from_bits(src.get_u16_le());
1794 let cur_cmd = src.get_u16_le();
1795 let row_count = src.get_u64_le();
1796
1797 Ok(Self {
1798 status,
1799 cur_cmd,
1800 row_count,
1801 })
1802 }
1803
1804 pub fn encode(&self, dst: &mut impl BufMut) {
1806 dst.put_u8(TokenType::DoneProc as u8);
1807 dst.put_u16_le(self.status.to_bits());
1808 dst.put_u16_le(self.cur_cmd);
1809 dst.put_u64_le(self.row_count);
1810 }
1811}
1812
1813impl DoneInProc {
1814 pub const SIZE: usize = 12;
1816
1817 pub fn decode(src: &mut impl Buf) -> Result<Self, ProtocolError> {
1819 if src.remaining() < Self::SIZE {
1820 return Err(ProtocolError::IncompletePacket {
1821 expected: Self::SIZE,
1822 actual: src.remaining(),
1823 });
1824 }
1825
1826 let status = DoneStatus::from_bits(src.get_u16_le());
1827 let cur_cmd = src.get_u16_le();
1828 let row_count = src.get_u64_le();
1829
1830 Ok(Self {
1831 status,
1832 cur_cmd,
1833 row_count,
1834 })
1835 }
1836
1837 pub fn encode(&self, dst: &mut impl BufMut) {
1839 dst.put_u8(TokenType::DoneInProc as u8);
1840 dst.put_u16_le(self.status.to_bits());
1841 dst.put_u16_le(self.cur_cmd);
1842 dst.put_u64_le(self.row_count);
1843 }
1844}
1845
1846impl ServerError {
1847 pub fn decode(src: &mut impl Buf) -> Result<Self, ProtocolError> {
1849 if src.remaining() < 2 {
1852 return Err(ProtocolError::UnexpectedEof);
1853 }
1854
1855 let _length = src.get_u16_le();
1856
1857 if src.remaining() < 6 {
1858 return Err(ProtocolError::UnexpectedEof);
1859 }
1860
1861 let number = src.get_i32_le();
1862 let state = src.get_u8();
1863 let class = src.get_u8();
1864
1865 let message = read_us_varchar(src).ok_or(ProtocolError::UnexpectedEof)?;
1866 let server = read_b_varchar(src).ok_or(ProtocolError::UnexpectedEof)?;
1867 let procedure = read_b_varchar(src).ok_or(ProtocolError::UnexpectedEof)?;
1868
1869 if src.remaining() < 4 {
1870 return Err(ProtocolError::UnexpectedEof);
1871 }
1872 let line = src.get_i32_le();
1873
1874 Ok(Self {
1875 number,
1876 state,
1877 class,
1878 message,
1879 server,
1880 procedure,
1881 line,
1882 })
1883 }
1884
1885 #[must_use]
1887 pub const fn is_fatal(&self) -> bool {
1888 self.class >= 20
1889 }
1890
1891 #[must_use]
1893 pub const fn is_batch_abort(&self) -> bool {
1894 self.class >= 16
1895 }
1896}
1897
1898impl ServerInfo {
1899 pub fn decode(src: &mut impl Buf) -> Result<Self, ProtocolError> {
1903 if src.remaining() < 2 {
1904 return Err(ProtocolError::UnexpectedEof);
1905 }
1906
1907 let _length = src.get_u16_le();
1908
1909 if src.remaining() < 6 {
1910 return Err(ProtocolError::UnexpectedEof);
1911 }
1912
1913 let number = src.get_i32_le();
1914 let state = src.get_u8();
1915 let class = src.get_u8();
1916
1917 let message = read_us_varchar(src).ok_or(ProtocolError::UnexpectedEof)?;
1918 let server = read_b_varchar(src).ok_or(ProtocolError::UnexpectedEof)?;
1919 let procedure = read_b_varchar(src).ok_or(ProtocolError::UnexpectedEof)?;
1920
1921 if src.remaining() < 4 {
1922 return Err(ProtocolError::UnexpectedEof);
1923 }
1924 let line = src.get_i32_le();
1925
1926 Ok(Self {
1927 number,
1928 state,
1929 class,
1930 message,
1931 server,
1932 procedure,
1933 line,
1934 })
1935 }
1936}
1937
1938impl LoginAck {
1939 pub fn decode(src: &mut impl Buf) -> Result<Self, ProtocolError> {
1941 if src.remaining() < 2 {
1943 return Err(ProtocolError::UnexpectedEof);
1944 }
1945
1946 let _length = src.get_u16_le();
1947
1948 if src.remaining() < 5 {
1949 return Err(ProtocolError::UnexpectedEof);
1950 }
1951
1952 let interface = src.get_u8();
1953 let tds_version = src.get_u32_le();
1954 let prog_name = read_b_varchar(src).ok_or(ProtocolError::UnexpectedEof)?;
1955
1956 if src.remaining() < 4 {
1957 return Err(ProtocolError::UnexpectedEof);
1958 }
1959 let prog_version = src.get_u32_le();
1960
1961 Ok(Self {
1962 interface,
1963 tds_version,
1964 prog_name,
1965 prog_version,
1966 })
1967 }
1968
1969 #[must_use]
1971 pub fn tds_version(&self) -> crate::version::TdsVersion {
1972 crate::version::TdsVersion::new(self.tds_version)
1973 }
1974}
1975
1976impl EnvChangeType {
1977 pub fn from_u8(value: u8) -> Option<Self> {
1979 match value {
1980 1 => Some(Self::Database),
1981 2 => Some(Self::Language),
1982 3 => Some(Self::CharacterSet),
1983 4 => Some(Self::PacketSize),
1984 5 => Some(Self::UnicodeSortingLocalId),
1985 6 => Some(Self::UnicodeComparisonFlags),
1986 7 => Some(Self::SqlCollation),
1987 8 => Some(Self::BeginTransaction),
1988 9 => Some(Self::CommitTransaction),
1989 10 => Some(Self::RollbackTransaction),
1990 11 => Some(Self::EnlistDtcTransaction),
1991 12 => Some(Self::DefectTransaction),
1992 13 => Some(Self::RealTimeLogShipping),
1993 15 => Some(Self::PromoteTransaction),
1994 16 => Some(Self::TransactionManagerAddress),
1995 17 => Some(Self::TransactionEnded),
1996 18 => Some(Self::ResetConnectionCompletionAck),
1997 19 => Some(Self::UserInstanceStarted),
1998 20 => Some(Self::Routing),
1999 _ => None,
2000 }
2001 }
2002}
2003
2004impl EnvChange {
2005 pub fn decode(src: &mut impl Buf) -> Result<Self, ProtocolError> {
2007 if src.remaining() < 3 {
2008 return Err(ProtocolError::UnexpectedEof);
2009 }
2010
2011 let length = src.get_u16_le() as usize;
2012 if length == 0 {
2013 return Err(ProtocolError::UnexpectedEof);
2016 }
2017 if src.remaining() < length {
2018 return Err(ProtocolError::IncompletePacket {
2019 expected: length,
2020 actual: src.remaining(),
2021 });
2022 }
2023
2024 let mut frame = src.copy_to_bytes(length);
2033 let src = &mut frame;
2034
2035 let env_type_byte = src.get_u8();
2036 let env_type = EnvChangeType::from_u8(env_type_byte)
2037 .ok_or(ProtocolError::InvalidTokenType(env_type_byte))?;
2038
2039 let (new_value, old_value) = match env_type {
2040 EnvChangeType::Routing => {
2041 let new_value = Self::decode_routing_value(src)?;
2043 let old_value = EnvChangeValue::Binary(Bytes::new());
2044 (new_value, old_value)
2045 }
2046 EnvChangeType::BeginTransaction
2047 | EnvChangeType::CommitTransaction
2048 | EnvChangeType::RollbackTransaction
2049 | EnvChangeType::EnlistDtcTransaction
2050 | EnvChangeType::SqlCollation => {
2051 let new_len = if src.has_remaining() {
2060 src.get_u8() as usize
2061 } else {
2062 0
2063 };
2064 let new_value = if new_len > 0 && src.remaining() >= new_len {
2065 EnvChangeValue::Binary(src.copy_to_bytes(new_len))
2066 } else {
2067 EnvChangeValue::Binary(Bytes::new())
2068 };
2069
2070 let old_len = if src.has_remaining() {
2071 src.get_u8() as usize
2072 } else {
2073 0
2074 };
2075 let old_value = if old_len > 0 && src.remaining() >= old_len {
2076 EnvChangeValue::Binary(src.copy_to_bytes(old_len))
2077 } else {
2078 EnvChangeValue::Binary(Bytes::new())
2079 };
2080
2081 (new_value, old_value)
2082 }
2083 _ => {
2084 let new_value = read_b_varchar(src)
2086 .map(EnvChangeValue::String)
2087 .unwrap_or(EnvChangeValue::String(String::new()));
2088
2089 let old_value = read_b_varchar(src)
2090 .map(EnvChangeValue::String)
2091 .unwrap_or(EnvChangeValue::String(String::new()));
2092
2093 (new_value, old_value)
2094 }
2095 };
2096
2097 Ok(Self {
2103 env_type,
2104 new_value,
2105 old_value,
2106 })
2107 }
2108
2109 fn decode_routing_value(src: &mut impl Buf) -> Result<EnvChangeValue, ProtocolError> {
2110 if src.remaining() < 2 {
2112 return Err(ProtocolError::UnexpectedEof);
2113 }
2114
2115 let _routing_len = src.get_u16_le();
2116
2117 if src.remaining() < 5 {
2118 return Err(ProtocolError::UnexpectedEof);
2119 }
2120
2121 let _protocol = src.get_u8();
2122 let port = src.get_u16_le();
2123 let server_len = src.get_u16_le() as usize;
2124
2125 if src.remaining() < server_len * 2 {
2127 return Err(ProtocolError::UnexpectedEof);
2128 }
2129
2130 let mut chars = Vec::with_capacity(server_len);
2131 for _ in 0..server_len {
2132 chars.push(src.get_u16_le());
2133 }
2134
2135 let host = String::from_utf16(&chars).map_err(|_| {
2136 ProtocolError::StringEncoding(
2137 #[cfg(feature = "std")]
2138 "invalid UTF-16 in routing hostname".to_string(),
2139 #[cfg(not(feature = "std"))]
2140 "invalid UTF-16 in routing hostname",
2141 )
2142 })?;
2143
2144 Ok(EnvChangeValue::Routing { host, port })
2145 }
2146
2147 #[must_use]
2149 pub fn is_routing(&self) -> bool {
2150 self.env_type == EnvChangeType::Routing
2151 }
2152
2153 #[must_use]
2155 pub fn routing_info(&self) -> Option<(&str, u16)> {
2156 if let EnvChangeValue::Routing { host, port } = &self.new_value {
2157 Some((host, *port))
2158 } else {
2159 None
2160 }
2161 }
2162
2163 #[must_use]
2165 pub fn new_database(&self) -> Option<&str> {
2166 if self.env_type == EnvChangeType::Database {
2167 if let EnvChangeValue::String(s) = &self.new_value {
2168 return Some(s);
2169 }
2170 }
2171 None
2172 }
2173}
2174
2175impl Order {
2176 pub fn decode(src: &mut impl Buf) -> Result<Self, ProtocolError> {
2178 if src.remaining() < 2 {
2179 return Err(ProtocolError::UnexpectedEof);
2180 }
2181
2182 let length = src.get_u16_le() as usize;
2183 let column_count = length / 2;
2184
2185 if src.remaining() < length {
2186 return Err(ProtocolError::IncompletePacket {
2187 expected: length,
2188 actual: src.remaining(),
2189 });
2190 }
2191
2192 let mut columns = Vec::with_capacity(column_count);
2193 for _ in 0..column_count {
2194 columns.push(src.get_u16_le());
2195 }
2196
2197 Ok(Self { columns })
2198 }
2199}
2200
2201impl FeatureExtAck {
2202 pub const TERMINATOR: u8 = 0xFF;
2204
2205 pub fn decode(src: &mut impl Buf) -> Result<Self, ProtocolError> {
2207 let mut features = Vec::new();
2208
2209 loop {
2210 if !src.has_remaining() {
2211 return Err(ProtocolError::UnexpectedEof);
2212 }
2213
2214 let feature_id = src.get_u8();
2215 if feature_id == Self::TERMINATOR {
2216 break;
2217 }
2218
2219 if src.remaining() < 4 {
2220 return Err(ProtocolError::UnexpectedEof);
2221 }
2222
2223 let data_len = src.get_u32_le() as usize;
2224
2225 if src.remaining() < data_len {
2226 return Err(ProtocolError::IncompletePacket {
2227 expected: data_len,
2228 actual: src.remaining(),
2229 });
2230 }
2231
2232 let data = src.copy_to_bytes(data_len);
2233 features.push(FeatureAck { feature_id, data });
2234 }
2235
2236 Ok(Self { features })
2237 }
2238}
2239
2240impl SspiToken {
2241 pub fn decode(src: &mut impl Buf) -> Result<Self, ProtocolError> {
2243 if src.remaining() < 2 {
2244 return Err(ProtocolError::UnexpectedEof);
2245 }
2246
2247 let length = src.get_u16_le() as usize;
2248
2249 if src.remaining() < length {
2250 return Err(ProtocolError::IncompletePacket {
2251 expected: length,
2252 actual: src.remaining(),
2253 });
2254 }
2255
2256 let data = src.copy_to_bytes(length);
2257 Ok(Self { data })
2258 }
2259}
2260
2261impl FedAuthInfo {
2262 const ID_STSURL: u8 = 0x01;
2264 const ID_SPN: u8 = 0x02;
2267 const OPT_HEADER_LEN: usize = 9;
2269
2270 pub fn decode(src: &mut impl Buf) -> Result<Self, ProtocolError> {
2282 if src.remaining() < 4 {
2283 return Err(ProtocolError::UnexpectedEof);
2284 }
2285 let token_len = src.get_u32_le() as usize;
2286 if src.remaining() < token_len {
2287 return Err(ProtocolError::UnexpectedEof);
2288 }
2289
2290 let region = src.copy_to_bytes(token_len);
2293 if region.len() < 4 {
2294 return Err(ProtocolError::UnexpectedEof);
2295 }
2296 let count = u32::from_le_bytes([region[0], region[1], region[2], region[3]]) as usize;
2297
2298 let headers_end = count
2302 .checked_mul(Self::OPT_HEADER_LEN)
2303 .and_then(|n| n.checked_add(4))
2304 .ok_or(ProtocolError::UnexpectedEof)?;
2305 if headers_end > region.len() {
2306 return Err(ProtocolError::UnexpectedEof);
2307 }
2308
2309 let mut sts_url = String::new();
2310 let mut spn = String::new();
2311
2312 for i in 0..count {
2313 let h = 4 + i * Self::OPT_HEADER_LEN;
2314 let info_id = region[h];
2315 let data_len =
2316 u32::from_le_bytes([region[h + 1], region[h + 2], region[h + 3], region[h + 4]])
2317 as usize;
2318 let data_off =
2319 u32::from_le_bytes([region[h + 5], region[h + 6], region[h + 7], region[h + 8]])
2320 as usize;
2321
2322 if info_id != Self::ID_SPN && info_id != Self::ID_STSURL {
2325 continue;
2326 }
2327
2328 let data_end = data_off
2329 .checked_add(data_len)
2330 .ok_or(ProtocolError::UnexpectedEof)?;
2331 if data_end > region.len() {
2332 return Err(ProtocolError::UnexpectedEof);
2333 }
2334 if data_len % 2 != 0 {
2335 return Err(ProtocolError::StringEncoding(
2336 #[cfg(feature = "std")]
2337 "FEDAUTHINFO option data has odd length, not UTF-16".to_string(),
2338 #[cfg(not(feature = "std"))]
2339 "FEDAUTHINFO option data has odd length, not UTF-16",
2340 ));
2341 }
2342
2343 let chars: Vec<u16> = region[data_off..data_end]
2344 .chunks_exact(2)
2345 .map(|b| u16::from_le_bytes([b[0], b[1]]))
2346 .collect();
2347 let value = String::from_utf16(&chars).map_err(|_| {
2348 ProtocolError::StringEncoding(
2349 #[cfg(feature = "std")]
2350 "invalid UTF-16 in FEDAUTHINFO option".to_string(),
2351 #[cfg(not(feature = "std"))]
2352 "invalid UTF-16 in FEDAUTHINFO option",
2353 )
2354 })?;
2355
2356 if info_id == Self::ID_SPN {
2357 spn = value;
2358 } else {
2359 sts_url = value;
2360 }
2361 }
2362
2363 Ok(Self { sts_url, spn })
2364 }
2365}
2366
2367pub struct TokenParser {
2408 data: Bytes,
2409 position: usize,
2410 encryption_enabled: bool,
2413 alt_metadata: Vec<(u16, ColMetaData)>,
2417}
2418
2419impl TokenParser {
2420 #[must_use]
2422 pub fn new(data: Bytes) -> Self {
2423 Self {
2424 data,
2425 position: 0,
2426 encryption_enabled: false,
2427 alt_metadata: Vec::new(),
2428 }
2429 }
2430
2431 #[must_use]
2436 pub fn with_encryption(mut self, enabled: bool) -> Self {
2437 self.encryption_enabled = enabled;
2438 self
2439 }
2440
2441 #[must_use]
2443 pub fn remaining(&self) -> usize {
2444 self.data.len().saturating_sub(self.position)
2445 }
2446
2447 #[must_use]
2449 pub fn has_remaining(&self) -> bool {
2450 self.position < self.data.len()
2451 }
2452
2453 #[must_use]
2455 pub fn peek_token_type(&self) -> Option<TokenType> {
2456 if self.position < self.data.len() {
2457 TokenType::from_u8(self.data[self.position])
2458 } else {
2459 None
2460 }
2461 }
2462
2463 pub fn next_token(&mut self) -> Result<Option<Token>, ProtocolError> {
2471 self.next_token_with_metadata(None)
2472 }
2473
2474 pub fn next_token_with_metadata(
2481 &mut self,
2482 metadata: Option<&ColMetaData>,
2483 ) -> Result<Option<Token>, ProtocolError> {
2484 loop {
2485 if !self.has_remaining() {
2486 return Ok(None);
2487 }
2488
2489 let mut buf = &self.data[self.position..];
2490 let start_pos = self.position;
2491
2492 let token_type_byte = buf.get_u8();
2493 let token_type = TokenType::from_u8(token_type_byte);
2494
2495 let token = match token_type {
2496 Some(TokenType::Done) => {
2497 let done = Done::decode(&mut buf)?;
2498 Token::Done(done)
2499 }
2500 Some(TokenType::DoneProc) => {
2501 let done = DoneProc::decode(&mut buf)?;
2502 Token::DoneProc(done)
2503 }
2504 Some(TokenType::DoneInProc) => {
2505 let done = DoneInProc::decode(&mut buf)?;
2506 Token::DoneInProc(done)
2507 }
2508 Some(TokenType::Error) => {
2509 let error = ServerError::decode(&mut buf)?;
2510 Token::Error(error)
2511 }
2512 Some(TokenType::Info) => {
2513 let info = ServerInfo::decode(&mut buf)?;
2514 Token::Info(info)
2515 }
2516 Some(TokenType::LoginAck) => {
2517 let login_ack = LoginAck::decode(&mut buf)?;
2518 Token::LoginAck(login_ack)
2519 }
2520 Some(TokenType::EnvChange) => {
2521 let env_change = EnvChange::decode(&mut buf)?;
2522 Token::EnvChange(env_change)
2523 }
2524 Some(TokenType::Order) => {
2525 let order = Order::decode(&mut buf)?;
2526 Token::Order(order)
2527 }
2528 Some(TokenType::FeatureExtAck) => {
2529 let ack = FeatureExtAck::decode(&mut buf)?;
2530 Token::FeatureExtAck(ack)
2531 }
2532 Some(TokenType::Sspi) => {
2533 let sspi = SspiToken::decode(&mut buf)?;
2534 Token::Sspi(sspi)
2535 }
2536 Some(TokenType::FedAuthInfo) => {
2537 let info = FedAuthInfo::decode(&mut buf)?;
2538 Token::FedAuthInfo(info)
2539 }
2540 Some(TokenType::ReturnStatus) => {
2541 if buf.remaining() < 4 {
2542 return Err(ProtocolError::UnexpectedEof);
2543 }
2544 let status = buf.get_i32_le();
2545 Token::ReturnStatus(status)
2546 }
2547 Some(TokenType::ColMetaData) => {
2548 let col_meta = if self.encryption_enabled {
2549 ColMetaData::decode_encrypted(&mut buf)?
2550 } else {
2551 ColMetaData::decode(&mut buf)?
2552 };
2553 self.alt_metadata.clear();
2556 Token::ColMetaData(col_meta)
2557 }
2558 Some(TokenType::Row) => {
2559 let meta = metadata.ok_or_else(|| {
2560 ProtocolError::StringEncoding(
2561 #[cfg(feature = "std")]
2562 "Row token requires column metadata".to_string(),
2563 #[cfg(not(feature = "std"))]
2564 "Row token requires column metadata",
2565 )
2566 })?;
2567 let row = RawRow::decode(&mut buf, meta)?;
2568 Token::Row(row)
2569 }
2570 Some(TokenType::NbcRow) => {
2571 let meta = metadata.ok_or_else(|| {
2572 ProtocolError::StringEncoding(
2573 #[cfg(feature = "std")]
2574 "NbcRow token requires column metadata".to_string(),
2575 #[cfg(not(feature = "std"))]
2576 "NbcRow token requires column metadata",
2577 )
2578 })?;
2579 let row = NbcRow::decode(&mut buf, meta)?;
2580 Token::NbcRow(row)
2581 }
2582 Some(TokenType::ReturnValue) => {
2583 let ret_val = ReturnValue::decode(&mut buf)?;
2584 Token::ReturnValue(ret_val)
2585 }
2586 Some(TokenType::SessionState) => {
2587 let session = SessionState::decode(&mut buf)?;
2588 Token::SessionState(session)
2589 }
2590 Some(TokenType::ColInfo) | Some(TokenType::TabName) | Some(TokenType::Offset) => {
2591 if buf.remaining() < 2 {
2594 return Err(ProtocolError::UnexpectedEof);
2595 }
2596 let length = buf.get_u16_le() as usize;
2597 if buf.remaining() < length {
2598 return Err(ProtocolError::IncompletePacket {
2599 expected: length,
2600 actual: buf.remaining(),
2601 });
2602 }
2603 buf.advance(length);
2605 self.position = start_pos + (self.data.len() - start_pos - buf.remaining());
2610 continue;
2611 }
2612 Some(TokenType::AltMetaData) => {
2613 let (id, alt_meta) = ColMetaData::decode_alt(&mut buf)?;
2618 self.position = start_pos + (self.data.len() - start_pos - buf.remaining());
2619 self.alt_metadata.push((id, alt_meta));
2620 continue;
2621 }
2622 Some(TokenType::AltRow) => {
2623 if buf.remaining() < 2 {
2627 return Err(ProtocolError::UnexpectedEof);
2628 }
2629 let id = buf.get_u16_le();
2630 let alt_meta = self
2631 .alt_metadata
2632 .iter()
2633 .find(|(stored_id, _)| *stored_id == id)
2634 .map(|(_, meta)| meta)
2635 .ok_or_else(|| {
2636 ProtocolError::StringEncoding(
2637 #[cfg(feature = "std")]
2638 "ALTROW token without matching ALTMETADATA".to_string(),
2639 #[cfg(not(feature = "std"))]
2640 "ALTROW token without matching ALTMETADATA",
2641 )
2642 })?;
2643 let _ = RawRow::decode(&mut buf, alt_meta)?;
2644 self.position = start_pos + (self.data.len() - start_pos - buf.remaining());
2645 continue;
2646 }
2647 None => {
2648 return Err(ProtocolError::InvalidTokenType(token_type_byte));
2649 }
2650 };
2651
2652 let consumed = self.data.len() - start_pos - buf.remaining();
2654 self.position = start_pos + consumed;
2655
2656 return Ok(Some(token));
2657 }
2658 }
2659
2660 pub fn skip_token(&mut self) -> Result<(), ProtocolError> {
2664 if !self.has_remaining() {
2665 return Ok(());
2666 }
2667
2668 let token_type_byte = self.data[self.position];
2669 let token_type = TokenType::from_u8(token_type_byte);
2670
2671 let skip_amount = match token_type {
2673 Some(TokenType::Done) | Some(TokenType::DoneProc) | Some(TokenType::DoneInProc) => {
2675 1 + Done::SIZE }
2677 Some(TokenType::ReturnStatus) => {
2678 1 + 4 }
2680 Some(TokenType::Error)
2682 | Some(TokenType::Info)
2683 | Some(TokenType::LoginAck)
2684 | Some(TokenType::EnvChange)
2685 | Some(TokenType::Order)
2686 | Some(TokenType::Sspi)
2687 | Some(TokenType::ColInfo)
2688 | Some(TokenType::TabName)
2689 | Some(TokenType::Offset) => {
2690 if self.remaining() < 3 {
2691 return Err(ProtocolError::UnexpectedEof);
2692 }
2693 let length = u16::from_le_bytes([
2694 self.data[self.position + 1],
2695 self.data[self.position + 2],
2696 ]) as usize;
2697 1 + 2 + length }
2699 Some(TokenType::ReturnValue) => {
2704 let mut buf = &self.data[self.position + 1..];
2705 let _ = ReturnValue::decode(&mut buf)?;
2706 self.data.len() - self.position - buf.remaining()
2707 }
2708 Some(TokenType::SessionState) | Some(TokenType::FedAuthInfo) => {
2710 if self.remaining() < 5 {
2711 return Err(ProtocolError::UnexpectedEof);
2712 }
2713 let length = u32::from_le_bytes([
2714 self.data[self.position + 1],
2715 self.data[self.position + 2],
2716 self.data[self.position + 3],
2717 self.data[self.position + 4],
2718 ]) as usize;
2719 1 + 4 + length
2720 }
2721 Some(TokenType::FeatureExtAck) => {
2723 let mut buf = &self.data[self.position + 1..];
2725 let _ = FeatureExtAck::decode(&mut buf)?;
2726 self.data.len() - self.position - buf.remaining()
2727 }
2728 Some(TokenType::AltMetaData) => {
2731 let mut buf = &self.data[self.position + 1..];
2732 let (id, alt_meta) = ColMetaData::decode_alt(&mut buf)?;
2733 let consumed = self.data.len() - self.position - buf.remaining();
2734 self.alt_metadata.push((id, alt_meta));
2735 consumed
2736 }
2737 Some(TokenType::AltRow) => {
2739 let mut buf = &self.data[self.position + 1..];
2740 if buf.remaining() < 2 {
2741 return Err(ProtocolError::UnexpectedEof);
2742 }
2743 let id = buf.get_u16_le();
2744 let alt_meta = self
2745 .alt_metadata
2746 .iter()
2747 .find(|(stored_id, _)| *stored_id == id)
2748 .map(|(_, meta)| meta)
2749 .ok_or(ProtocolError::InvalidTokenType(token_type_byte))?;
2750 let _ = RawRow::decode(&mut buf, alt_meta)?;
2751 self.data.len() - self.position - buf.remaining()
2752 }
2753 Some(TokenType::ColMetaData) | Some(TokenType::Row) | Some(TokenType::NbcRow) => {
2755 return Err(ProtocolError::InvalidTokenType(token_type_byte));
2756 }
2757 None => {
2758 return Err(ProtocolError::InvalidTokenType(token_type_byte));
2759 }
2760 };
2761
2762 if self.remaining() < skip_amount {
2763 return Err(ProtocolError::UnexpectedEof);
2764 }
2765
2766 self.position += skip_amount;
2767 Ok(())
2768 }
2769
2770 #[must_use]
2772 pub fn position(&self) -> usize {
2773 self.position
2774 }
2775
2776 pub fn reset(&mut self) {
2778 self.position = 0;
2779 }
2780}
2781
2782#[cfg(test)]
2787#[allow(clippy::unwrap_used, clippy::panic)]
2788mod tests {
2789 use super::*;
2790 use bytes::BytesMut;
2791
2792 #[test]
2793 fn test_done_roundtrip() {
2794 let done = Done {
2795 status: DoneStatus {
2796 more: false,
2797 error: false,
2798 in_xact: false,
2799 count: true,
2800 attn: false,
2801 srverror: false,
2802 },
2803 cur_cmd: 193, row_count: 42,
2805 };
2806
2807 let mut buf = BytesMut::new();
2808 done.encode(&mut buf);
2809
2810 let mut cursor = &buf[1..];
2812 let decoded = Done::decode(&mut cursor).unwrap();
2813
2814 assert_eq!(decoded.status.count, done.status.count);
2815 assert_eq!(decoded.cur_cmd, done.cur_cmd);
2816 assert_eq!(decoded.row_count, done.row_count);
2817 }
2818
2819 #[test]
2820 fn test_done_status_bits() {
2821 let status = DoneStatus {
2822 more: true,
2823 error: true,
2824 in_xact: true,
2825 count: true,
2826 attn: false,
2827 srverror: false,
2828 };
2829
2830 let bits = status.to_bits();
2831 let restored = DoneStatus::from_bits(bits);
2832
2833 assert_eq!(status.more, restored.more);
2834 assert_eq!(status.error, restored.error);
2835 assert_eq!(status.in_xact, restored.in_xact);
2836 assert_eq!(status.count, restored.count);
2837 }
2838
2839 #[test]
2840 fn test_token_parser_done() {
2841 let data = Bytes::from_static(&[
2843 0xFD, 0x10, 0x00, 0xC1, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ]);
2848
2849 let mut parser = TokenParser::new(data);
2850 let token = parser.next_token().unwrap().unwrap();
2851
2852 match token {
2853 Token::Done(done) => {
2854 assert!(done.status.count);
2855 assert!(!done.status.more);
2856 assert_eq!(done.cur_cmd, 193);
2857 assert_eq!(done.row_count, 5);
2858 }
2859 _ => panic!("Expected Done token"),
2860 }
2861
2862 assert!(parser.next_token().unwrap().is_none());
2864 }
2865
2866 #[test]
2867 fn test_env_change_type_from_u8() {
2868 assert_eq!(EnvChangeType::from_u8(1), Some(EnvChangeType::Database));
2869 assert_eq!(EnvChangeType::from_u8(20), Some(EnvChangeType::Routing));
2870 assert_eq!(EnvChangeType::from_u8(100), None);
2871 }
2872
2873 #[test]
2880 fn test_env_change_routing_consumes_declared_length() {
2881 let host = "redirect.example";
2882 let host_utf16: Vec<u16> = host.encode_utf16().collect();
2883
2884 let mut data = BytesMut::new();
2885 let routing_len = 1 + 2 + 2 + host_utf16.len() * 2;
2887 let env_len = 1 + 2 + routing_len + 2;
2890 data.put_u16_le(env_len as u16);
2891 data.put_u8(20); data.put_u16_le(routing_len as u16);
2893 data.put_u8(0); data.put_u16_le(11000); data.put_u16_le(host_utf16.len() as u16);
2896 for c in &host_utf16 {
2897 data.put_u16_le(*c);
2898 }
2899 data.put_u16_le(0); data.put_u8(0xFD);
2902
2903 let mut buf: &[u8] = &data;
2904 let env = EnvChange::decode(&mut buf).unwrap();
2905 assert_eq!(env.routing_info(), Some((host, 11000)));
2906 assert_eq!(
2907 buf,
2908 &[0xFD],
2909 "decode must consume exactly the declared ENVCHANGE frame"
2910 );
2911 }
2912
2913 fn put_b_varchar(buf: &mut BytesMut, s: &str) {
2914 let utf16: Vec<u16> = s.encode_utf16().collect();
2915 buf.put_u8(utf16.len() as u8);
2916 for c in utf16 {
2917 buf.put_u16_le(c);
2918 }
2919 }
2920
2921 fn put_us_varchar(buf: &mut BytesMut, s: &str) {
2922 let utf16: Vec<u16> = s.encode_utf16().collect();
2923 buf.put_u16_le(utf16.len() as u16);
2924 for c in utf16 {
2925 buf.put_u16_le(c);
2926 }
2927 }
2928
2929 #[test]
2936 fn test_udt_info_metadata_uses_b_varchar_names() {
2937 let mut data = BytesMut::new();
2938 data.put_u16_le(0xFFFF); put_b_varchar(&mut data, "master");
2940 put_b_varchar(&mut data, "dbo");
2941 put_b_varchar(&mut data, "hierarchyid");
2942 put_us_varchar(
2943 &mut data,
2944 "Microsoft.SqlServer.Types.SqlHierarchyId, Microsoft.SqlServer.Types",
2945 );
2946 data.put_u8(0xFD);
2948
2949 let mut buf: &[u8] = &data;
2950 let info = decode_type_info(&mut buf, TypeId::Udt, TypeId::Udt as u8).unwrap();
2951 assert_eq!(info.max_length, Some(0xFFFF));
2952 assert_eq!(
2953 buf,
2954 &[0xFD],
2955 "decode must consume exactly the UDT_INFO frame"
2956 );
2957 }
2958
2959 #[test]
2963 fn test_xml_info_schema_bound_uses_b_varchar_names() {
2964 let mut data = BytesMut::new();
2965 data.put_u8(1); put_b_varchar(&mut data, "master");
2967 put_b_varchar(&mut data, "dbo");
2968 put_us_varchar(&mut data, "MyXmlSchemaCollection");
2969 data.put_u8(0xFD);
2970
2971 let mut buf: &[u8] = &data;
2972 decode_type_info(&mut buf, TypeId::Xml, TypeId::Xml as u8).unwrap();
2973 assert_eq!(
2974 buf,
2975 &[0xFD],
2976 "decode must consume exactly the XML_INFO frame"
2977 );
2978 }
2979
2980 #[test]
2981 fn hostile_env_change_binary_truncated_is_not_panic() {
2982 let data = [0x01, 0x00, 0x08];
2987 let mut buf: &[u8] = &data;
2988 let env = EnvChange::decode(&mut buf).unwrap();
2989 assert_eq!(env.env_type, EnvChangeType::BeginTransaction);
2990 }
2991
2992 #[test]
2995 fn hostile_env_change_under_declared_cannot_steal_following_bytes() {
2996 let mut data = BytesMut::new();
3001 data.put_u16_le(1); data.put_u8(0x08); let following: &[u8] = &[0x08, 1, 2, 3, 4, 5, 6, 7, 8, 0x00];
3004 data.extend_from_slice(following);
3005
3006 let mut buf: &[u8] = &data;
3007 let env = EnvChange::decode(&mut buf).unwrap();
3008 assert_eq!(env.env_type, EnvChangeType::BeginTransaction);
3009 match &env.new_value {
3010 EnvChangeValue::Binary(b) => {
3011 assert!(
3012 b.is_empty(),
3013 "under-declared frame yields the lenient empty value"
3014 );
3015 }
3016 other => panic!("expected empty Binary value, got {other:?}"),
3017 }
3018 assert_eq!(
3019 buf, following,
3020 "bytes beyond the declared frame belong to the next token"
3021 );
3022 }
3023
3024 #[test]
3027 fn hostile_env_change_zero_length_frame_errors() {
3028 let data = [0x00, 0x00, 0xFD];
3029 let mut buf: &[u8] = &data;
3030 assert!(EnvChange::decode(&mut buf).is_err());
3031 }
3032
3033 #[test]
3034 fn test_colmetadata_no_columns() {
3035 let data = Bytes::from_static(&[0xFF, 0xFF]);
3037 let mut cursor: &[u8] = &data;
3038 let meta = ColMetaData::decode(&mut cursor).unwrap();
3039 assert!(meta.is_empty());
3040 assert_eq!(meta.column_count(), 0);
3041 }
3042
3043 #[test]
3044 fn test_colmetadata_single_int_column() {
3045 let mut data = BytesMut::new();
3048 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;
3057 let meta = ColMetaData::decode(&mut cursor).unwrap();
3058
3059 assert_eq!(meta.column_count(), 1);
3060 assert_eq!(meta.columns[0].name, "id");
3061 assert_eq!(meta.columns[0].type_id, TypeId::Int4);
3062 assert!(meta.columns[0].is_nullable());
3063 }
3064
3065 #[test]
3066 fn test_colmetadata_nvarchar_column() {
3067 let mut data = BytesMut::new();
3069 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]);
3079
3080 let mut cursor: &[u8] = &data;
3081 let meta = ColMetaData::decode(&mut cursor).unwrap();
3082
3083 assert_eq!(meta.column_count(), 1);
3084 assert_eq!(meta.columns[0].name, "name");
3085 assert_eq!(meta.columns[0].type_id, TypeId::NVarChar);
3086 assert_eq!(meta.columns[0].type_info.max_length, Some(100));
3087 assert!(meta.columns[0].type_info.collation.is_some());
3088 }
3089
3090 #[test]
3091 fn test_raw_row_decode_int() {
3092 let metadata = ColMetaData {
3094 cek_table: None,
3095 columns: vec![ColumnData {
3096 name: "id".to_string(),
3097 type_id: TypeId::Int4,
3098 col_type: 0x38,
3099 flags: 0,
3100 user_type: 0,
3101 type_info: TypeInfo::default(),
3102 crypto_metadata: None,
3103 }],
3104 };
3105
3106 let data = Bytes::from_static(&[0x2A, 0x00, 0x00, 0x00]); let mut cursor: &[u8] = &data;
3109 let row = RawRow::decode(&mut cursor, &metadata).unwrap();
3110
3111 assert_eq!(row.data.len(), 4);
3113 assert_eq!(&row.data[..], &[0x2A, 0x00, 0x00, 0x00]);
3114 }
3115
3116 #[test]
3117 fn test_raw_row_decode_nullable_int() {
3118 let metadata = ColMetaData {
3120 cek_table: None,
3121 columns: vec![ColumnData {
3122 name: "id".to_string(),
3123 type_id: TypeId::IntN,
3124 col_type: 0x26,
3125 flags: 0x01, user_type: 0,
3127 type_info: TypeInfo {
3128 max_length: Some(4),
3129 ..Default::default()
3130 },
3131 crypto_metadata: None,
3132 }],
3133 };
3134
3135 let data = Bytes::from_static(&[0x04, 0x2A, 0x00, 0x00, 0x00]); let mut cursor: &[u8] = &data;
3138 let row = RawRow::decode(&mut cursor, &metadata).unwrap();
3139
3140 assert_eq!(row.data.len(), 5);
3141 assert_eq!(row.data[0], 4); assert_eq!(&row.data[1..], &[0x2A, 0x00, 0x00, 0x00]);
3143 }
3144
3145 #[test]
3146 fn test_raw_row_decode_null_value() {
3147 let metadata = ColMetaData {
3149 cek_table: None,
3150 columns: vec![ColumnData {
3151 name: "id".to_string(),
3152 type_id: TypeId::IntN,
3153 col_type: 0x26,
3154 flags: 0x01, user_type: 0,
3156 type_info: TypeInfo {
3157 max_length: Some(4),
3158 ..Default::default()
3159 },
3160 crypto_metadata: None,
3161 }],
3162 };
3163
3164 let data = Bytes::from_static(&[0xFF]);
3166 let mut cursor: &[u8] = &data;
3167 let row = RawRow::decode(&mut cursor, &metadata).unwrap();
3168
3169 assert_eq!(row.data.len(), 1);
3170 assert_eq!(row.data[0], 0xFF); }
3172
3173 #[test]
3174 fn test_nbcrow_null_bitmap() {
3175 let row = NbcRow {
3176 null_bitmap: vec![0b00000101], data: Bytes::new(),
3178 };
3179
3180 assert!(row.is_null(0));
3181 assert!(!row.is_null(1));
3182 assert!(row.is_null(2));
3183 assert!(!row.is_null(3));
3184 }
3185
3186 #[test]
3187 fn test_token_parser_colmetadata() {
3188 let mut data = BytesMut::new();
3190 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());
3199 let token = parser.next_token().unwrap().unwrap();
3200
3201 match token {
3202 Token::ColMetaData(meta) => {
3203 assert_eq!(meta.column_count(), 1);
3204 assert_eq!(meta.columns[0].name, "id");
3205 assert_eq!(meta.columns[0].type_id, TypeId::Int4);
3206 }
3207 _ => panic!("Expected ColMetaData token"),
3208 }
3209 }
3210
3211 #[test]
3212 fn test_token_parser_row_with_metadata() {
3213 let metadata = ColMetaData {
3215 cek_table: None,
3216 columns: vec![ColumnData {
3217 name: "id".to_string(),
3218 type_id: TypeId::Int4,
3219 col_type: 0x38,
3220 flags: 0,
3221 user_type: 0,
3222 type_info: TypeInfo::default(),
3223 crypto_metadata: None,
3224 }],
3225 };
3226
3227 let mut data = BytesMut::new();
3229 data.extend_from_slice(&[0xD1]); data.extend_from_slice(&[0x2A, 0x00, 0x00, 0x00]); let mut parser = TokenParser::new(data.freeze());
3233 let token = parser
3234 .next_token_with_metadata(Some(&metadata))
3235 .unwrap()
3236 .unwrap();
3237
3238 match token {
3239 Token::Row(row) => {
3240 assert_eq!(row.data.len(), 4);
3241 }
3242 _ => panic!("Expected Row token"),
3243 }
3244 }
3245
3246 #[test]
3247 fn test_token_parser_row_without_metadata_fails() {
3248 let mut data = BytesMut::new();
3250 data.extend_from_slice(&[0xD1]); data.extend_from_slice(&[0x2A, 0x00, 0x00, 0x00]); let mut parser = TokenParser::new(data.freeze());
3254 let result = parser.next_token(); assert!(result.is_err());
3257 }
3258
3259 #[test]
3260 fn test_token_parser_peek() {
3261 let data = Bytes::from_static(&[
3262 0xFD, 0x10, 0x00, 0xC1, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ]);
3267
3268 let parser = TokenParser::new(data);
3269 assert_eq!(parser.peek_token_type(), Some(TokenType::Done));
3270 }
3271
3272 #[test]
3273 fn test_column_data_fixed_size() {
3274 let col = ColumnData {
3275 name: String::new(),
3276 type_id: TypeId::Int4,
3277 col_type: 0x38,
3278 flags: 0,
3279 user_type: 0,
3280 type_info: TypeInfo::default(),
3281 crypto_metadata: None,
3282 };
3283 assert_eq!(col.fixed_size(), Some(4));
3284
3285 let col2 = ColumnData {
3286 name: String::new(),
3287 type_id: TypeId::NVarChar,
3288 col_type: 0xE7,
3289 flags: 0,
3290 user_type: 0,
3291 type_info: TypeInfo::default(),
3292 crypto_metadata: None,
3293 };
3294 assert_eq!(col2.fixed_size(), None);
3295 }
3296
3297 #[test]
3305 fn test_decode_nvarchar_then_intn_roundtrip() {
3306 let mut wire_data = BytesMut::new();
3311
3312 let word = "World";
3315 let utf16: Vec<u16> = word.encode_utf16().collect();
3316 wire_data.put_u16_le((utf16.len() * 2) as u16); for code_unit in &utf16 {
3318 wire_data.put_u16_le(*code_unit);
3319 }
3320
3321 wire_data.put_u8(4); wire_data.put_i32_le(42);
3324
3325 let metadata = ColMetaData {
3327 cek_table: None,
3328 columns: vec![
3329 ColumnData {
3330 name: "greeting".to_string(),
3331 type_id: TypeId::NVarChar,
3332 col_type: 0xE7,
3333 flags: 0x01,
3334 user_type: 0,
3335 type_info: TypeInfo {
3336 max_length: Some(10), precision: None,
3338 scale: None,
3339 collation: None,
3340 },
3341 crypto_metadata: None,
3342 },
3343 ColumnData {
3344 name: "number".to_string(),
3345 type_id: TypeId::IntN,
3346 col_type: 0x26,
3347 flags: 0x01,
3348 user_type: 0,
3349 type_info: TypeInfo {
3350 max_length: Some(4),
3351 precision: None,
3352 scale: None,
3353 collation: None,
3354 },
3355 crypto_metadata: None,
3356 },
3357 ],
3358 };
3359
3360 let mut wire_cursor = wire_data.freeze();
3362 let raw_row = RawRow::decode(&mut wire_cursor, &metadata).unwrap();
3363
3364 assert_eq!(
3366 wire_cursor.remaining(),
3367 0,
3368 "wire data should be fully consumed"
3369 );
3370
3371 let mut stored_cursor: &[u8] = &raw_row.data;
3373
3374 assert!(
3377 stored_cursor.remaining() >= 2,
3378 "need at least 2 bytes for length"
3379 );
3380 let len0 = stored_cursor.get_u16_le() as usize;
3381 assert_eq!(len0, 10, "NVarChar length should be 10 bytes");
3382 assert!(
3383 stored_cursor.remaining() >= len0,
3384 "need {len0} bytes for data"
3385 );
3386
3387 let mut utf16_read = Vec::new();
3389 for _ in 0..(len0 / 2) {
3390 utf16_read.push(stored_cursor.get_u16_le());
3391 }
3392 let string0 = String::from_utf16(&utf16_read).unwrap();
3393 assert_eq!(string0, "World", "column 0 should be 'World'");
3394
3395 assert!(
3398 stored_cursor.remaining() >= 1,
3399 "need at least 1 byte for length"
3400 );
3401 let len1 = stored_cursor.get_u8();
3402 assert_eq!(len1, 4, "IntN length should be 4");
3403 assert!(stored_cursor.remaining() >= 4, "need 4 bytes for INT data");
3404 let int1 = stored_cursor.get_i32_le();
3405 assert_eq!(int1, 42, "column 1 should be 42");
3406
3407 assert_eq!(
3409 stored_cursor.remaining(),
3410 0,
3411 "stored data should be fully consumed"
3412 );
3413 }
3414
3415 #[test]
3416 fn test_decode_nvarchar_max_then_intn_roundtrip() {
3417 let mut wire_data = BytesMut::new();
3421
3422 let word = "Hello";
3425 let utf16: Vec<u16> = word.encode_utf16().collect();
3426 let byte_len = (utf16.len() * 2) as u64;
3427
3428 wire_data.put_u64_le(byte_len); wire_data.put_u32_le(byte_len as u32); for code_unit in &utf16 {
3431 wire_data.put_u16_le(*code_unit);
3432 }
3433 wire_data.put_u32_le(0); wire_data.put_u8(4);
3437 wire_data.put_i32_le(99);
3438
3439 let metadata = ColMetaData {
3441 cek_table: None,
3442 columns: vec![
3443 ColumnData {
3444 name: "text".to_string(),
3445 type_id: TypeId::NVarChar,
3446 col_type: 0xE7,
3447 flags: 0x01,
3448 user_type: 0,
3449 type_info: TypeInfo {
3450 max_length: Some(0xFFFF), precision: None,
3452 scale: None,
3453 collation: None,
3454 },
3455 crypto_metadata: None,
3456 },
3457 ColumnData {
3458 name: "num".to_string(),
3459 type_id: TypeId::IntN,
3460 col_type: 0x26,
3461 flags: 0x01,
3462 user_type: 0,
3463 type_info: TypeInfo {
3464 max_length: Some(4),
3465 precision: None,
3466 scale: None,
3467 collation: None,
3468 },
3469 crypto_metadata: None,
3470 },
3471 ],
3472 };
3473
3474 let mut wire_cursor = wire_data.freeze();
3476 let raw_row = RawRow::decode(&mut wire_cursor, &metadata).unwrap();
3477
3478 assert_eq!(
3480 wire_cursor.remaining(),
3481 0,
3482 "wire data should be fully consumed"
3483 );
3484
3485 let mut stored_cursor: &[u8] = &raw_row.data;
3487
3488 let total_len = stored_cursor.get_u64_le();
3490 assert_eq!(total_len, 10, "PLP total length should be 10");
3491
3492 let chunk_len = stored_cursor.get_u32_le();
3493 assert_eq!(chunk_len, 10, "PLP chunk length should be 10");
3494
3495 let mut utf16_read = Vec::new();
3496 for _ in 0..(chunk_len / 2) {
3497 utf16_read.push(stored_cursor.get_u16_le());
3498 }
3499 let string0 = String::from_utf16(&utf16_read).unwrap();
3500 assert_eq!(string0, "Hello", "column 0 should be 'Hello'");
3501
3502 let terminator = stored_cursor.get_u32_le();
3503 assert_eq!(terminator, 0, "PLP should end with 0");
3504
3505 let len1 = stored_cursor.get_u8();
3507 assert_eq!(len1, 4);
3508 let int1 = stored_cursor.get_i32_le();
3509 assert_eq!(int1, 99, "column 1 should be 99");
3510
3511 assert_eq!(
3513 stored_cursor.remaining(),
3514 0,
3515 "stored data should be fully consumed"
3516 );
3517 }
3518
3519 #[test]
3524 fn test_return_status_via_parser() {
3525 let data = Bytes::from_static(&[
3527 0x79, 0x00, 0x00, 0x00, 0x00, ]);
3530
3531 let mut parser = TokenParser::new(data);
3532 let token = parser.next_token().unwrap().unwrap();
3533
3534 match token {
3535 Token::ReturnStatus(status) => {
3536 assert_eq!(status, 0);
3537 }
3538 _ => panic!("Expected ReturnStatus token, got {token:?}"),
3539 }
3540
3541 assert!(parser.next_token().unwrap().is_none());
3542 }
3543
3544 #[test]
3545 fn test_return_status_nonzero() {
3546 let mut buf = BytesMut::new();
3548 buf.put_u8(0x79); buf.put_i32_le(-6);
3550
3551 let mut parser = TokenParser::new(buf.freeze());
3552 let token = parser.next_token().unwrap().unwrap();
3553
3554 match token {
3555 Token::ReturnStatus(status) => {
3556 assert_eq!(status, -6);
3557 }
3558 _ => panic!("Expected ReturnStatus token"),
3559 }
3560 }
3561
3562 #[test]
3567 fn test_done_proc_roundtrip() {
3568 let done = DoneProc {
3569 status: DoneStatus {
3570 more: false,
3571 error: false,
3572 in_xact: false,
3573 count: true,
3574 attn: false,
3575 srverror: false,
3576 },
3577 cur_cmd: 0x00C6, row_count: 100,
3579 };
3580
3581 let mut buf = BytesMut::new();
3582 done.encode(&mut buf);
3583
3584 assert_eq!(buf[0], 0xFE);
3586
3587 let mut cursor = &buf[1..];
3589 let decoded = DoneProc::decode(&mut cursor).unwrap();
3590
3591 assert!(decoded.status.count);
3592 assert!(!decoded.status.more);
3593 assert!(!decoded.status.error);
3594 assert_eq!(decoded.cur_cmd, 0x00C6);
3595 assert_eq!(decoded.row_count, 100);
3596 }
3597
3598 #[test]
3599 fn test_done_proc_via_parser() {
3600 let data = Bytes::from_static(&[
3601 0xFE, 0x00, 0x00, 0xC6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ]);
3606
3607 let mut parser = TokenParser::new(data);
3608 let token = parser.next_token().unwrap().unwrap();
3609
3610 match token {
3611 Token::DoneProc(done) => {
3612 assert!(!done.status.count);
3613 assert!(!done.status.more);
3614 assert_eq!(done.cur_cmd, 198);
3615 assert_eq!(done.row_count, 0);
3616 }
3617 _ => panic!("Expected DoneProc token"),
3618 }
3619 }
3620
3621 #[test]
3622 fn test_done_proc_with_error_flag() {
3623 let mut buf = BytesMut::new();
3624 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());
3630 let token = parser.next_token().unwrap().unwrap();
3631
3632 match token {
3633 Token::DoneProc(done) => {
3634 assert!(done.status.error);
3635 assert!(!done.status.count);
3636 assert!(!done.status.more);
3637 }
3638 _ => panic!("Expected DoneProc token"),
3639 }
3640 }
3641
3642 #[test]
3647 fn test_done_in_proc_roundtrip() {
3648 let done = DoneInProc {
3649 status: DoneStatus {
3650 more: true,
3651 error: false,
3652 in_xact: false,
3653 count: true,
3654 attn: false,
3655 srverror: false,
3656 },
3657 cur_cmd: 193, row_count: 7,
3659 };
3660
3661 let mut buf = BytesMut::new();
3662 done.encode(&mut buf);
3663
3664 assert_eq!(buf[0], 0xFF);
3665
3666 let mut cursor = &buf[1..];
3667 let decoded = DoneInProc::decode(&mut cursor).unwrap();
3668
3669 assert!(decoded.status.more);
3670 assert!(decoded.status.count);
3671 assert!(!decoded.status.error);
3672 assert_eq!(decoded.cur_cmd, 193);
3673 assert_eq!(decoded.row_count, 7);
3674 }
3675
3676 #[test]
3677 fn test_done_in_proc_via_parser() {
3678 let data = Bytes::from_static(&[
3679 0xFF, 0x11, 0x00, 0xC1, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ]);
3684
3685 let mut parser = TokenParser::new(data);
3686 let token = parser.next_token().unwrap().unwrap();
3687
3688 match token {
3689 Token::DoneInProc(done) => {
3690 assert!(done.status.more);
3691 assert!(done.status.count);
3692 assert_eq!(done.cur_cmd, 193);
3693 assert_eq!(done.row_count, 3);
3694 }
3695 _ => panic!("Expected DoneInProc token"),
3696 }
3697 }
3698
3699 #[test]
3704 fn test_server_error_decode() {
3705 let mut buf = BytesMut::new();
3708
3709 let msg_utf16: Vec<u16> = "Invalid column name 'foo'.".encode_utf16().collect();
3711 let srv_utf16: Vec<u16> = "SQLDB01".encode_utf16().collect();
3712 let proc_utf16: Vec<u16> = "".encode_utf16().collect();
3713
3714 let length: u16 = (4
3720 + 1
3721 + 1
3722 + 2
3723 + (msg_utf16.len() * 2)
3724 + 1
3725 + (srv_utf16.len() * 2)
3726 + 1
3727 + (proc_utf16.len() * 2)
3728 + 4) as u16;
3729
3730 buf.put_u16_le(length);
3731 buf.put_i32_le(207); buf.put_u8(1); buf.put_u8(16); buf.put_u16_le(msg_utf16.len() as u16);
3737 for &c in &msg_utf16 {
3738 buf.put_u16_le(c);
3739 }
3740
3741 buf.put_u8(srv_utf16.len() as u8);
3743 for &c in &srv_utf16 {
3744 buf.put_u16_le(c);
3745 }
3746
3747 buf.put_u8(proc_utf16.len() as u8);
3749
3750 buf.put_i32_le(42);
3752
3753 let mut cursor = buf.freeze();
3754 let error = ServerError::decode(&mut cursor).unwrap();
3755
3756 assert_eq!(error.number, 207);
3757 assert_eq!(error.state, 1);
3758 assert_eq!(error.class, 16);
3759 assert_eq!(error.message, "Invalid column name 'foo'.");
3760 assert_eq!(error.server, "SQLDB01");
3761 assert_eq!(error.procedure, "");
3762 assert_eq!(error.line, 42);
3763 }
3764
3765 #[test]
3766 fn test_server_error_severity_helpers() {
3767 let fatal = ServerError {
3768 number: 4014,
3769 state: 1,
3770 class: 20,
3771 message: "Fatal error".to_string(),
3772 server: String::new(),
3773 procedure: String::new(),
3774 line: 0,
3775 };
3776 assert!(fatal.is_fatal());
3777 assert!(fatal.is_batch_abort());
3778
3779 let batch_abort = ServerError {
3780 number: 547,
3781 state: 0,
3782 class: 16,
3783 message: "Constraint violation".to_string(),
3784 server: String::new(),
3785 procedure: String::new(),
3786 line: 1,
3787 };
3788 assert!(!batch_abort.is_fatal());
3789 assert!(batch_abort.is_batch_abort());
3790
3791 let informational = ServerError {
3792 number: 5701,
3793 state: 2,
3794 class: 10,
3795 message: "Changed db context".to_string(),
3796 server: String::new(),
3797 procedure: String::new(),
3798 line: 0,
3799 };
3800 assert!(!informational.is_fatal());
3801 assert!(!informational.is_batch_abort());
3802 }
3803
3804 #[test]
3805 fn test_server_error_via_parser() {
3806 let mut buf = BytesMut::new();
3808 buf.put_u8(0xAA); let msg_utf16: Vec<u16> = "Syntax error".encode_utf16().collect();
3811 let srv_utf16: Vec<u16> = "SRV".encode_utf16().collect();
3812 let proc_utf16: Vec<u16> = "sp_test".encode_utf16().collect();
3813
3814 let length: u16 = (4
3815 + 1
3816 + 1
3817 + 2
3818 + (msg_utf16.len() * 2)
3819 + 1
3820 + (srv_utf16.len() * 2)
3821 + 1
3822 + (proc_utf16.len() * 2)
3823 + 4) as u16;
3824
3825 buf.put_u16_le(length);
3826 buf.put_i32_le(102); buf.put_u8(1);
3828 buf.put_u8(15);
3829
3830 buf.put_u16_le(msg_utf16.len() as u16);
3831 for &c in &msg_utf16 {
3832 buf.put_u16_le(c);
3833 }
3834 buf.put_u8(srv_utf16.len() as u8);
3835 for &c in &srv_utf16 {
3836 buf.put_u16_le(c);
3837 }
3838 buf.put_u8(proc_utf16.len() as u8);
3839 for &c in &proc_utf16 {
3840 buf.put_u16_le(c);
3841 }
3842 buf.put_i32_le(5);
3843
3844 let mut parser = TokenParser::new(buf.freeze());
3845 let token = parser.next_token().unwrap().unwrap();
3846
3847 match token {
3848 Token::Error(err) => {
3849 assert_eq!(err.number, 102);
3850 assert_eq!(err.class, 15);
3851 assert_eq!(err.message, "Syntax error");
3852 assert_eq!(err.server, "SRV");
3853 assert_eq!(err.procedure, "sp_test");
3854 assert_eq!(err.line, 5);
3855 }
3856 _ => panic!("Expected Error token"),
3857 }
3858 }
3859
3860 fn build_return_value_intn(
3867 ordinal: u16,
3868 name: &str,
3869 status: u8,
3870 value: Option<i32>,
3871 ) -> BytesMut {
3872 let mut inner = BytesMut::new();
3873
3874 inner.put_u16_le(ordinal);
3876
3877 let name_utf16: Vec<u16> = name.encode_utf16().collect();
3879 inner.put_u8(name_utf16.len() as u8);
3880 for &c in &name_utf16 {
3881 inner.put_u16_le(c);
3882 }
3883
3884 inner.put_u8(status);
3886
3887 inner.put_u32_le(0);
3889
3890 inner.put_u16_le(0x0001); inner.put_u8(0x26);
3895
3896 inner.put_u8(4);
3898
3899 match value {
3901 Some(v) => {
3902 inner.put_u8(4); inner.put_i32_le(v);
3904 }
3905 None => {
3906 inner.put_u8(0); }
3908 }
3909
3910 inner
3913 }
3914
3915 #[test]
3916 fn test_return_value_int_output() {
3917 let buf = build_return_value_intn(1, "@result", 0x01, Some(42));
3918 let mut cursor = buf.freeze();
3919 let rv = ReturnValue::decode(&mut cursor).unwrap();
3920
3921 assert_eq!(rv.param_ordinal, 1);
3922 assert_eq!(rv.param_name, "@result");
3923 assert_eq!(rv.status, 0x01); assert_eq!(rv.col_type, 0x26); assert_eq!(rv.type_info.max_length, Some(4));
3926 assert_eq!(rv.value.len(), 5);
3928 assert_eq!(rv.value[0], 4);
3929 assert_eq!(
3930 i32::from_le_bytes([rv.value[1], rv.value[2], rv.value[3], rv.value[4]]),
3931 42
3932 );
3933 }
3934
3935 #[test]
3936 fn test_return_value_null_output() {
3937 let buf = build_return_value_intn(2, "@count", 0x01, None);
3938 let mut cursor = buf.freeze();
3939 let rv = ReturnValue::decode(&mut cursor).unwrap();
3940
3941 assert_eq!(rv.param_ordinal, 2);
3942 assert_eq!(rv.param_name, "@count");
3943 assert_eq!(rv.status, 0x01);
3944 assert_eq!(rv.col_type, 0x26);
3945 assert_eq!(rv.value.len(), 1);
3947 assert_eq!(rv.value[0], 0);
3948 }
3949
3950 #[test]
3951 fn test_return_value_udf_status() {
3952 let buf = build_return_value_intn(0, "@RETURN_VALUE", 0x02, Some(-1));
3954 let mut cursor = buf.freeze();
3955 let rv = ReturnValue::decode(&mut cursor).unwrap();
3956
3957 assert_eq!(rv.param_ordinal, 0);
3958 assert_eq!(rv.param_name, "@RETURN_VALUE");
3959 assert_eq!(rv.status, 0x02); assert_eq!(rv.value[0], 4);
3961 assert_eq!(
3962 i32::from_le_bytes([rv.value[1], rv.value[2], rv.value[3], rv.value[4]]),
3963 -1
3964 );
3965 }
3966
3967 #[test]
3968 fn test_return_value_nvarchar_output() {
3969 let mut inner = BytesMut::new();
3971
3972 inner.put_u16_le(1);
3974
3975 let name_utf16: Vec<u16> = "@name".encode_utf16().collect();
3977 inner.put_u8(name_utf16.len() as u8);
3978 for &c in &name_utf16 {
3979 inner.put_u16_le(c);
3980 }
3981
3982 inner.put_u8(0x01);
3984 inner.put_u32_le(0);
3986 inner.put_u16_le(0x0001);
3988 inner.put_u8(0xE7);
3990 inner.put_u16_le(200); inner.put_u32_le(0x0904D000); inner.put_u8(0x34); let val_utf16: Vec<u16> = "Hello".encode_utf16().collect();
3997 let byte_len = (val_utf16.len() * 2) as u16;
3998 inner.put_u16_le(byte_len);
3999 for &c in &val_utf16 {
4000 inner.put_u16_le(c);
4001 }
4002
4003 let mut cursor = inner.freeze();
4004 let rv = ReturnValue::decode(&mut cursor).unwrap();
4005
4006 assert_eq!(rv.param_ordinal, 1);
4007 assert_eq!(rv.param_name, "@name");
4008 assert_eq!(rv.status, 0x01);
4009 assert_eq!(rv.col_type, 0xE7); assert_eq!(rv.type_info.max_length, Some(200));
4011 assert!(rv.type_info.collation.is_some());
4012
4013 assert_eq!(rv.value.len(), 12); let val_len = u16::from_le_bytes([rv.value[0], rv.value[1]]);
4016 assert_eq!(val_len, 10);
4017 }
4018
4019 #[test]
4020 fn test_return_value_via_parser() {
4021 let mut data = BytesMut::new();
4023 data.put_u8(0xAC); data.extend_from_slice(&build_return_value_intn(0, "@out", 0x01, Some(99)));
4025
4026 let mut parser = TokenParser::new(data.freeze());
4027 let token = parser.next_token().unwrap().unwrap();
4028
4029 match token {
4030 Token::ReturnValue(rv) => {
4031 assert_eq!(rv.param_name, "@out");
4032 assert_eq!(rv.param_ordinal, 0);
4033 assert_eq!(rv.status, 0x01);
4034 assert_eq!(rv.col_type, 0x26);
4035 }
4036 _ => panic!("Expected ReturnValue token"),
4037 }
4038 }
4039
4040 #[test]
4045 fn test_multi_token_stored_proc_response() {
4046 let mut data = BytesMut::new();
4049
4050 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);
4059
4060 data.put_u8(0xFE); data.put_u16_le(0x0000); data.put_u16_le(0x00C6); data.put_u64_le(0);
4065
4066 let mut parser = TokenParser::new(data.freeze());
4067
4068 let t1 = parser.next_token().unwrap().unwrap();
4070 match t1 {
4071 Token::DoneInProc(done) => {
4072 assert!(done.status.count);
4073 assert_eq!(done.row_count, 3);
4074 assert_eq!(done.cur_cmd, 193);
4075 }
4076 _ => panic!("Expected DoneInProc, got {t1:?}"),
4077 }
4078
4079 let t2 = parser.next_token().unwrap().unwrap();
4081 match t2 {
4082 Token::ReturnStatus(status) => {
4083 assert_eq!(status, 0);
4084 }
4085 _ => panic!("Expected ReturnStatus, got {t2:?}"),
4086 }
4087
4088 let t3 = parser.next_token().unwrap().unwrap();
4090 match t3 {
4091 Token::DoneProc(done) => {
4092 assert!(!done.status.count);
4093 assert!(!done.status.more);
4094 assert_eq!(done.cur_cmd, 198);
4095 }
4096 _ => panic!("Expected DoneProc, got {t3:?}"),
4097 }
4098
4099 assert!(parser.next_token().unwrap().is_none());
4101 }
4102
4103 #[test]
4104 fn test_multi_token_error_in_stream() {
4105 let mut data = BytesMut::new();
4107
4108 data.put_u8(0xAA);
4110
4111 let msg_utf16: Vec<u16> = "Deadlock".encode_utf16().collect();
4112 let srv_utf16: Vec<u16> = "DB1".encode_utf16().collect();
4113
4114 let length: u16 = (4 + 1 + 1
4115 + 2 + (msg_utf16.len() * 2)
4116 + 1 + (srv_utf16.len() * 2)
4117 + 1 + 4) as u16;
4119
4120 data.put_u16_le(length);
4121 data.put_i32_le(1205); data.put_u8(51); data.put_u8(13); data.put_u16_le(msg_utf16.len() as u16);
4126 for &c in &msg_utf16 {
4127 data.put_u16_le(c);
4128 }
4129 data.put_u8(srv_utf16.len() as u8);
4130 for &c in &srv_utf16 {
4131 data.put_u16_le(c);
4132 }
4133 data.put_u8(0); data.put_i32_le(0);
4135
4136 data.put_u8(0xFD);
4138 data.put_u16_le(0x0002); data.put_u16_le(0x00C1); data.put_u64_le(0);
4141
4142 let mut parser = TokenParser::new(data.freeze());
4143
4144 let t1 = parser.next_token().unwrap().unwrap();
4146 match t1 {
4147 Token::Error(err) => {
4148 assert_eq!(err.number, 1205);
4149 assert_eq!(err.class, 13);
4150 assert_eq!(err.message, "Deadlock");
4151 assert_eq!(err.server, "DB1");
4152 }
4153 _ => panic!("Expected Error token, got {t1:?}"),
4154 }
4155
4156 let t2 = parser.next_token().unwrap().unwrap();
4158 match t2 {
4159 Token::Done(done) => {
4160 assert!(done.status.error);
4161 assert!(!done.status.count);
4162 }
4163 _ => panic!("Expected Done token, got {t2:?}"),
4164 }
4165
4166 assert!(parser.next_token().unwrap().is_none());
4167 }
4168
4169 #[test]
4170 fn test_multi_token_proc_with_return_value() {
4171 let mut data = BytesMut::new();
4173
4174 data.put_u8(0xAC);
4176 data.extend_from_slice(&build_return_value_intn(1, "@result", 0x01, Some(42)));
4177
4178 data.put_u8(0x79);
4180 data.put_i32_le(0);
4181
4182 data.put_u8(0xFE);
4184 data.put_u16_le(0x0000);
4185 data.put_u16_le(0x00C6);
4186 data.put_u64_le(0);
4187
4188 let mut parser = TokenParser::new(data.freeze());
4189
4190 let t1 = parser.next_token().unwrap().unwrap();
4191 match t1 {
4192 Token::ReturnValue(rv) => {
4193 assert_eq!(rv.param_name, "@result");
4194 assert_eq!(rv.param_ordinal, 1);
4195 }
4196 _ => panic!("Expected ReturnValue, got {t1:?}"),
4197 }
4198
4199 let t2 = parser.next_token().unwrap().unwrap();
4200 assert!(matches!(t2, Token::ReturnStatus(0)));
4201
4202 let t3 = parser.next_token().unwrap().unwrap();
4203 assert!(matches!(t3, Token::DoneProc(_)));
4204
4205 assert!(parser.next_token().unwrap().is_none());
4206 }
4207
4208 #[test]
4213 fn test_return_status_truncated() {
4214 let data = Bytes::from_static(&[0x79, 0x01, 0x02, 0x03]);
4216 let mut parser = TokenParser::new(data);
4217 assert!(parser.next_token().is_err());
4218 }
4219
4220 #[test]
4221 fn test_done_proc_truncated() {
4222 let data = Bytes::from_static(&[0xFE, 0x00, 0x00, 0xC1, 0x00, 0x01, 0x00, 0x00, 0x00]);
4224 let mut parser = TokenParser::new(data);
4225 assert!(parser.next_token().is_err());
4226 }
4227
4228 #[test]
4229 fn test_server_error_truncated() {
4230 let data = Bytes::from_static(&[0xAA, 0x20, 0x00]);
4232 let mut parser = TokenParser::new(data);
4233 assert!(parser.next_token().is_err());
4234 }
4235
4236 fn build_fed_auth_info_token(options: &[(u8, &str)]) -> Vec<u8> {
4245 let headers_end = 4 + options.len() * 9;
4246 let mut data_block = Vec::new();
4247 let mut headers = Vec::new();
4248 for (id, value) in options {
4249 let encoded: Vec<u8> = value.encode_utf16().flat_map(u16::to_le_bytes).collect();
4250 let offset = headers_end + data_block.len();
4251 headers.push(*id);
4252 headers.extend_from_slice(&u32::try_from(encoded.len()).unwrap().to_le_bytes());
4253 headers.extend_from_slice(&u32::try_from(offset).unwrap().to_le_bytes());
4254 data_block.extend_from_slice(&encoded);
4255 }
4256
4257 let token_len = 4 + headers.len() + data_block.len();
4258 let mut out = vec![0xEE];
4259 out.extend_from_slice(&u32::try_from(token_len).unwrap().to_le_bytes());
4260 out.extend_from_slice(&u32::try_from(options.len()).unwrap().to_le_bytes());
4261 out.extend_from_slice(&headers);
4262 out.extend_from_slice(&data_block);
4263 out
4264 }
4265
4266 #[test]
4267 fn test_fed_auth_info_decodes_spec_layout() {
4268 const STS: &str = "https://login.microsoftonline.com/common";
4269 const SPN: &str = "https://database.windows.net/";
4270 let token = build_fed_auth_info_token(&[(0x01, STS), (0x02, SPN)]);
4274
4275 let mut parser = TokenParser::new(Bytes::from(token));
4276 let parsed = parser.next_token().unwrap().unwrap();
4277 let Token::FedAuthInfo(info) = parsed else {
4278 panic!("expected FedAuthInfo, got {parsed:?}");
4279 };
4280 assert_eq!(info.sts_url, STS);
4281 assert_eq!(info.spn, SPN);
4282 assert!(parser.next_token().unwrap().is_none(), "exact consumption");
4283 }
4284
4285 #[test]
4286 fn test_fed_auth_info_preserves_following_tokens() {
4287 let mut stream = build_fed_auth_info_token(&[
4291 (0x01, "https://sts.example/"),
4292 (0x02, "https://db.example/"),
4293 ]);
4294 stream.push(0xFD); stream.extend_from_slice(&0u16.to_le_bytes()); stream.extend_from_slice(&0u16.to_le_bytes()); stream.extend_from_slice(&0u64.to_le_bytes()); let mut parser = TokenParser::new(Bytes::from(stream));
4300 assert!(matches!(
4301 parser.next_token().unwrap(),
4302 Some(Token::FedAuthInfo(_))
4303 ));
4304 assert!(
4305 matches!(parser.next_token().unwrap(), Some(Token::Done(_))),
4306 "DONE after FEDAUTHINFO must not be swallowed"
4307 );
4308 assert!(parser.next_token().unwrap().is_none());
4309 }
4310
4311 #[test]
4312 fn test_fed_auth_info_unknown_ids_ignored() {
4313 let token =
4315 build_fed_auth_info_token(&[(0x7F, "ignore-me"), (0x01, "https://sts.example/")]);
4316 let mut parser = TokenParser::new(Bytes::from(token));
4317 let Some(Token::FedAuthInfo(info)) = parser.next_token().unwrap() else {
4318 panic!("expected FedAuthInfo");
4319 };
4320 assert_eq!(info.sts_url, "https://sts.example/");
4321 assert_eq!(info.spn, "");
4322 }
4323
4324 #[test]
4325 fn test_fed_auth_info_hostile_inputs_error() {
4326 let mut truncated = build_fed_auth_info_token(&[(0x02, "https://sts.example/")]);
4328 truncated.truncate(truncated.len() - 4);
4329 assert!(
4330 TokenParser::new(Bytes::from(truncated))
4331 .next_token()
4332 .is_err()
4333 );
4334
4335 let mut bad_count = build_fed_auth_info_token(&[(0x02, "https://sts.example/")]);
4338 bad_count[5..9].copy_from_slice(&u32::MAX.to_le_bytes());
4339 assert!(
4340 TokenParser::new(Bytes::from(bad_count))
4341 .next_token()
4342 .is_err()
4343 );
4344
4345 let mut bad_offset = build_fed_auth_info_token(&[(0x02, "https://sts.example/")]);
4347 bad_offset[14..18].copy_from_slice(&u32::MAX.to_le_bytes());
4348 assert!(
4349 TokenParser::new(Bytes::from(bad_offset))
4350 .next_token()
4351 .is_err()
4352 );
4353
4354 let mut odd_len = build_fed_auth_info_token(&[(0x02, "https://sts.example/")]);
4356 odd_len[10..14].copy_from_slice(&3u32.to_le_bytes());
4357 assert!(TokenParser::new(Bytes::from(odd_len)).next_token().is_err());
4358 }
4359
4360 #[test]
4361 fn test_fed_auth_info_parse_and_skip_agree() {
4362 let token = build_fed_auth_info_token(&[(0x02, "https://sts.example/")]);
4365 let total = token.len();
4366
4367 let mut parser = TokenParser::new(Bytes::from(token.clone()));
4368 parser.next_token().unwrap();
4369 assert_eq!(parser.position(), total, "decode consumption");
4370
4371 let mut skipper = TokenParser::new(Bytes::from(token));
4372 skipper.skip_token().unwrap();
4373 assert_eq!(skipper.position(), total, "skip consumption");
4374 }
4375
4376 #[test]
4387 fn test_fed_auth_info_captured_from_azure() {
4388 const CAPTURED: &[u8] = &[
4389 0xEE, 0xCC, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x3A, 0x00, 0x00, 0x00,
4390 0x16, 0x00, 0x00, 0x00, 0x01, 0x7C, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x68,
4391 0x00, 0x74, 0x00, 0x74, 0x00, 0x70, 0x00, 0x73, 0x00, 0x3A, 0x00, 0x2F, 0x00, 0x2F,
4392 0x00, 0x64, 0x00, 0x61, 0x00, 0x74, 0x00, 0x61, 0x00, 0x62, 0x00, 0x61, 0x00, 0x73,
4393 0x00, 0x65, 0x00, 0x2E, 0x00, 0x77, 0x00, 0x69, 0x00, 0x6E, 0x00, 0x64, 0x00, 0x6F,
4394 0x00, 0x77, 0x00, 0x73, 0x00, 0x2E, 0x00, 0x6E, 0x00, 0x65, 0x00, 0x74, 0x00, 0x2F,
4395 0x00, 0x68, 0x00, 0x74, 0x00, 0x74, 0x00, 0x70, 0x00, 0x73, 0x00, 0x3A, 0x00, 0x2F,
4396 0x00, 0x2F, 0x00, 0x6C, 0x00, 0x6F, 0x00, 0x67, 0x00, 0x69, 0x00, 0x6E, 0x00, 0x2E,
4397 0x00, 0x77, 0x00, 0x69, 0x00, 0x6E, 0x00, 0x64, 0x00, 0x6F, 0x00, 0x77, 0x00, 0x73,
4398 0x00, 0x2E, 0x00, 0x6E, 0x00, 0x65, 0x00, 0x74, 0x00, 0x2F, 0x00, 0x30, 0x00, 0x30,
4399 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x2D,
4400 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x2D, 0x00, 0x30, 0x00, 0x30,
4401 0x00, 0x30, 0x00, 0x30, 0x00, 0x2D, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30,
4402 0x00, 0x2D, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30,
4403 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00,
4404 ];
4405
4406 let mut parser = TokenParser::new(Bytes::from_static(CAPTURED));
4407 let Some(Token::FedAuthInfo(info)) = parser.next_token().unwrap() else {
4408 panic!("expected FedAuthInfo");
4409 };
4410 assert_eq!(
4411 info.sts_url,
4412 "https://login.windows.net/00000000-0000-0000-0000-000000000000"
4413 );
4414 assert_eq!(info.spn, "https://database.windows.net/");
4415 assert!(
4416 parser.next_token().unwrap().is_none(),
4417 "the captured token must be consumed exactly"
4418 );
4419 }
4420
4421 #[test]
4437 fn skip_tokens_iterate_not_recurse_273() {
4438 const SKIP_COUNT: usize = 200_000;
4439 let mut buf = BytesMut::with_capacity(SKIP_COUNT * 3 + 13);
4440 for _ in 0..SKIP_COUNT {
4441 buf.put_u8(TokenType::ColInfo as u8);
4442 buf.put_u16_le(0); }
4444 let done = Done {
4445 status: DoneStatus {
4446 more: false,
4447 error: false,
4448 in_xact: false,
4449 count: true,
4450 attn: false,
4451 srverror: false,
4452 },
4453 cur_cmd: 0xABCD,
4454 row_count: 99,
4455 };
4456 done.encode(&mut buf);
4457 let total_len = buf.len();
4458
4459 let mut parser = TokenParser::new(buf.freeze());
4460
4461 let Some(Token::Done(decoded)) = parser.next_token().unwrap() else {
4464 panic!("expected the DONE token after the skip run");
4465 };
4466 assert_eq!(decoded.cur_cmd, 0xABCD);
4467 assert_eq!(decoded.row_count, 99);
4468
4469 assert_eq!(parser.position(), total_len);
4471 assert!(parser.next_token().unwrap().is_none());
4472 }
4473
4474 #[test]
4479 fn skip_token_returnvalue_advances_to_token_end() {
4480 let rv = build_return_value_intn(1, "@result", 0x01, Some(42));
4481 let rv_token_len = 1 + rv.len(); let mut buf = BytesMut::new();
4484 buf.put_u8(TokenType::ReturnValue as u8);
4485 buf.extend_from_slice(&rv);
4486 let done = Done {
4488 status: DoneStatus {
4489 more: false,
4490 error: false,
4491 in_xact: false,
4492 count: true,
4493 attn: false,
4494 srverror: false,
4495 },
4496 cur_cmd: 0x1234,
4497 row_count: 7,
4498 };
4499 done.encode(&mut buf);
4500
4501 let mut parser = TokenParser::new(buf.freeze());
4502 parser.skip_token().unwrap();
4503 assert_eq!(parser.position(), rv_token_len);
4504
4505 let Some(Token::Done(decoded)) = parser.next_token().unwrap() else {
4506 panic!("expected the DONE token after skipping the RETURNVALUE");
4507 };
4508 assert_eq!(decoded.cur_cmd, 0x1234);
4509 assert_eq!(decoded.row_count, 7);
4510 }
4511
4512 fn compute_by_tokens(id: u16, rows: &[i32]) -> BytesMut {
4516 let mut buf = BytesMut::new();
4517 buf.put_u8(TokenType::AltMetaData as u8);
4519 buf.put_u16_le(1); buf.put_u16_le(id); buf.put_u8(1); buf.put_u16_le(1); buf.put_u8(0x4D); buf.put_u16_le(1); buf.put_u32_le(0); buf.put_u16_le(0); buf.put_u8(TypeId::Int4 as u8); buf.put_u8(0); for &v in rows {
4531 buf.put_u8(TokenType::AltRow as u8);
4532 buf.put_u16_le(id); buf.put_i32_le(v); }
4535 buf
4536 }
4537
4538 fn trailing_done(buf: &mut BytesMut) {
4539 let done = Done {
4540 status: DoneStatus {
4541 more: false,
4542 error: false,
4543 in_xact: false,
4544 count: true,
4545 attn: false,
4546 srverror: false,
4547 },
4548 cur_cmd: 0xBEEF,
4549 row_count: 3,
4550 };
4551 done.encode(buf);
4552 }
4553
4554 #[test]
4558 fn compute_by_alt_tokens_skipped_275() {
4559 let mut buf = compute_by_tokens(7, &[42, -1]);
4560 trailing_done(&mut buf);
4561 let total_len = buf.len();
4562
4563 let mut parser = TokenParser::new(buf.freeze());
4564
4565 let Some(Token::Done(done)) = parser.next_token().unwrap() else {
4568 panic!("expected DONE after the COMPUTE BY tokens were skipped");
4569 };
4570 assert_eq!(done.cur_cmd, 0xBEEF);
4571
4572 assert_eq!(parser.position(), total_len);
4574 assert!(parser.next_token().unwrap().is_none());
4575 }
4576
4577 #[test]
4580 fn compute_by_alt_metadata_cleared_on_new_colmetadata_275() {
4581 let mut buf = compute_by_tokens(7, &[42]);
4582 buf.put_u8(TokenType::ColMetaData as u8);
4585 buf.put_u16_le(ColMetaData::NO_METADATA);
4586 buf.extend_from_slice(&compute_by_tokens(7, &[99]));
4587 trailing_done(&mut buf);
4588 let total_len = buf.len();
4589
4590 let mut parser = TokenParser::new(buf.freeze());
4591
4592 let Some(Token::ColMetaData(_)) = parser.next_token().unwrap() else {
4594 panic!("expected ColMetaData between the two compute groups");
4595 };
4596 let Some(Token::Done(_)) = parser.next_token().unwrap() else {
4598 panic!("expected DONE after the second COMPUTE BY group");
4599 };
4600 assert_eq!(parser.position(), total_len);
4601 }
4602
4603 #[test]
4606 fn altrow_without_altmetadata_errors_275() {
4607 let mut buf = BytesMut::new();
4608 buf.put_u8(TokenType::AltRow as u8);
4609 buf.put_u16_le(7); buf.put_i32_le(42);
4611
4612 let mut parser = TokenParser::new(buf.freeze());
4613 assert!(parser.next_token().is_err());
4614 }
4615}