1use bytes::{Buf, BufMut, Bytes};
31
32use crate::codec::{read_b_varchar, read_us_varchar};
33use crate::error::ProtocolError;
34use crate::prelude::*;
35use crate::types::TypeId;
36
37#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
39#[repr(u8)]
40#[non_exhaustive]
41pub enum TokenType {
42 ColMetaData = 0x81,
44 Error = 0xAA,
46 Info = 0xAB,
48 LoginAck = 0xAD,
50 Row = 0xD1,
52 NbcRow = 0xD2,
54 EnvChange = 0xE3,
56 Sspi = 0xED,
58 Done = 0xFD,
60 DoneInProc = 0xFF,
62 DoneProc = 0xFE,
64 ReturnStatus = 0x79,
66 ReturnValue = 0xAC,
68 Order = 0xA9,
70 FeatureExtAck = 0xAE,
72 SessionState = 0xE4,
74 FedAuthInfo = 0xEE,
76 ColInfo = 0xA5,
78 TabName = 0xA4,
80 Offset = 0x78,
82}
83
84impl TokenType {
85 pub fn from_u8(value: u8) -> Option<Self> {
87 match value {
88 0x81 => Some(Self::ColMetaData),
89 0xAA => Some(Self::Error),
90 0xAB => Some(Self::Info),
91 0xAD => Some(Self::LoginAck),
92 0xD1 => Some(Self::Row),
93 0xD2 => Some(Self::NbcRow),
94 0xE3 => Some(Self::EnvChange),
95 0xED => Some(Self::Sspi),
96 0xFD => Some(Self::Done),
97 0xFF => Some(Self::DoneInProc),
98 0xFE => Some(Self::DoneProc),
99 0x79 => Some(Self::ReturnStatus),
100 0xAC => Some(Self::ReturnValue),
101 0xA9 => Some(Self::Order),
102 0xAE => Some(Self::FeatureExtAck),
103 0xE4 => Some(Self::SessionState),
104 0xEE => Some(Self::FedAuthInfo),
105 0xA5 => Some(Self::ColInfo),
106 0xA4 => Some(Self::TabName),
107 0x78 => Some(Self::Offset),
108 _ => None,
109 }
110 }
111}
112
113#[derive(Debug, Clone)]
118#[non_exhaustive]
119pub enum Token {
120 ColMetaData(ColMetaData),
122 Row(RawRow),
124 NbcRow(NbcRow),
126 Done(Done),
128 DoneProc(DoneProc),
130 DoneInProc(DoneInProc),
132 ReturnStatus(i32),
134 ReturnValue(ReturnValue),
136 Error(ServerError),
138 Info(ServerInfo),
140 LoginAck(LoginAck),
142 EnvChange(EnvChange),
144 Order(Order),
146 FeatureExtAck(FeatureExtAck),
148 Sspi(SspiToken),
150 SessionState(SessionState),
152 FedAuthInfo(FedAuthInfo),
154}
155
156#[derive(Debug, Clone, Default)]
158pub struct ColMetaData {
159 pub columns: Vec<ColumnData>,
161}
162
163#[derive(Debug, Clone)]
165pub struct ColumnData {
166 pub name: String,
168 pub type_id: TypeId,
170 pub col_type: u8,
172 pub flags: u16,
174 pub user_type: u32,
176 pub type_info: TypeInfo,
178}
179
180#[derive(Debug, Clone, Default)]
182pub struct TypeInfo {
183 pub max_length: Option<u32>,
185 pub precision: Option<u8>,
187 pub scale: Option<u8>,
189 pub collation: Option<Collation>,
191}
192
193#[derive(Debug, Clone, Copy, Default)]
216pub struct Collation {
217 pub lcid: u32,
225 pub sort_id: u8,
229}
230
231impl Collation {
232 #[cfg(feature = "encoding")]
258 pub fn encoding(&self) -> Option<&'static encoding_rs::Encoding> {
259 crate::collation::encoding_for_lcid(self.lcid)
260 }
261
262 #[cfg(feature = "encoding")]
267 pub fn is_utf8(&self) -> bool {
268 crate::collation::is_utf8_collation(self.lcid)
269 }
270
271 #[cfg(feature = "encoding")]
279 pub fn code_page(&self) -> Option<u16> {
280 crate::collation::code_page_for_lcid(self.lcid)
281 }
282
283 #[cfg(feature = "encoding")]
287 pub fn encoding_name(&self) -> &'static str {
288 crate::collation::encoding_name_for_lcid(self.lcid)
289 }
290}
291
292#[derive(Debug, Clone)]
294pub struct RawRow {
295 pub data: bytes::Bytes,
297}
298
299#[derive(Debug, Clone)]
301pub struct NbcRow {
302 pub null_bitmap: Vec<u8>,
304 pub data: bytes::Bytes,
306}
307
308#[derive(Debug, Clone, Copy)]
310pub struct Done {
311 pub status: DoneStatus,
313 pub cur_cmd: u16,
315 pub row_count: u64,
317}
318
319#[derive(Debug, Clone, Copy, Default)]
321#[non_exhaustive]
322pub struct DoneStatus {
323 pub more: bool,
325 pub error: bool,
327 pub in_xact: bool,
329 pub count: bool,
331 pub attn: bool,
333 pub srverror: bool,
335}
336
337#[derive(Debug, Clone, Copy)]
339pub struct DoneInProc {
340 pub status: DoneStatus,
342 pub cur_cmd: u16,
344 pub row_count: u64,
346}
347
348#[derive(Debug, Clone, Copy)]
350pub struct DoneProc {
351 pub status: DoneStatus,
353 pub cur_cmd: u16,
355 pub row_count: u64,
357}
358
359#[derive(Debug, Clone)]
361pub struct ReturnValue {
362 pub param_ordinal: u16,
364 pub param_name: String,
366 pub status: u8,
368 pub user_type: u32,
370 pub flags: u16,
372 pub type_info: TypeInfo,
374 pub value: bytes::Bytes,
376}
377
378#[derive(Debug, Clone)]
380pub struct ServerError {
381 pub number: i32,
383 pub state: u8,
385 pub class: u8,
387 pub message: String,
389 pub server: String,
391 pub procedure: String,
393 pub line: i32,
395}
396
397#[derive(Debug, Clone)]
399pub struct ServerInfo {
400 pub number: i32,
402 pub state: u8,
404 pub class: u8,
406 pub message: String,
408 pub server: String,
410 pub procedure: String,
412 pub line: i32,
414}
415
416#[derive(Debug, Clone)]
418pub struct LoginAck {
419 pub interface: u8,
421 pub tds_version: u32,
423 pub prog_name: String,
425 pub prog_version: u32,
427}
428
429#[derive(Debug, Clone)]
431pub struct EnvChange {
432 pub env_type: EnvChangeType,
434 pub new_value: EnvChangeValue,
436 pub old_value: EnvChangeValue,
438}
439
440#[derive(Debug, Clone, Copy, PartialEq, Eq)]
442#[repr(u8)]
443#[non_exhaustive]
444pub enum EnvChangeType {
445 Database = 1,
447 Language = 2,
449 CharacterSet = 3,
451 PacketSize = 4,
453 UnicodeSortingLocalId = 5,
455 UnicodeComparisonFlags = 6,
457 SqlCollation = 7,
459 BeginTransaction = 8,
461 CommitTransaction = 9,
463 RollbackTransaction = 10,
465 EnlistDtcTransaction = 11,
467 DefectTransaction = 12,
469 RealTimeLogShipping = 13,
471 PromoteTransaction = 15,
473 TransactionManagerAddress = 16,
475 TransactionEnded = 17,
477 ResetConnectionCompletionAck = 18,
479 UserInstanceStarted = 19,
481 Routing = 20,
483}
484
485#[derive(Debug, Clone)]
487#[non_exhaustive]
488pub enum EnvChangeValue {
489 String(String),
491 Binary(bytes::Bytes),
493 Routing {
495 host: String,
497 port: u16,
499 },
500}
501
502#[derive(Debug, Clone)]
504pub struct Order {
505 pub columns: Vec<u16>,
507}
508
509#[derive(Debug, Clone)]
511pub struct FeatureExtAck {
512 pub features: Vec<FeatureAck>,
514}
515
516#[derive(Debug, Clone)]
518pub struct FeatureAck {
519 pub feature_id: u8,
521 pub data: bytes::Bytes,
523}
524
525#[derive(Debug, Clone)]
527pub struct SspiToken {
528 pub data: bytes::Bytes,
530}
531
532#[derive(Debug, Clone)]
534pub struct SessionState {
535 pub data: bytes::Bytes,
537}
538
539#[derive(Debug, Clone)]
541pub struct FedAuthInfo {
542 pub sts_url: String,
544 pub spn: String,
546}
547
548impl ColMetaData {
553 pub const NO_METADATA: u16 = 0xFFFF;
555
556 pub fn decode(src: &mut impl Buf) -> Result<Self, ProtocolError> {
558 if src.remaining() < 2 {
559 return Err(ProtocolError::UnexpectedEof);
560 }
561
562 let column_count = src.get_u16_le();
563
564 if column_count == Self::NO_METADATA {
566 return Ok(Self {
567 columns: Vec::new(),
568 });
569 }
570
571 let mut columns = Vec::with_capacity(column_count as usize);
572
573 for _ in 0..column_count {
574 let column = Self::decode_column(src)?;
575 columns.push(column);
576 }
577
578 Ok(Self { columns })
579 }
580
581 fn decode_column(src: &mut impl Buf) -> Result<ColumnData, ProtocolError> {
583 if src.remaining() < 7 {
585 return Err(ProtocolError::UnexpectedEof);
586 }
587
588 let user_type = src.get_u32_le();
589 let flags = src.get_u16_le();
590 let col_type = src.get_u8();
591
592 let type_id = TypeId::from_u8(col_type).unwrap_or(TypeId::Null); let type_info = Self::decode_type_info(src, type_id, col_type)?;
596
597 let name = read_b_varchar(src).ok_or(ProtocolError::UnexpectedEof)?;
599
600 Ok(ColumnData {
601 name,
602 type_id,
603 col_type,
604 flags,
605 user_type,
606 type_info,
607 })
608 }
609
610 fn decode_type_info(
612 src: &mut impl Buf,
613 type_id: TypeId,
614 col_type: u8,
615 ) -> Result<TypeInfo, ProtocolError> {
616 match type_id {
617 TypeId::Null => Ok(TypeInfo::default()),
619 TypeId::Int1 | TypeId::Bit => Ok(TypeInfo::default()),
620 TypeId::Int2 => Ok(TypeInfo::default()),
621 TypeId::Int4 => Ok(TypeInfo::default()),
622 TypeId::Int8 => Ok(TypeInfo::default()),
623 TypeId::Float4 => Ok(TypeInfo::default()),
624 TypeId::Float8 => Ok(TypeInfo::default()),
625 TypeId::Money => Ok(TypeInfo::default()),
626 TypeId::Money4 => Ok(TypeInfo::default()),
627 TypeId::DateTime => Ok(TypeInfo::default()),
628 TypeId::DateTime4 => Ok(TypeInfo::default()),
629
630 TypeId::IntN | TypeId::BitN | TypeId::FloatN | TypeId::MoneyN | TypeId::DateTimeN => {
632 if src.remaining() < 1 {
633 return Err(ProtocolError::UnexpectedEof);
634 }
635 let max_length = src.get_u8() as u32;
636 Ok(TypeInfo {
637 max_length: Some(max_length),
638 ..Default::default()
639 })
640 }
641
642 TypeId::Guid => {
644 if src.remaining() < 1 {
645 return Err(ProtocolError::UnexpectedEof);
646 }
647 let max_length = src.get_u8() as u32;
648 Ok(TypeInfo {
649 max_length: Some(max_length),
650 ..Default::default()
651 })
652 }
653
654 TypeId::Decimal | TypeId::Numeric | TypeId::DecimalN | TypeId::NumericN => {
656 if src.remaining() < 3 {
657 return Err(ProtocolError::UnexpectedEof);
658 }
659 let max_length = src.get_u8() as u32;
660 let precision = src.get_u8();
661 let scale = src.get_u8();
662 Ok(TypeInfo {
663 max_length: Some(max_length),
664 precision: Some(precision),
665 scale: Some(scale),
666 ..Default::default()
667 })
668 }
669
670 TypeId::Char | TypeId::VarChar | TypeId::Binary | TypeId::VarBinary => {
672 if src.remaining() < 1 {
673 return Err(ProtocolError::UnexpectedEof);
674 }
675 let max_length = src.get_u8() as u32;
676 Ok(TypeInfo {
677 max_length: Some(max_length),
678 ..Default::default()
679 })
680 }
681
682 TypeId::BigVarChar | TypeId::BigChar => {
684 if src.remaining() < 7 {
685 return Err(ProtocolError::UnexpectedEof);
687 }
688 let max_length = src.get_u16_le() as u32;
689 let collation = Self::decode_collation(src)?;
690 Ok(TypeInfo {
691 max_length: Some(max_length),
692 collation: Some(collation),
693 ..Default::default()
694 })
695 }
696
697 TypeId::BigVarBinary | TypeId::BigBinary => {
699 if src.remaining() < 2 {
700 return Err(ProtocolError::UnexpectedEof);
701 }
702 let max_length = src.get_u16_le() as u32;
703 Ok(TypeInfo {
704 max_length: Some(max_length),
705 ..Default::default()
706 })
707 }
708
709 TypeId::NChar | TypeId::NVarChar => {
711 if src.remaining() < 7 {
712 return Err(ProtocolError::UnexpectedEof);
714 }
715 let max_length = src.get_u16_le() as u32;
716 let collation = Self::decode_collation(src)?;
717 Ok(TypeInfo {
718 max_length: Some(max_length),
719 collation: Some(collation),
720 ..Default::default()
721 })
722 }
723
724 TypeId::Date => Ok(TypeInfo::default()),
726
727 TypeId::Time | TypeId::DateTime2 | TypeId::DateTimeOffset => {
729 if src.remaining() < 1 {
730 return Err(ProtocolError::UnexpectedEof);
731 }
732 let scale = src.get_u8();
733 Ok(TypeInfo {
734 scale: Some(scale),
735 ..Default::default()
736 })
737 }
738
739 TypeId::Text | TypeId::NText | TypeId::Image => {
741 if src.remaining() < 4 {
743 return Err(ProtocolError::UnexpectedEof);
744 }
745 let max_length = src.get_u32_le();
746
747 let collation = if type_id == TypeId::Text || type_id == TypeId::NText {
749 if src.remaining() < 5 {
750 return Err(ProtocolError::UnexpectedEof);
751 }
752 Some(Self::decode_collation(src)?)
753 } else {
754 None
755 };
756
757 if src.remaining() < 1 {
760 return Err(ProtocolError::UnexpectedEof);
761 }
762 let num_parts = src.get_u8();
763 for _ in 0..num_parts {
764 let _ = read_us_varchar(src).ok_or(ProtocolError::UnexpectedEof)?;
766 }
767
768 Ok(TypeInfo {
769 max_length: Some(max_length),
770 collation,
771 ..Default::default()
772 })
773 }
774
775 TypeId::Xml => {
777 if src.remaining() < 1 {
778 return Err(ProtocolError::UnexpectedEof);
779 }
780 let schema_present = src.get_u8();
781
782 if schema_present != 0 {
783 let _ = read_us_varchar(src).ok_or(ProtocolError::UnexpectedEof)?; let _ = read_us_varchar(src).ok_or(ProtocolError::UnexpectedEof)?; let _ = read_us_varchar(src).ok_or(ProtocolError::UnexpectedEof)?; }
788
789 Ok(TypeInfo::default())
790 }
791
792 TypeId::Udt => {
794 if src.remaining() < 2 {
796 return Err(ProtocolError::UnexpectedEof);
797 }
798 let max_length = src.get_u16_le() as u32;
799
800 let _ = read_us_varchar(src).ok_or(ProtocolError::UnexpectedEof)?; let _ = read_us_varchar(src).ok_or(ProtocolError::UnexpectedEof)?; let _ = read_us_varchar(src).ok_or(ProtocolError::UnexpectedEof)?; let _ = read_us_varchar(src).ok_or(ProtocolError::UnexpectedEof)?; Ok(TypeInfo {
807 max_length: Some(max_length),
808 ..Default::default()
809 })
810 }
811
812 TypeId::Tvp => {
814 Err(ProtocolError::InvalidTokenType(col_type))
817 }
818
819 TypeId::Variant => {
821 if src.remaining() < 4 {
822 return Err(ProtocolError::UnexpectedEof);
823 }
824 let max_length = src.get_u32_le();
825 Ok(TypeInfo {
826 max_length: Some(max_length),
827 ..Default::default()
828 })
829 }
830 }
831 }
832
833 fn decode_collation(src: &mut impl Buf) -> Result<Collation, ProtocolError> {
835 if src.remaining() < 5 {
836 return Err(ProtocolError::UnexpectedEof);
837 }
838 let lcid = src.get_u32_le();
840 let sort_id = src.get_u8();
841 Ok(Collation { lcid, sort_id })
842 }
843
844 #[must_use]
846 pub fn column_count(&self) -> usize {
847 self.columns.len()
848 }
849
850 #[must_use]
852 pub fn is_empty(&self) -> bool {
853 self.columns.is_empty()
854 }
855}
856
857impl ColumnData {
858 #[must_use]
860 pub fn is_nullable(&self) -> bool {
861 (self.flags & 0x0001) != 0
862 }
863
864 #[must_use]
868 pub fn fixed_size(&self) -> Option<usize> {
869 match self.type_id {
870 TypeId::Null => Some(0),
871 TypeId::Int1 | TypeId::Bit => Some(1),
872 TypeId::Int2 => Some(2),
873 TypeId::Int4 => Some(4),
874 TypeId::Int8 => Some(8),
875 TypeId::Float4 => Some(4),
876 TypeId::Float8 => Some(8),
877 TypeId::Money => Some(8),
878 TypeId::Money4 => Some(4),
879 TypeId::DateTime => Some(8),
880 TypeId::DateTime4 => Some(4),
881 TypeId::Date => Some(3),
882 _ => None,
883 }
884 }
885}
886
887impl RawRow {
892 pub fn decode(src: &mut impl Buf, metadata: &ColMetaData) -> Result<Self, ProtocolError> {
897 let mut data = bytes::BytesMut::new();
898
899 for col in &metadata.columns {
900 Self::decode_column_value(src, col, &mut data)?;
901 }
902
903 Ok(Self {
904 data: data.freeze(),
905 })
906 }
907
908 fn decode_column_value(
910 src: &mut impl Buf,
911 col: &ColumnData,
912 dst: &mut bytes::BytesMut,
913 ) -> Result<(), ProtocolError> {
914 match col.type_id {
915 TypeId::Null => {
917 }
919 TypeId::Int1 | TypeId::Bit => {
920 if src.remaining() < 1 {
921 return Err(ProtocolError::UnexpectedEof);
922 }
923 dst.extend_from_slice(&[src.get_u8()]);
924 }
925 TypeId::Int2 => {
926 if src.remaining() < 2 {
927 return Err(ProtocolError::UnexpectedEof);
928 }
929 dst.extend_from_slice(&src.get_u16_le().to_le_bytes());
930 }
931 TypeId::Int4 => {
932 if src.remaining() < 4 {
933 return Err(ProtocolError::UnexpectedEof);
934 }
935 dst.extend_from_slice(&src.get_u32_le().to_le_bytes());
936 }
937 TypeId::Int8 => {
938 if src.remaining() < 8 {
939 return Err(ProtocolError::UnexpectedEof);
940 }
941 dst.extend_from_slice(&src.get_u64_le().to_le_bytes());
942 }
943 TypeId::Float4 => {
944 if src.remaining() < 4 {
945 return Err(ProtocolError::UnexpectedEof);
946 }
947 dst.extend_from_slice(&src.get_u32_le().to_le_bytes());
948 }
949 TypeId::Float8 => {
950 if src.remaining() < 8 {
951 return Err(ProtocolError::UnexpectedEof);
952 }
953 dst.extend_from_slice(&src.get_u64_le().to_le_bytes());
954 }
955 TypeId::Money => {
956 if src.remaining() < 8 {
957 return Err(ProtocolError::UnexpectedEof);
958 }
959 let hi = src.get_u32_le();
960 let lo = src.get_u32_le();
961 dst.extend_from_slice(&hi.to_le_bytes());
962 dst.extend_from_slice(&lo.to_le_bytes());
963 }
964 TypeId::Money4 => {
965 if src.remaining() < 4 {
966 return Err(ProtocolError::UnexpectedEof);
967 }
968 dst.extend_from_slice(&src.get_u32_le().to_le_bytes());
969 }
970 TypeId::DateTime => {
971 if src.remaining() < 8 {
972 return Err(ProtocolError::UnexpectedEof);
973 }
974 let days = src.get_u32_le();
975 let time = src.get_u32_le();
976 dst.extend_from_slice(&days.to_le_bytes());
977 dst.extend_from_slice(&time.to_le_bytes());
978 }
979 TypeId::DateTime4 => {
980 if src.remaining() < 4 {
981 return Err(ProtocolError::UnexpectedEof);
982 }
983 dst.extend_from_slice(&src.get_u32_le().to_le_bytes());
984 }
985 TypeId::Date => {
987 Self::decode_bytelen_type(src, dst)?;
988 }
989
990 TypeId::IntN | TypeId::BitN | TypeId::FloatN | TypeId::MoneyN | TypeId::DateTimeN => {
992 Self::decode_bytelen_type(src, dst)?;
993 }
994
995 TypeId::Guid => {
996 Self::decode_bytelen_type(src, dst)?;
997 }
998
999 TypeId::Decimal | TypeId::Numeric | TypeId::DecimalN | TypeId::NumericN => {
1000 Self::decode_bytelen_type(src, dst)?;
1001 }
1002
1003 TypeId::Char | TypeId::VarChar | TypeId::Binary | TypeId::VarBinary => {
1005 Self::decode_bytelen_type(src, dst)?;
1006 }
1007
1008 TypeId::BigVarChar | TypeId::BigVarBinary => {
1010 if col.type_info.max_length == Some(0xFFFF) {
1012 Self::decode_plp_type(src, dst)?;
1013 } else {
1014 Self::decode_ushortlen_type(src, dst)?;
1015 }
1016 }
1017
1018 TypeId::BigChar | TypeId::BigBinary => {
1020 Self::decode_ushortlen_type(src, dst)?;
1021 }
1022
1023 TypeId::NVarChar => {
1025 if col.type_info.max_length == Some(0xFFFF) {
1027 Self::decode_plp_type(src, dst)?;
1028 } else {
1029 Self::decode_ushortlen_type(src, dst)?;
1030 }
1031 }
1032
1033 TypeId::NChar => {
1035 Self::decode_ushortlen_type(src, dst)?;
1036 }
1037
1038 TypeId::Time | TypeId::DateTime2 | TypeId::DateTimeOffset => {
1040 Self::decode_bytelen_type(src, dst)?;
1041 }
1042
1043 TypeId::Text | TypeId::NText | TypeId::Image => {
1045 Self::decode_textptr_type(src, dst)?;
1046 }
1047
1048 TypeId::Xml => {
1050 Self::decode_plp_type(src, dst)?;
1051 }
1052
1053 TypeId::Variant => {
1055 Self::decode_intlen_type(src, dst)?;
1056 }
1057
1058 TypeId::Udt => {
1059 Self::decode_plp_type(src, dst)?;
1061 }
1062
1063 TypeId::Tvp => {
1064 return Err(ProtocolError::InvalidTokenType(col.col_type));
1066 }
1067 }
1068
1069 Ok(())
1070 }
1071
1072 fn decode_bytelen_type(
1074 src: &mut impl Buf,
1075 dst: &mut bytes::BytesMut,
1076 ) -> Result<(), ProtocolError> {
1077 if src.remaining() < 1 {
1078 return Err(ProtocolError::UnexpectedEof);
1079 }
1080 let len = src.get_u8() as usize;
1081 if len == 0xFF {
1082 dst.extend_from_slice(&[0xFF]);
1084 } else if len == 0 {
1085 dst.extend_from_slice(&[0x00]);
1087 } else {
1088 if src.remaining() < len {
1089 return Err(ProtocolError::UnexpectedEof);
1090 }
1091 dst.extend_from_slice(&[len as u8]);
1092 for _ in 0..len {
1093 dst.extend_from_slice(&[src.get_u8()]);
1094 }
1095 }
1096 Ok(())
1097 }
1098
1099 fn decode_ushortlen_type(
1101 src: &mut impl Buf,
1102 dst: &mut bytes::BytesMut,
1103 ) -> Result<(), ProtocolError> {
1104 if src.remaining() < 2 {
1105 return Err(ProtocolError::UnexpectedEof);
1106 }
1107 let len = src.get_u16_le() as usize;
1108 if len == 0xFFFF {
1109 dst.extend_from_slice(&0xFFFFu16.to_le_bytes());
1111 } else if len == 0 {
1112 dst.extend_from_slice(&0u16.to_le_bytes());
1114 } else {
1115 if src.remaining() < len {
1116 return Err(ProtocolError::UnexpectedEof);
1117 }
1118 dst.extend_from_slice(&(len as u16).to_le_bytes());
1119 for _ in 0..len {
1120 dst.extend_from_slice(&[src.get_u8()]);
1121 }
1122 }
1123 Ok(())
1124 }
1125
1126 fn decode_intlen_type(
1128 src: &mut impl Buf,
1129 dst: &mut bytes::BytesMut,
1130 ) -> Result<(), ProtocolError> {
1131 if src.remaining() < 4 {
1132 return Err(ProtocolError::UnexpectedEof);
1133 }
1134 let len = src.get_u32_le() as usize;
1135 if len == 0xFFFFFFFF {
1136 dst.extend_from_slice(&0xFFFFFFFFu32.to_le_bytes());
1138 } else if len == 0 {
1139 dst.extend_from_slice(&0u32.to_le_bytes());
1141 } else {
1142 if src.remaining() < len {
1143 return Err(ProtocolError::UnexpectedEof);
1144 }
1145 dst.extend_from_slice(&(len as u32).to_le_bytes());
1146 for _ in 0..len {
1147 dst.extend_from_slice(&[src.get_u8()]);
1148 }
1149 }
1150 Ok(())
1151 }
1152
1153 fn decode_textptr_type(
1168 src: &mut impl Buf,
1169 dst: &mut bytes::BytesMut,
1170 ) -> Result<(), ProtocolError> {
1171 if src.remaining() < 1 {
1172 return Err(ProtocolError::UnexpectedEof);
1173 }
1174
1175 let textptr_len = src.get_u8() as usize;
1176
1177 if textptr_len == 0 {
1178 dst.extend_from_slice(&0xFFFFFFFFFFFFFFFFu64.to_le_bytes());
1180 return Ok(());
1181 }
1182
1183 if src.remaining() < textptr_len {
1185 return Err(ProtocolError::UnexpectedEof);
1186 }
1187 src.advance(textptr_len);
1188
1189 if src.remaining() < 8 {
1191 return Err(ProtocolError::UnexpectedEof);
1192 }
1193 src.advance(8);
1194
1195 if src.remaining() < 4 {
1197 return Err(ProtocolError::UnexpectedEof);
1198 }
1199 let data_len = src.get_u32_le() as usize;
1200
1201 if src.remaining() < data_len {
1202 return Err(ProtocolError::UnexpectedEof);
1203 }
1204
1205 dst.extend_from_slice(&(data_len as u64).to_le_bytes());
1211 dst.extend_from_slice(&(data_len as u32).to_le_bytes());
1212 for _ in 0..data_len {
1213 dst.extend_from_slice(&[src.get_u8()]);
1214 }
1215 dst.extend_from_slice(&0u32.to_le_bytes()); Ok(())
1218 }
1219
1220 fn decode_plp_type(src: &mut impl Buf, dst: &mut bytes::BytesMut) -> Result<(), ProtocolError> {
1226 if src.remaining() < 8 {
1227 return Err(ProtocolError::UnexpectedEof);
1228 }
1229
1230 let total_len = src.get_u64_le();
1231
1232 dst.extend_from_slice(&total_len.to_le_bytes());
1234
1235 if total_len == 0xFFFFFFFFFFFFFFFF {
1236 return Ok(());
1238 }
1239
1240 loop {
1242 if src.remaining() < 4 {
1243 return Err(ProtocolError::UnexpectedEof);
1244 }
1245 let chunk_len = src.get_u32_le() as usize;
1246 dst.extend_from_slice(&(chunk_len as u32).to_le_bytes());
1247
1248 if chunk_len == 0 {
1249 break;
1251 }
1252
1253 if src.remaining() < chunk_len {
1254 return Err(ProtocolError::UnexpectedEof);
1255 }
1256
1257 for _ in 0..chunk_len {
1258 dst.extend_from_slice(&[src.get_u8()]);
1259 }
1260 }
1261
1262 Ok(())
1263 }
1264}
1265
1266impl NbcRow {
1271 pub fn decode(src: &mut impl Buf, metadata: &ColMetaData) -> Result<Self, ProtocolError> {
1276 let col_count = metadata.columns.len();
1277 let bitmap_len = col_count.div_ceil(8);
1278
1279 if src.remaining() < bitmap_len {
1280 return Err(ProtocolError::UnexpectedEof);
1281 }
1282
1283 let mut null_bitmap = vec![0u8; bitmap_len];
1285 for byte in &mut null_bitmap {
1286 *byte = src.get_u8();
1287 }
1288
1289 let mut data = bytes::BytesMut::new();
1291
1292 for (i, col) in metadata.columns.iter().enumerate() {
1293 let byte_idx = i / 8;
1294 let bit_idx = i % 8;
1295 let is_null = (null_bitmap[byte_idx] & (1 << bit_idx)) != 0;
1296
1297 if !is_null {
1298 RawRow::decode_column_value(src, col, &mut data)?;
1301 }
1302 }
1303
1304 Ok(Self {
1305 null_bitmap,
1306 data: data.freeze(),
1307 })
1308 }
1309
1310 #[must_use]
1312 pub fn is_null(&self, column_index: usize) -> bool {
1313 let byte_idx = column_index / 8;
1314 let bit_idx = column_index % 8;
1315 if byte_idx < self.null_bitmap.len() {
1316 (self.null_bitmap[byte_idx] & (1 << bit_idx)) != 0
1317 } else {
1318 true }
1320 }
1321}
1322
1323impl ReturnValue {
1328 pub fn decode(src: &mut impl Buf) -> Result<Self, ProtocolError> {
1330 if src.remaining() < 2 {
1332 return Err(ProtocolError::UnexpectedEof);
1333 }
1334 let _length = src.get_u16_le();
1335
1336 if src.remaining() < 2 {
1338 return Err(ProtocolError::UnexpectedEof);
1339 }
1340 let param_ordinal = src.get_u16_le();
1341
1342 let param_name = read_b_varchar(src).ok_or(ProtocolError::UnexpectedEof)?;
1344
1345 if src.remaining() < 1 {
1347 return Err(ProtocolError::UnexpectedEof);
1348 }
1349 let status = src.get_u8();
1350
1351 if src.remaining() < 7 {
1353 return Err(ProtocolError::UnexpectedEof);
1354 }
1355 let user_type = src.get_u32_le();
1356 let flags = src.get_u16_le();
1357 let col_type = src.get_u8();
1358
1359 let type_id = TypeId::from_u8(col_type).unwrap_or(TypeId::Null);
1360
1361 let type_info = ColMetaData::decode_type_info(src, type_id, col_type)?;
1363
1364 let mut value_buf = bytes::BytesMut::new();
1366
1367 let temp_col = ColumnData {
1369 name: String::new(),
1370 type_id,
1371 col_type,
1372 flags,
1373 user_type,
1374 type_info: type_info.clone(),
1375 };
1376
1377 RawRow::decode_column_value(src, &temp_col, &mut value_buf)?;
1378
1379 Ok(Self {
1380 param_ordinal,
1381 param_name,
1382 status,
1383 user_type,
1384 flags,
1385 type_info,
1386 value: value_buf.freeze(),
1387 })
1388 }
1389}
1390
1391impl SessionState {
1396 pub fn decode(src: &mut impl Buf) -> Result<Self, ProtocolError> {
1398 if src.remaining() < 4 {
1399 return Err(ProtocolError::UnexpectedEof);
1400 }
1401
1402 let length = src.get_u32_le() as usize;
1403
1404 if src.remaining() < length {
1405 return Err(ProtocolError::IncompletePacket {
1406 expected: length,
1407 actual: src.remaining(),
1408 });
1409 }
1410
1411 let data = src.copy_to_bytes(length);
1412
1413 Ok(Self { data })
1414 }
1415}
1416
1417mod done_status_bits {
1423 pub const DONE_MORE: u16 = 0x0001;
1424 pub const DONE_ERROR: u16 = 0x0002;
1425 pub const DONE_INXACT: u16 = 0x0004;
1426 pub const DONE_COUNT: u16 = 0x0010;
1427 pub const DONE_ATTN: u16 = 0x0020;
1428 pub const DONE_SRVERROR: u16 = 0x0100;
1429}
1430
1431impl DoneStatus {
1432 #[must_use]
1434 pub fn from_bits(bits: u16) -> Self {
1435 use done_status_bits::*;
1436 Self {
1437 more: (bits & DONE_MORE) != 0,
1438 error: (bits & DONE_ERROR) != 0,
1439 in_xact: (bits & DONE_INXACT) != 0,
1440 count: (bits & DONE_COUNT) != 0,
1441 attn: (bits & DONE_ATTN) != 0,
1442 srverror: (bits & DONE_SRVERROR) != 0,
1443 }
1444 }
1445
1446 #[must_use]
1448 pub fn to_bits(&self) -> u16 {
1449 use done_status_bits::*;
1450 let mut bits = 0u16;
1451 if self.more {
1452 bits |= DONE_MORE;
1453 }
1454 if self.error {
1455 bits |= DONE_ERROR;
1456 }
1457 if self.in_xact {
1458 bits |= DONE_INXACT;
1459 }
1460 if self.count {
1461 bits |= DONE_COUNT;
1462 }
1463 if self.attn {
1464 bits |= DONE_ATTN;
1465 }
1466 if self.srverror {
1467 bits |= DONE_SRVERROR;
1468 }
1469 bits
1470 }
1471}
1472
1473impl Done {
1474 pub const SIZE: usize = 12; pub fn decode(src: &mut impl Buf) -> Result<Self, ProtocolError> {
1479 if src.remaining() < Self::SIZE {
1480 return Err(ProtocolError::IncompletePacket {
1481 expected: Self::SIZE,
1482 actual: src.remaining(),
1483 });
1484 }
1485
1486 let status = DoneStatus::from_bits(src.get_u16_le());
1487 let cur_cmd = src.get_u16_le();
1488 let row_count = src.get_u64_le();
1489
1490 Ok(Self {
1491 status,
1492 cur_cmd,
1493 row_count,
1494 })
1495 }
1496
1497 pub fn encode(&self, dst: &mut impl BufMut) {
1499 dst.put_u8(TokenType::Done as u8);
1500 dst.put_u16_le(self.status.to_bits());
1501 dst.put_u16_le(self.cur_cmd);
1502 dst.put_u64_le(self.row_count);
1503 }
1504
1505 #[must_use]
1507 pub const fn has_more(&self) -> bool {
1508 self.status.more
1509 }
1510
1511 #[must_use]
1513 pub const fn has_error(&self) -> bool {
1514 self.status.error
1515 }
1516
1517 #[must_use]
1519 pub const fn has_count(&self) -> bool {
1520 self.status.count
1521 }
1522}
1523
1524impl DoneProc {
1525 pub const SIZE: usize = 12;
1527
1528 pub fn decode(src: &mut impl Buf) -> Result<Self, ProtocolError> {
1530 if src.remaining() < Self::SIZE {
1531 return Err(ProtocolError::IncompletePacket {
1532 expected: Self::SIZE,
1533 actual: src.remaining(),
1534 });
1535 }
1536
1537 let status = DoneStatus::from_bits(src.get_u16_le());
1538 let cur_cmd = src.get_u16_le();
1539 let row_count = src.get_u64_le();
1540
1541 Ok(Self {
1542 status,
1543 cur_cmd,
1544 row_count,
1545 })
1546 }
1547
1548 pub fn encode(&self, dst: &mut impl BufMut) {
1550 dst.put_u8(TokenType::DoneProc as u8);
1551 dst.put_u16_le(self.status.to_bits());
1552 dst.put_u16_le(self.cur_cmd);
1553 dst.put_u64_le(self.row_count);
1554 }
1555}
1556
1557impl DoneInProc {
1558 pub const SIZE: usize = 12;
1560
1561 pub fn decode(src: &mut impl Buf) -> Result<Self, ProtocolError> {
1563 if src.remaining() < Self::SIZE {
1564 return Err(ProtocolError::IncompletePacket {
1565 expected: Self::SIZE,
1566 actual: src.remaining(),
1567 });
1568 }
1569
1570 let status = DoneStatus::from_bits(src.get_u16_le());
1571 let cur_cmd = src.get_u16_le();
1572 let row_count = src.get_u64_le();
1573
1574 Ok(Self {
1575 status,
1576 cur_cmd,
1577 row_count,
1578 })
1579 }
1580
1581 pub fn encode(&self, dst: &mut impl BufMut) {
1583 dst.put_u8(TokenType::DoneInProc as u8);
1584 dst.put_u16_le(self.status.to_bits());
1585 dst.put_u16_le(self.cur_cmd);
1586 dst.put_u64_le(self.row_count);
1587 }
1588}
1589
1590impl ServerError {
1591 pub fn decode(src: &mut impl Buf) -> Result<Self, ProtocolError> {
1593 if src.remaining() < 2 {
1596 return Err(ProtocolError::UnexpectedEof);
1597 }
1598
1599 let _length = src.get_u16_le();
1600
1601 if src.remaining() < 6 {
1602 return Err(ProtocolError::UnexpectedEof);
1603 }
1604
1605 let number = src.get_i32_le();
1606 let state = src.get_u8();
1607 let class = src.get_u8();
1608
1609 let message = read_us_varchar(src).ok_or(ProtocolError::UnexpectedEof)?;
1610 let server = read_b_varchar(src).ok_or(ProtocolError::UnexpectedEof)?;
1611 let procedure = read_b_varchar(src).ok_or(ProtocolError::UnexpectedEof)?;
1612
1613 if src.remaining() < 4 {
1614 return Err(ProtocolError::UnexpectedEof);
1615 }
1616 let line = src.get_i32_le();
1617
1618 Ok(Self {
1619 number,
1620 state,
1621 class,
1622 message,
1623 server,
1624 procedure,
1625 line,
1626 })
1627 }
1628
1629 #[must_use]
1631 pub const fn is_fatal(&self) -> bool {
1632 self.class >= 20
1633 }
1634
1635 #[must_use]
1637 pub const fn is_batch_abort(&self) -> bool {
1638 self.class >= 16
1639 }
1640}
1641
1642impl ServerInfo {
1643 pub fn decode(src: &mut impl Buf) -> Result<Self, ProtocolError> {
1647 if src.remaining() < 2 {
1648 return Err(ProtocolError::UnexpectedEof);
1649 }
1650
1651 let _length = src.get_u16_le();
1652
1653 if src.remaining() < 6 {
1654 return Err(ProtocolError::UnexpectedEof);
1655 }
1656
1657 let number = src.get_i32_le();
1658 let state = src.get_u8();
1659 let class = src.get_u8();
1660
1661 let message = read_us_varchar(src).ok_or(ProtocolError::UnexpectedEof)?;
1662 let server = read_b_varchar(src).ok_or(ProtocolError::UnexpectedEof)?;
1663 let procedure = read_b_varchar(src).ok_or(ProtocolError::UnexpectedEof)?;
1664
1665 if src.remaining() < 4 {
1666 return Err(ProtocolError::UnexpectedEof);
1667 }
1668 let line = src.get_i32_le();
1669
1670 Ok(Self {
1671 number,
1672 state,
1673 class,
1674 message,
1675 server,
1676 procedure,
1677 line,
1678 })
1679 }
1680}
1681
1682impl LoginAck {
1683 pub fn decode(src: &mut impl Buf) -> Result<Self, ProtocolError> {
1685 if src.remaining() < 2 {
1687 return Err(ProtocolError::UnexpectedEof);
1688 }
1689
1690 let _length = src.get_u16_le();
1691
1692 if src.remaining() < 5 {
1693 return Err(ProtocolError::UnexpectedEof);
1694 }
1695
1696 let interface = src.get_u8();
1697 let tds_version = src.get_u32_le();
1698 let prog_name = read_b_varchar(src).ok_or(ProtocolError::UnexpectedEof)?;
1699
1700 if src.remaining() < 4 {
1701 return Err(ProtocolError::UnexpectedEof);
1702 }
1703 let prog_version = src.get_u32_le();
1704
1705 Ok(Self {
1706 interface,
1707 tds_version,
1708 prog_name,
1709 prog_version,
1710 })
1711 }
1712
1713 #[must_use]
1715 pub fn tds_version(&self) -> crate::version::TdsVersion {
1716 crate::version::TdsVersion::new(self.tds_version)
1717 }
1718}
1719
1720impl EnvChangeType {
1721 pub fn from_u8(value: u8) -> Option<Self> {
1723 match value {
1724 1 => Some(Self::Database),
1725 2 => Some(Self::Language),
1726 3 => Some(Self::CharacterSet),
1727 4 => Some(Self::PacketSize),
1728 5 => Some(Self::UnicodeSortingLocalId),
1729 6 => Some(Self::UnicodeComparisonFlags),
1730 7 => Some(Self::SqlCollation),
1731 8 => Some(Self::BeginTransaction),
1732 9 => Some(Self::CommitTransaction),
1733 10 => Some(Self::RollbackTransaction),
1734 11 => Some(Self::EnlistDtcTransaction),
1735 12 => Some(Self::DefectTransaction),
1736 13 => Some(Self::RealTimeLogShipping),
1737 15 => Some(Self::PromoteTransaction),
1738 16 => Some(Self::TransactionManagerAddress),
1739 17 => Some(Self::TransactionEnded),
1740 18 => Some(Self::ResetConnectionCompletionAck),
1741 19 => Some(Self::UserInstanceStarted),
1742 20 => Some(Self::Routing),
1743 _ => None,
1744 }
1745 }
1746}
1747
1748impl EnvChange {
1749 pub fn decode(src: &mut impl Buf) -> Result<Self, ProtocolError> {
1751 if src.remaining() < 3 {
1752 return Err(ProtocolError::UnexpectedEof);
1753 }
1754
1755 let length = src.get_u16_le() as usize;
1756 if src.remaining() < length {
1757 return Err(ProtocolError::IncompletePacket {
1758 expected: length,
1759 actual: src.remaining(),
1760 });
1761 }
1762
1763 let env_type_byte = src.get_u8();
1764 let env_type = EnvChangeType::from_u8(env_type_byte)
1765 .ok_or(ProtocolError::InvalidTokenType(env_type_byte))?;
1766
1767 let (new_value, old_value) = match env_type {
1768 EnvChangeType::Routing => {
1769 let new_value = Self::decode_routing_value(src)?;
1771 let old_value = EnvChangeValue::Binary(Bytes::new());
1772 (new_value, old_value)
1773 }
1774 EnvChangeType::BeginTransaction
1775 | EnvChangeType::CommitTransaction
1776 | EnvChangeType::RollbackTransaction
1777 | EnvChangeType::EnlistDtcTransaction
1778 | EnvChangeType::SqlCollation => {
1779 let new_len = src.get_u8() as usize;
1783 let new_value = if new_len > 0 && src.remaining() >= new_len {
1784 EnvChangeValue::Binary(src.copy_to_bytes(new_len))
1785 } else {
1786 EnvChangeValue::Binary(Bytes::new())
1787 };
1788
1789 let old_len = src.get_u8() as usize;
1790 let old_value = if old_len > 0 && src.remaining() >= old_len {
1791 EnvChangeValue::Binary(src.copy_to_bytes(old_len))
1792 } else {
1793 EnvChangeValue::Binary(Bytes::new())
1794 };
1795
1796 (new_value, old_value)
1797 }
1798 _ => {
1799 let new_value = read_b_varchar(src)
1801 .map(EnvChangeValue::String)
1802 .unwrap_or(EnvChangeValue::String(String::new()));
1803
1804 let old_value = read_b_varchar(src)
1805 .map(EnvChangeValue::String)
1806 .unwrap_or(EnvChangeValue::String(String::new()));
1807
1808 (new_value, old_value)
1809 }
1810 };
1811
1812 Ok(Self {
1813 env_type,
1814 new_value,
1815 old_value,
1816 })
1817 }
1818
1819 fn decode_routing_value(src: &mut impl Buf) -> Result<EnvChangeValue, ProtocolError> {
1820 if src.remaining() < 2 {
1822 return Err(ProtocolError::UnexpectedEof);
1823 }
1824
1825 let _routing_len = src.get_u16_le();
1826
1827 if src.remaining() < 5 {
1828 return Err(ProtocolError::UnexpectedEof);
1829 }
1830
1831 let _protocol = src.get_u8();
1832 let port = src.get_u16_le();
1833 let server_len = src.get_u16_le() as usize;
1834
1835 if src.remaining() < server_len * 2 {
1837 return Err(ProtocolError::UnexpectedEof);
1838 }
1839
1840 let mut chars = Vec::with_capacity(server_len);
1841 for _ in 0..server_len {
1842 chars.push(src.get_u16_le());
1843 }
1844
1845 let host = String::from_utf16(&chars).map_err(|_| {
1846 ProtocolError::StringEncoding(
1847 #[cfg(feature = "std")]
1848 "invalid UTF-16 in routing hostname".to_string(),
1849 #[cfg(not(feature = "std"))]
1850 "invalid UTF-16 in routing hostname",
1851 )
1852 })?;
1853
1854 Ok(EnvChangeValue::Routing { host, port })
1855 }
1856
1857 #[must_use]
1859 pub fn is_routing(&self) -> bool {
1860 self.env_type == EnvChangeType::Routing
1861 }
1862
1863 #[must_use]
1865 pub fn routing_info(&self) -> Option<(&str, u16)> {
1866 if let EnvChangeValue::Routing { host, port } = &self.new_value {
1867 Some((host, *port))
1868 } else {
1869 None
1870 }
1871 }
1872
1873 #[must_use]
1875 pub fn new_database(&self) -> Option<&str> {
1876 if self.env_type == EnvChangeType::Database {
1877 if let EnvChangeValue::String(s) = &self.new_value {
1878 return Some(s);
1879 }
1880 }
1881 None
1882 }
1883}
1884
1885impl Order {
1886 pub fn decode(src: &mut impl Buf) -> Result<Self, ProtocolError> {
1888 if src.remaining() < 2 {
1889 return Err(ProtocolError::UnexpectedEof);
1890 }
1891
1892 let length = src.get_u16_le() as usize;
1893 let column_count = length / 2;
1894
1895 if src.remaining() < length {
1896 return Err(ProtocolError::IncompletePacket {
1897 expected: length,
1898 actual: src.remaining(),
1899 });
1900 }
1901
1902 let mut columns = Vec::with_capacity(column_count);
1903 for _ in 0..column_count {
1904 columns.push(src.get_u16_le());
1905 }
1906
1907 Ok(Self { columns })
1908 }
1909}
1910
1911impl FeatureExtAck {
1912 pub const TERMINATOR: u8 = 0xFF;
1914
1915 pub fn decode(src: &mut impl Buf) -> Result<Self, ProtocolError> {
1917 let mut features = Vec::new();
1918
1919 loop {
1920 if !src.has_remaining() {
1921 return Err(ProtocolError::UnexpectedEof);
1922 }
1923
1924 let feature_id = src.get_u8();
1925 if feature_id == Self::TERMINATOR {
1926 break;
1927 }
1928
1929 if src.remaining() < 4 {
1930 return Err(ProtocolError::UnexpectedEof);
1931 }
1932
1933 let data_len = src.get_u32_le() as usize;
1934
1935 if src.remaining() < data_len {
1936 return Err(ProtocolError::IncompletePacket {
1937 expected: data_len,
1938 actual: src.remaining(),
1939 });
1940 }
1941
1942 let data = src.copy_to_bytes(data_len);
1943 features.push(FeatureAck { feature_id, data });
1944 }
1945
1946 Ok(Self { features })
1947 }
1948}
1949
1950impl SspiToken {
1951 pub fn decode(src: &mut impl Buf) -> Result<Self, ProtocolError> {
1953 if src.remaining() < 2 {
1954 return Err(ProtocolError::UnexpectedEof);
1955 }
1956
1957 let length = src.get_u16_le() as usize;
1958
1959 if src.remaining() < length {
1960 return Err(ProtocolError::IncompletePacket {
1961 expected: length,
1962 actual: src.remaining(),
1963 });
1964 }
1965
1966 let data = src.copy_to_bytes(length);
1967 Ok(Self { data })
1968 }
1969}
1970
1971impl FedAuthInfo {
1972 pub fn decode(src: &mut impl Buf) -> Result<Self, ProtocolError> {
1974 if src.remaining() < 4 {
1975 return Err(ProtocolError::UnexpectedEof);
1976 }
1977
1978 let _length = src.get_u32_le();
1979
1980 if src.remaining() < 5 {
1981 return Err(ProtocolError::UnexpectedEof);
1982 }
1983
1984 let _count = src.get_u8();
1985
1986 let mut sts_url = String::new();
1988 let mut spn = String::new();
1989
1990 while src.has_remaining() {
1992 if src.remaining() < 9 {
1993 break;
1994 }
1995
1996 let info_id = src.get_u8();
1997 let info_len = src.get_u32_le() as usize;
1998 let _info_offset = src.get_u32_le();
1999
2000 if src.remaining() < info_len {
2001 break;
2002 }
2003
2004 let char_count = info_len / 2;
2006 let mut chars = Vec::with_capacity(char_count);
2007 for _ in 0..char_count {
2008 chars.push(src.get_u16_le());
2009 }
2010
2011 if let Ok(value) = String::from_utf16(&chars) {
2012 match info_id {
2013 0x01 => spn = value,
2014 0x02 => sts_url = value,
2015 _ => {}
2016 }
2017 }
2018 }
2019
2020 Ok(Self { sts_url, spn })
2021 }
2022}
2023
2024pub struct TokenParser {
2065 data: Bytes,
2066 position: usize,
2067}
2068
2069impl TokenParser {
2070 #[must_use]
2072 pub fn new(data: Bytes) -> Self {
2073 Self { data, position: 0 }
2074 }
2075
2076 #[must_use]
2078 pub fn remaining(&self) -> usize {
2079 self.data.len().saturating_sub(self.position)
2080 }
2081
2082 #[must_use]
2084 pub fn has_remaining(&self) -> bool {
2085 self.position < self.data.len()
2086 }
2087
2088 #[must_use]
2090 pub fn peek_token_type(&self) -> Option<TokenType> {
2091 if self.position < self.data.len() {
2092 TokenType::from_u8(self.data[self.position])
2093 } else {
2094 None
2095 }
2096 }
2097
2098 pub fn next_token(&mut self) -> Result<Option<Token>, ProtocolError> {
2106 self.next_token_with_metadata(None)
2107 }
2108
2109 pub fn next_token_with_metadata(
2116 &mut self,
2117 metadata: Option<&ColMetaData>,
2118 ) -> Result<Option<Token>, ProtocolError> {
2119 if !self.has_remaining() {
2120 return Ok(None);
2121 }
2122
2123 let mut buf = &self.data[self.position..];
2124 let start_pos = self.position;
2125
2126 let token_type_byte = buf.get_u8();
2127 let token_type = TokenType::from_u8(token_type_byte);
2128
2129 let token = match token_type {
2130 Some(TokenType::Done) => {
2131 let done = Done::decode(&mut buf)?;
2132 Token::Done(done)
2133 }
2134 Some(TokenType::DoneProc) => {
2135 let done = DoneProc::decode(&mut buf)?;
2136 Token::DoneProc(done)
2137 }
2138 Some(TokenType::DoneInProc) => {
2139 let done = DoneInProc::decode(&mut buf)?;
2140 Token::DoneInProc(done)
2141 }
2142 Some(TokenType::Error) => {
2143 let error = ServerError::decode(&mut buf)?;
2144 Token::Error(error)
2145 }
2146 Some(TokenType::Info) => {
2147 let info = ServerInfo::decode(&mut buf)?;
2148 Token::Info(info)
2149 }
2150 Some(TokenType::LoginAck) => {
2151 let login_ack = LoginAck::decode(&mut buf)?;
2152 Token::LoginAck(login_ack)
2153 }
2154 Some(TokenType::EnvChange) => {
2155 let env_change = EnvChange::decode(&mut buf)?;
2156 Token::EnvChange(env_change)
2157 }
2158 Some(TokenType::Order) => {
2159 let order = Order::decode(&mut buf)?;
2160 Token::Order(order)
2161 }
2162 Some(TokenType::FeatureExtAck) => {
2163 let ack = FeatureExtAck::decode(&mut buf)?;
2164 Token::FeatureExtAck(ack)
2165 }
2166 Some(TokenType::Sspi) => {
2167 let sspi = SspiToken::decode(&mut buf)?;
2168 Token::Sspi(sspi)
2169 }
2170 Some(TokenType::FedAuthInfo) => {
2171 let info = FedAuthInfo::decode(&mut buf)?;
2172 Token::FedAuthInfo(info)
2173 }
2174 Some(TokenType::ReturnStatus) => {
2175 if buf.remaining() < 4 {
2176 return Err(ProtocolError::UnexpectedEof);
2177 }
2178 let status = buf.get_i32_le();
2179 Token::ReturnStatus(status)
2180 }
2181 Some(TokenType::ColMetaData) => {
2182 let col_meta = ColMetaData::decode(&mut buf)?;
2183 Token::ColMetaData(col_meta)
2184 }
2185 Some(TokenType::Row) => {
2186 let meta = metadata.ok_or_else(|| {
2187 ProtocolError::StringEncoding(
2188 #[cfg(feature = "std")]
2189 "Row token requires column metadata".to_string(),
2190 #[cfg(not(feature = "std"))]
2191 "Row token requires column metadata",
2192 )
2193 })?;
2194 let row = RawRow::decode(&mut buf, meta)?;
2195 Token::Row(row)
2196 }
2197 Some(TokenType::NbcRow) => {
2198 let meta = metadata.ok_or_else(|| {
2199 ProtocolError::StringEncoding(
2200 #[cfg(feature = "std")]
2201 "NbcRow token requires column metadata".to_string(),
2202 #[cfg(not(feature = "std"))]
2203 "NbcRow token requires column metadata",
2204 )
2205 })?;
2206 let row = NbcRow::decode(&mut buf, meta)?;
2207 Token::NbcRow(row)
2208 }
2209 Some(TokenType::ReturnValue) => {
2210 let ret_val = ReturnValue::decode(&mut buf)?;
2211 Token::ReturnValue(ret_val)
2212 }
2213 Some(TokenType::SessionState) => {
2214 let session = SessionState::decode(&mut buf)?;
2215 Token::SessionState(session)
2216 }
2217 Some(TokenType::ColInfo) | Some(TokenType::TabName) | Some(TokenType::Offset) => {
2218 if buf.remaining() < 2 {
2221 return Err(ProtocolError::UnexpectedEof);
2222 }
2223 let length = buf.get_u16_le() as usize;
2224 if buf.remaining() < length {
2225 return Err(ProtocolError::IncompletePacket {
2226 expected: length,
2227 actual: buf.remaining(),
2228 });
2229 }
2230 buf.advance(length);
2232 self.position = start_pos + (self.data.len() - start_pos - buf.remaining());
2234 return self.next_token_with_metadata(metadata);
2235 }
2236 None => {
2237 return Err(ProtocolError::InvalidTokenType(token_type_byte));
2238 }
2239 };
2240
2241 let consumed = self.data.len() - start_pos - buf.remaining();
2243 self.position = start_pos + consumed;
2244
2245 Ok(Some(token))
2246 }
2247
2248 pub fn skip_token(&mut self) -> Result<(), ProtocolError> {
2252 if !self.has_remaining() {
2253 return Ok(());
2254 }
2255
2256 let token_type_byte = self.data[self.position];
2257 let token_type = TokenType::from_u8(token_type_byte);
2258
2259 let skip_amount = match token_type {
2261 Some(TokenType::Done) | Some(TokenType::DoneProc) | Some(TokenType::DoneInProc) => {
2263 1 + Done::SIZE }
2265 Some(TokenType::ReturnStatus) => {
2266 1 + 4 }
2268 Some(TokenType::Error)
2270 | Some(TokenType::Info)
2271 | Some(TokenType::LoginAck)
2272 | Some(TokenType::EnvChange)
2273 | Some(TokenType::Order)
2274 | Some(TokenType::Sspi)
2275 | Some(TokenType::ColInfo)
2276 | Some(TokenType::TabName)
2277 | Some(TokenType::Offset)
2278 | Some(TokenType::ReturnValue) => {
2279 if self.remaining() < 3 {
2280 return Err(ProtocolError::UnexpectedEof);
2281 }
2282 let length = u16::from_le_bytes([
2283 self.data[self.position + 1],
2284 self.data[self.position + 2],
2285 ]) as usize;
2286 1 + 2 + length }
2288 Some(TokenType::SessionState) | Some(TokenType::FedAuthInfo) => {
2290 if self.remaining() < 5 {
2291 return Err(ProtocolError::UnexpectedEof);
2292 }
2293 let length = u32::from_le_bytes([
2294 self.data[self.position + 1],
2295 self.data[self.position + 2],
2296 self.data[self.position + 3],
2297 self.data[self.position + 4],
2298 ]) as usize;
2299 1 + 4 + length
2300 }
2301 Some(TokenType::FeatureExtAck) => {
2303 let mut buf = &self.data[self.position + 1..];
2305 let _ = FeatureExtAck::decode(&mut buf)?;
2306 self.data.len() - self.position - buf.remaining()
2307 }
2308 Some(TokenType::ColMetaData) | Some(TokenType::Row) | Some(TokenType::NbcRow) => {
2310 return Err(ProtocolError::InvalidTokenType(token_type_byte));
2311 }
2312 None => {
2313 return Err(ProtocolError::InvalidTokenType(token_type_byte));
2314 }
2315 };
2316
2317 if self.remaining() < skip_amount {
2318 return Err(ProtocolError::UnexpectedEof);
2319 }
2320
2321 self.position += skip_amount;
2322 Ok(())
2323 }
2324
2325 #[must_use]
2327 pub fn position(&self) -> usize {
2328 self.position
2329 }
2330
2331 pub fn reset(&mut self) {
2333 self.position = 0;
2334 }
2335}
2336
2337#[cfg(test)]
2342#[allow(clippy::unwrap_used, clippy::panic)]
2343mod tests {
2344 use super::*;
2345 use bytes::BytesMut;
2346
2347 #[test]
2348 fn test_done_roundtrip() {
2349 let done = Done {
2350 status: DoneStatus {
2351 more: false,
2352 error: false,
2353 in_xact: false,
2354 count: true,
2355 attn: false,
2356 srverror: false,
2357 },
2358 cur_cmd: 193, row_count: 42,
2360 };
2361
2362 let mut buf = BytesMut::new();
2363 done.encode(&mut buf);
2364
2365 let mut cursor = &buf[1..];
2367 let decoded = Done::decode(&mut cursor).unwrap();
2368
2369 assert_eq!(decoded.status.count, done.status.count);
2370 assert_eq!(decoded.cur_cmd, done.cur_cmd);
2371 assert_eq!(decoded.row_count, done.row_count);
2372 }
2373
2374 #[test]
2375 fn test_done_status_bits() {
2376 let status = DoneStatus {
2377 more: true,
2378 error: true,
2379 in_xact: true,
2380 count: true,
2381 attn: false,
2382 srverror: false,
2383 };
2384
2385 let bits = status.to_bits();
2386 let restored = DoneStatus::from_bits(bits);
2387
2388 assert_eq!(status.more, restored.more);
2389 assert_eq!(status.error, restored.error);
2390 assert_eq!(status.in_xact, restored.in_xact);
2391 assert_eq!(status.count, restored.count);
2392 }
2393
2394 #[test]
2395 fn test_token_parser_done() {
2396 let data = Bytes::from_static(&[
2398 0xFD, 0x10, 0x00, 0xC1, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ]);
2403
2404 let mut parser = TokenParser::new(data);
2405 let token = parser.next_token().unwrap().unwrap();
2406
2407 match token {
2408 Token::Done(done) => {
2409 assert!(done.status.count);
2410 assert!(!done.status.more);
2411 assert_eq!(done.cur_cmd, 193);
2412 assert_eq!(done.row_count, 5);
2413 }
2414 _ => panic!("Expected Done token"),
2415 }
2416
2417 assert!(parser.next_token().unwrap().is_none());
2419 }
2420
2421 #[test]
2422 fn test_env_change_type_from_u8() {
2423 assert_eq!(EnvChangeType::from_u8(1), Some(EnvChangeType::Database));
2424 assert_eq!(EnvChangeType::from_u8(20), Some(EnvChangeType::Routing));
2425 assert_eq!(EnvChangeType::from_u8(100), None);
2426 }
2427
2428 #[test]
2429 fn test_colmetadata_no_columns() {
2430 let data = Bytes::from_static(&[0xFF, 0xFF]);
2432 let mut cursor: &[u8] = &data;
2433 let meta = ColMetaData::decode(&mut cursor).unwrap();
2434 assert!(meta.is_empty());
2435 assert_eq!(meta.column_count(), 0);
2436 }
2437
2438 #[test]
2439 fn test_colmetadata_single_int_column() {
2440 let mut data = BytesMut::new();
2443 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;
2452 let meta = ColMetaData::decode(&mut cursor).unwrap();
2453
2454 assert_eq!(meta.column_count(), 1);
2455 assert_eq!(meta.columns[0].name, "id");
2456 assert_eq!(meta.columns[0].type_id, TypeId::Int4);
2457 assert!(meta.columns[0].is_nullable());
2458 }
2459
2460 #[test]
2461 fn test_colmetadata_nvarchar_column() {
2462 let mut data = BytesMut::new();
2464 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]);
2474
2475 let mut cursor: &[u8] = &data;
2476 let meta = ColMetaData::decode(&mut cursor).unwrap();
2477
2478 assert_eq!(meta.column_count(), 1);
2479 assert_eq!(meta.columns[0].name, "name");
2480 assert_eq!(meta.columns[0].type_id, TypeId::NVarChar);
2481 assert_eq!(meta.columns[0].type_info.max_length, Some(100));
2482 assert!(meta.columns[0].type_info.collation.is_some());
2483 }
2484
2485 #[test]
2486 fn test_raw_row_decode_int() {
2487 let metadata = ColMetaData {
2489 columns: vec![ColumnData {
2490 name: "id".to_string(),
2491 type_id: TypeId::Int4,
2492 col_type: 0x38,
2493 flags: 0,
2494 user_type: 0,
2495 type_info: TypeInfo::default(),
2496 }],
2497 };
2498
2499 let data = Bytes::from_static(&[0x2A, 0x00, 0x00, 0x00]); let mut cursor: &[u8] = &data;
2502 let row = RawRow::decode(&mut cursor, &metadata).unwrap();
2503
2504 assert_eq!(row.data.len(), 4);
2506 assert_eq!(&row.data[..], &[0x2A, 0x00, 0x00, 0x00]);
2507 }
2508
2509 #[test]
2510 fn test_raw_row_decode_nullable_int() {
2511 let metadata = ColMetaData {
2513 columns: vec![ColumnData {
2514 name: "id".to_string(),
2515 type_id: TypeId::IntN,
2516 col_type: 0x26,
2517 flags: 0x01, user_type: 0,
2519 type_info: TypeInfo {
2520 max_length: Some(4),
2521 ..Default::default()
2522 },
2523 }],
2524 };
2525
2526 let data = Bytes::from_static(&[0x04, 0x2A, 0x00, 0x00, 0x00]); let mut cursor: &[u8] = &data;
2529 let row = RawRow::decode(&mut cursor, &metadata).unwrap();
2530
2531 assert_eq!(row.data.len(), 5);
2532 assert_eq!(row.data[0], 4); assert_eq!(&row.data[1..], &[0x2A, 0x00, 0x00, 0x00]);
2534 }
2535
2536 #[test]
2537 fn test_raw_row_decode_null_value() {
2538 let metadata = ColMetaData {
2540 columns: vec![ColumnData {
2541 name: "id".to_string(),
2542 type_id: TypeId::IntN,
2543 col_type: 0x26,
2544 flags: 0x01, user_type: 0,
2546 type_info: TypeInfo {
2547 max_length: Some(4),
2548 ..Default::default()
2549 },
2550 }],
2551 };
2552
2553 let data = Bytes::from_static(&[0xFF]);
2555 let mut cursor: &[u8] = &data;
2556 let row = RawRow::decode(&mut cursor, &metadata).unwrap();
2557
2558 assert_eq!(row.data.len(), 1);
2559 assert_eq!(row.data[0], 0xFF); }
2561
2562 #[test]
2563 fn test_nbcrow_null_bitmap() {
2564 let row = NbcRow {
2565 null_bitmap: vec![0b00000101], data: Bytes::new(),
2567 };
2568
2569 assert!(row.is_null(0));
2570 assert!(!row.is_null(1));
2571 assert!(row.is_null(2));
2572 assert!(!row.is_null(3));
2573 }
2574
2575 #[test]
2576 fn test_token_parser_colmetadata() {
2577 let mut data = BytesMut::new();
2579 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());
2588 let token = parser.next_token().unwrap().unwrap();
2589
2590 match token {
2591 Token::ColMetaData(meta) => {
2592 assert_eq!(meta.column_count(), 1);
2593 assert_eq!(meta.columns[0].name, "id");
2594 assert_eq!(meta.columns[0].type_id, TypeId::Int4);
2595 }
2596 _ => panic!("Expected ColMetaData token"),
2597 }
2598 }
2599
2600 #[test]
2601 fn test_token_parser_row_with_metadata() {
2602 let metadata = ColMetaData {
2604 columns: vec![ColumnData {
2605 name: "id".to_string(),
2606 type_id: TypeId::Int4,
2607 col_type: 0x38,
2608 flags: 0,
2609 user_type: 0,
2610 type_info: TypeInfo::default(),
2611 }],
2612 };
2613
2614 let mut data = BytesMut::new();
2616 data.extend_from_slice(&[0xD1]); data.extend_from_slice(&[0x2A, 0x00, 0x00, 0x00]); let mut parser = TokenParser::new(data.freeze());
2620 let token = parser
2621 .next_token_with_metadata(Some(&metadata))
2622 .unwrap()
2623 .unwrap();
2624
2625 match token {
2626 Token::Row(row) => {
2627 assert_eq!(row.data.len(), 4);
2628 }
2629 _ => panic!("Expected Row token"),
2630 }
2631 }
2632
2633 #[test]
2634 fn test_token_parser_row_without_metadata_fails() {
2635 let mut data = BytesMut::new();
2637 data.extend_from_slice(&[0xD1]); data.extend_from_slice(&[0x2A, 0x00, 0x00, 0x00]); let mut parser = TokenParser::new(data.freeze());
2641 let result = parser.next_token(); assert!(result.is_err());
2644 }
2645
2646 #[test]
2647 fn test_token_parser_peek() {
2648 let data = Bytes::from_static(&[
2649 0xFD, 0x10, 0x00, 0xC1, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ]);
2654
2655 let parser = TokenParser::new(data);
2656 assert_eq!(parser.peek_token_type(), Some(TokenType::Done));
2657 }
2658
2659 #[test]
2660 fn test_column_data_fixed_size() {
2661 let col = ColumnData {
2662 name: String::new(),
2663 type_id: TypeId::Int4,
2664 col_type: 0x38,
2665 flags: 0,
2666 user_type: 0,
2667 type_info: TypeInfo::default(),
2668 };
2669 assert_eq!(col.fixed_size(), Some(4));
2670
2671 let col2 = ColumnData {
2672 name: String::new(),
2673 type_id: TypeId::NVarChar,
2674 col_type: 0xE7,
2675 flags: 0,
2676 user_type: 0,
2677 type_info: TypeInfo::default(),
2678 };
2679 assert_eq!(col2.fixed_size(), None);
2680 }
2681
2682 #[test]
2690 fn test_decode_nvarchar_then_intn_roundtrip() {
2691 let mut wire_data = BytesMut::new();
2696
2697 let word = "World";
2700 let utf16: Vec<u16> = word.encode_utf16().collect();
2701 wire_data.put_u16_le((utf16.len() * 2) as u16); for code_unit in &utf16 {
2703 wire_data.put_u16_le(*code_unit);
2704 }
2705
2706 wire_data.put_u8(4); wire_data.put_i32_le(42);
2709
2710 let metadata = ColMetaData {
2712 columns: vec![
2713 ColumnData {
2714 name: "greeting".to_string(),
2715 type_id: TypeId::NVarChar,
2716 col_type: 0xE7,
2717 flags: 0x01,
2718 user_type: 0,
2719 type_info: TypeInfo {
2720 max_length: Some(10), precision: None,
2722 scale: None,
2723 collation: None,
2724 },
2725 },
2726 ColumnData {
2727 name: "number".to_string(),
2728 type_id: TypeId::IntN,
2729 col_type: 0x26,
2730 flags: 0x01,
2731 user_type: 0,
2732 type_info: TypeInfo {
2733 max_length: Some(4),
2734 precision: None,
2735 scale: None,
2736 collation: None,
2737 },
2738 },
2739 ],
2740 };
2741
2742 let mut wire_cursor = wire_data.freeze();
2744 let raw_row = RawRow::decode(&mut wire_cursor, &metadata).unwrap();
2745
2746 assert_eq!(
2748 wire_cursor.remaining(),
2749 0,
2750 "wire data should be fully consumed"
2751 );
2752
2753 let mut stored_cursor: &[u8] = &raw_row.data;
2755
2756 assert!(
2759 stored_cursor.remaining() >= 2,
2760 "need at least 2 bytes for length"
2761 );
2762 let len0 = stored_cursor.get_u16_le() as usize;
2763 assert_eq!(len0, 10, "NVarChar length should be 10 bytes");
2764 assert!(
2765 stored_cursor.remaining() >= len0,
2766 "need {len0} bytes for data"
2767 );
2768
2769 let mut utf16_read = Vec::new();
2771 for _ in 0..(len0 / 2) {
2772 utf16_read.push(stored_cursor.get_u16_le());
2773 }
2774 let string0 = String::from_utf16(&utf16_read).unwrap();
2775 assert_eq!(string0, "World", "column 0 should be 'World'");
2776
2777 assert!(
2780 stored_cursor.remaining() >= 1,
2781 "need at least 1 byte for length"
2782 );
2783 let len1 = stored_cursor.get_u8();
2784 assert_eq!(len1, 4, "IntN length should be 4");
2785 assert!(stored_cursor.remaining() >= 4, "need 4 bytes for INT data");
2786 let int1 = stored_cursor.get_i32_le();
2787 assert_eq!(int1, 42, "column 1 should be 42");
2788
2789 assert_eq!(
2791 stored_cursor.remaining(),
2792 0,
2793 "stored data should be fully consumed"
2794 );
2795 }
2796
2797 #[test]
2798 fn test_decode_nvarchar_max_then_intn_roundtrip() {
2799 let mut wire_data = BytesMut::new();
2803
2804 let word = "Hello";
2807 let utf16: Vec<u16> = word.encode_utf16().collect();
2808 let byte_len = (utf16.len() * 2) as u64;
2809
2810 wire_data.put_u64_le(byte_len); wire_data.put_u32_le(byte_len as u32); for code_unit in &utf16 {
2813 wire_data.put_u16_le(*code_unit);
2814 }
2815 wire_data.put_u32_le(0); wire_data.put_u8(4);
2819 wire_data.put_i32_le(99);
2820
2821 let metadata = ColMetaData {
2823 columns: vec![
2824 ColumnData {
2825 name: "text".to_string(),
2826 type_id: TypeId::NVarChar,
2827 col_type: 0xE7,
2828 flags: 0x01,
2829 user_type: 0,
2830 type_info: TypeInfo {
2831 max_length: Some(0xFFFF), precision: None,
2833 scale: None,
2834 collation: None,
2835 },
2836 },
2837 ColumnData {
2838 name: "num".to_string(),
2839 type_id: TypeId::IntN,
2840 col_type: 0x26,
2841 flags: 0x01,
2842 user_type: 0,
2843 type_info: TypeInfo {
2844 max_length: Some(4),
2845 precision: None,
2846 scale: None,
2847 collation: None,
2848 },
2849 },
2850 ],
2851 };
2852
2853 let mut wire_cursor = wire_data.freeze();
2855 let raw_row = RawRow::decode(&mut wire_cursor, &metadata).unwrap();
2856
2857 assert_eq!(
2859 wire_cursor.remaining(),
2860 0,
2861 "wire data should be fully consumed"
2862 );
2863
2864 let mut stored_cursor: &[u8] = &raw_row.data;
2866
2867 let total_len = stored_cursor.get_u64_le();
2869 assert_eq!(total_len, 10, "PLP total length should be 10");
2870
2871 let chunk_len = stored_cursor.get_u32_le();
2872 assert_eq!(chunk_len, 10, "PLP chunk length should be 10");
2873
2874 let mut utf16_read = Vec::new();
2875 for _ in 0..(chunk_len / 2) {
2876 utf16_read.push(stored_cursor.get_u16_le());
2877 }
2878 let string0 = String::from_utf16(&utf16_read).unwrap();
2879 assert_eq!(string0, "Hello", "column 0 should be 'Hello'");
2880
2881 let terminator = stored_cursor.get_u32_le();
2882 assert_eq!(terminator, 0, "PLP should end with 0");
2883
2884 let len1 = stored_cursor.get_u8();
2886 assert_eq!(len1, 4);
2887 let int1 = stored_cursor.get_i32_le();
2888 assert_eq!(int1, 99, "column 1 should be 99");
2889
2890 assert_eq!(
2892 stored_cursor.remaining(),
2893 0,
2894 "stored data should be fully consumed"
2895 );
2896 }
2897}