1use bytes::{Buf, BufMut, Bytes};
31
32use crate::codec::{read_b_varchar, read_us_varchar};
33use crate::error::ProtocolError;
34use crate::types::TypeId;
35
36#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
38#[repr(u8)]
39pub enum TokenType {
40 ColMetaData = 0x81,
42 Error = 0xAA,
44 Info = 0xAB,
46 LoginAck = 0xAD,
48 Row = 0xD1,
50 NbcRow = 0xD2,
52 EnvChange = 0xE3,
54 Sspi = 0xED,
56 Done = 0xFD,
58 DoneInProc = 0xFF,
60 DoneProc = 0xFE,
62 ReturnStatus = 0x79,
64 ReturnValue = 0xAC,
66 Order = 0xA9,
68 FeatureExtAck = 0xAE,
70 SessionState = 0xE4,
72 FedAuthInfo = 0xEE,
74 ColInfo = 0xA5,
76 TabName = 0xA4,
78 Offset = 0x78,
80}
81
82impl TokenType {
83 pub fn from_u8(value: u8) -> Option<Self> {
85 match value {
86 0x81 => Some(Self::ColMetaData),
87 0xAA => Some(Self::Error),
88 0xAB => Some(Self::Info),
89 0xAD => Some(Self::LoginAck),
90 0xD1 => Some(Self::Row),
91 0xD2 => Some(Self::NbcRow),
92 0xE3 => Some(Self::EnvChange),
93 0xED => Some(Self::Sspi),
94 0xFD => Some(Self::Done),
95 0xFF => Some(Self::DoneInProc),
96 0xFE => Some(Self::DoneProc),
97 0x79 => Some(Self::ReturnStatus),
98 0xAC => Some(Self::ReturnValue),
99 0xA9 => Some(Self::Order),
100 0xAE => Some(Self::FeatureExtAck),
101 0xE4 => Some(Self::SessionState),
102 0xEE => Some(Self::FedAuthInfo),
103 0xA5 => Some(Self::ColInfo),
104 0xA4 => Some(Self::TabName),
105 0x78 => Some(Self::Offset),
106 _ => None,
107 }
108 }
109}
110
111#[derive(Debug, Clone)]
116pub enum Token {
117 ColMetaData(ColMetaData),
119 Row(RawRow),
121 NbcRow(NbcRow),
123 Done(Done),
125 DoneProc(DoneProc),
127 DoneInProc(DoneInProc),
129 ReturnStatus(i32),
131 ReturnValue(ReturnValue),
133 Error(ServerError),
135 Info(ServerInfo),
137 LoginAck(LoginAck),
139 EnvChange(EnvChange),
141 Order(Order),
143 FeatureExtAck(FeatureExtAck),
145 Sspi(SspiToken),
147 SessionState(SessionState),
149 FedAuthInfo(FedAuthInfo),
151}
152
153#[derive(Debug, Clone, Default)]
155pub struct ColMetaData {
156 pub columns: Vec<ColumnData>,
158}
159
160#[derive(Debug, Clone)]
162pub struct ColumnData {
163 pub name: String,
165 pub type_id: TypeId,
167 pub col_type: u8,
169 pub flags: u16,
171 pub user_type: u32,
173 pub type_info: TypeInfo,
175}
176
177#[derive(Debug, Clone, Default)]
179pub struct TypeInfo {
180 pub max_length: Option<u32>,
182 pub precision: Option<u8>,
184 pub scale: Option<u8>,
186 pub collation: Option<Collation>,
188}
189
190#[derive(Debug, Clone, Copy, Default)]
213pub struct Collation {
214 pub lcid: u32,
222 pub sort_id: u8,
226}
227
228impl Collation {
229 #[cfg(feature = "encoding")]
255 pub fn encoding(&self) -> Option<&'static encoding_rs::Encoding> {
256 crate::collation::encoding_for_lcid(self.lcid)
257 }
258
259 #[cfg(feature = "encoding")]
264 pub fn is_utf8(&self) -> bool {
265 crate::collation::is_utf8_collation(self.lcid)
266 }
267
268 #[cfg(feature = "encoding")]
276 pub fn code_page(&self) -> Option<u16> {
277 crate::collation::code_page_for_lcid(self.lcid)
278 }
279
280 #[cfg(feature = "encoding")]
284 pub fn encoding_name(&self) -> &'static str {
285 crate::collation::encoding_name_for_lcid(self.lcid)
286 }
287}
288
289#[derive(Debug, Clone)]
291pub struct RawRow {
292 pub data: bytes::Bytes,
294}
295
296#[derive(Debug, Clone)]
298pub struct NbcRow {
299 pub null_bitmap: Vec<u8>,
301 pub data: bytes::Bytes,
303}
304
305#[derive(Debug, Clone, Copy)]
307pub struct Done {
308 pub status: DoneStatus,
310 pub cur_cmd: u16,
312 pub row_count: u64,
314}
315
316#[derive(Debug, Clone, Copy, Default)]
318pub struct DoneStatus {
319 pub more: bool,
321 pub error: bool,
323 pub in_xact: bool,
325 pub count: bool,
327 pub attn: bool,
329 pub srverror: bool,
331}
332
333#[derive(Debug, Clone, Copy)]
335pub struct DoneInProc {
336 pub status: DoneStatus,
338 pub cur_cmd: u16,
340 pub row_count: u64,
342}
343
344#[derive(Debug, Clone, Copy)]
346pub struct DoneProc {
347 pub status: DoneStatus,
349 pub cur_cmd: u16,
351 pub row_count: u64,
353}
354
355#[derive(Debug, Clone)]
357pub struct ReturnValue {
358 pub param_ordinal: u16,
360 pub param_name: String,
362 pub status: u8,
364 pub user_type: u32,
366 pub flags: u16,
368 pub type_info: TypeInfo,
370 pub value: bytes::Bytes,
372}
373
374#[derive(Debug, Clone)]
376pub struct ServerError {
377 pub number: i32,
379 pub state: u8,
381 pub class: u8,
383 pub message: String,
385 pub server: String,
387 pub procedure: String,
389 pub line: i32,
391}
392
393#[derive(Debug, Clone)]
395pub struct ServerInfo {
396 pub number: i32,
398 pub state: u8,
400 pub class: u8,
402 pub message: String,
404 pub server: String,
406 pub procedure: String,
408 pub line: i32,
410}
411
412#[derive(Debug, Clone)]
414pub struct LoginAck {
415 pub interface: u8,
417 pub tds_version: u32,
419 pub prog_name: String,
421 pub prog_version: u32,
423}
424
425#[derive(Debug, Clone)]
427pub struct EnvChange {
428 pub env_type: EnvChangeType,
430 pub new_value: EnvChangeValue,
432 pub old_value: EnvChangeValue,
434}
435
436#[derive(Debug, Clone, Copy, PartialEq, Eq)]
438#[repr(u8)]
439pub enum EnvChangeType {
440 Database = 1,
442 Language = 2,
444 CharacterSet = 3,
446 PacketSize = 4,
448 UnicodeSortingLocalId = 5,
450 UnicodeComparisonFlags = 6,
452 SqlCollation = 7,
454 BeginTransaction = 8,
456 CommitTransaction = 9,
458 RollbackTransaction = 10,
460 EnlistDtcTransaction = 11,
462 DefectTransaction = 12,
464 RealTimeLogShipping = 13,
466 PromoteTransaction = 15,
468 TransactionManagerAddress = 16,
470 TransactionEnded = 17,
472 ResetConnectionCompletionAck = 18,
474 UserInstanceStarted = 19,
476 Routing = 20,
478}
479
480#[derive(Debug, Clone)]
482pub enum EnvChangeValue {
483 String(String),
485 Binary(bytes::Bytes),
487 Routing {
489 host: String,
491 port: u16,
493 },
494}
495
496#[derive(Debug, Clone)]
498pub struct Order {
499 pub columns: Vec<u16>,
501}
502
503#[derive(Debug, Clone)]
505pub struct FeatureExtAck {
506 pub features: Vec<FeatureAck>,
508}
509
510#[derive(Debug, Clone)]
512pub struct FeatureAck {
513 pub feature_id: u8,
515 pub data: bytes::Bytes,
517}
518
519#[derive(Debug, Clone)]
521pub struct SspiToken {
522 pub data: bytes::Bytes,
524}
525
526#[derive(Debug, Clone)]
528pub struct SessionState {
529 pub data: bytes::Bytes,
531}
532
533#[derive(Debug, Clone)]
535pub struct FedAuthInfo {
536 pub sts_url: String,
538 pub spn: String,
540}
541
542impl ColMetaData {
547 pub const NO_METADATA: u16 = 0xFFFF;
549
550 pub fn decode(src: &mut impl Buf) -> Result<Self, ProtocolError> {
552 if src.remaining() < 2 {
553 return Err(ProtocolError::UnexpectedEof);
554 }
555
556 let column_count = src.get_u16_le();
557
558 if column_count == Self::NO_METADATA {
560 return Ok(Self {
561 columns: Vec::new(),
562 });
563 }
564
565 let mut columns = Vec::with_capacity(column_count as usize);
566
567 for _ in 0..column_count {
568 let column = Self::decode_column(src)?;
569 columns.push(column);
570 }
571
572 Ok(Self { columns })
573 }
574
575 fn decode_column(src: &mut impl Buf) -> Result<ColumnData, ProtocolError> {
577 if src.remaining() < 7 {
579 return Err(ProtocolError::UnexpectedEof);
580 }
581
582 let user_type = src.get_u32_le();
583 let flags = src.get_u16_le();
584 let col_type = src.get_u8();
585
586 let type_id = TypeId::from_u8(col_type).unwrap_or(TypeId::Null); let type_info = Self::decode_type_info(src, type_id, col_type)?;
590
591 let name = read_b_varchar(src).ok_or(ProtocolError::UnexpectedEof)?;
593
594 Ok(ColumnData {
595 name,
596 type_id,
597 col_type,
598 flags,
599 user_type,
600 type_info,
601 })
602 }
603
604 fn decode_type_info(
606 src: &mut impl Buf,
607 type_id: TypeId,
608 col_type: u8,
609 ) -> Result<TypeInfo, ProtocolError> {
610 match type_id {
611 TypeId::Null => Ok(TypeInfo::default()),
613 TypeId::Int1 | TypeId::Bit => Ok(TypeInfo::default()),
614 TypeId::Int2 => Ok(TypeInfo::default()),
615 TypeId::Int4 => Ok(TypeInfo::default()),
616 TypeId::Int8 => Ok(TypeInfo::default()),
617 TypeId::Float4 => Ok(TypeInfo::default()),
618 TypeId::Float8 => Ok(TypeInfo::default()),
619 TypeId::Money => Ok(TypeInfo::default()),
620 TypeId::Money4 => Ok(TypeInfo::default()),
621 TypeId::DateTime => Ok(TypeInfo::default()),
622 TypeId::DateTime4 => Ok(TypeInfo::default()),
623
624 TypeId::IntN | TypeId::BitN | TypeId::FloatN | TypeId::MoneyN | TypeId::DateTimeN => {
626 if src.remaining() < 1 {
627 return Err(ProtocolError::UnexpectedEof);
628 }
629 let max_length = src.get_u8() as u32;
630 Ok(TypeInfo {
631 max_length: Some(max_length),
632 ..Default::default()
633 })
634 }
635
636 TypeId::Guid => {
638 if src.remaining() < 1 {
639 return Err(ProtocolError::UnexpectedEof);
640 }
641 let max_length = src.get_u8() as u32;
642 Ok(TypeInfo {
643 max_length: Some(max_length),
644 ..Default::default()
645 })
646 }
647
648 TypeId::Decimal | TypeId::Numeric | TypeId::DecimalN | TypeId::NumericN => {
650 if src.remaining() < 3 {
651 return Err(ProtocolError::UnexpectedEof);
652 }
653 let max_length = src.get_u8() as u32;
654 let precision = src.get_u8();
655 let scale = src.get_u8();
656 Ok(TypeInfo {
657 max_length: Some(max_length),
658 precision: Some(precision),
659 scale: Some(scale),
660 ..Default::default()
661 })
662 }
663
664 TypeId::Char | TypeId::VarChar | TypeId::Binary | TypeId::VarBinary => {
666 if src.remaining() < 1 {
667 return Err(ProtocolError::UnexpectedEof);
668 }
669 let max_length = src.get_u8() as u32;
670 Ok(TypeInfo {
671 max_length: Some(max_length),
672 ..Default::default()
673 })
674 }
675
676 TypeId::BigVarChar | TypeId::BigChar => {
678 if src.remaining() < 7 {
679 return Err(ProtocolError::UnexpectedEof);
681 }
682 let max_length = src.get_u16_le() as u32;
683 let collation = Self::decode_collation(src)?;
684 Ok(TypeInfo {
685 max_length: Some(max_length),
686 collation: Some(collation),
687 ..Default::default()
688 })
689 }
690
691 TypeId::BigVarBinary | TypeId::BigBinary => {
693 if src.remaining() < 2 {
694 return Err(ProtocolError::UnexpectedEof);
695 }
696 let max_length = src.get_u16_le() as u32;
697 Ok(TypeInfo {
698 max_length: Some(max_length),
699 ..Default::default()
700 })
701 }
702
703 TypeId::NChar | TypeId::NVarChar => {
705 if src.remaining() < 7 {
706 return Err(ProtocolError::UnexpectedEof);
708 }
709 let max_length = src.get_u16_le() as u32;
710 let collation = Self::decode_collation(src)?;
711 Ok(TypeInfo {
712 max_length: Some(max_length),
713 collation: Some(collation),
714 ..Default::default()
715 })
716 }
717
718 TypeId::Date => Ok(TypeInfo::default()),
720
721 TypeId::Time | TypeId::DateTime2 | TypeId::DateTimeOffset => {
723 if src.remaining() < 1 {
724 return Err(ProtocolError::UnexpectedEof);
725 }
726 let scale = src.get_u8();
727 Ok(TypeInfo {
728 scale: Some(scale),
729 ..Default::default()
730 })
731 }
732
733 TypeId::Text | TypeId::NText | TypeId::Image => {
735 if src.remaining() < 4 {
737 return Err(ProtocolError::UnexpectedEof);
738 }
739 let max_length = src.get_u32_le();
740
741 let collation = if type_id == TypeId::Text || type_id == TypeId::NText {
743 if src.remaining() < 5 {
744 return Err(ProtocolError::UnexpectedEof);
745 }
746 Some(Self::decode_collation(src)?)
747 } else {
748 None
749 };
750
751 if src.remaining() < 1 {
754 return Err(ProtocolError::UnexpectedEof);
755 }
756 let num_parts = src.get_u8();
757 for _ in 0..num_parts {
758 let _ = read_us_varchar(src).ok_or(ProtocolError::UnexpectedEof)?;
760 }
761
762 Ok(TypeInfo {
763 max_length: Some(max_length),
764 collation,
765 ..Default::default()
766 })
767 }
768
769 TypeId::Xml => {
771 if src.remaining() < 1 {
772 return Err(ProtocolError::UnexpectedEof);
773 }
774 let schema_present = src.get_u8();
775
776 if schema_present != 0 {
777 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)?; }
782
783 Ok(TypeInfo::default())
784 }
785
786 TypeId::Udt => {
788 if src.remaining() < 2 {
790 return Err(ProtocolError::UnexpectedEof);
791 }
792 let max_length = src.get_u16_le() as u32;
793
794 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 {
801 max_length: Some(max_length),
802 ..Default::default()
803 })
804 }
805
806 TypeId::Tvp => {
808 Err(ProtocolError::InvalidTokenType(col_type))
811 }
812
813 TypeId::Variant => {
815 if src.remaining() < 4 {
816 return Err(ProtocolError::UnexpectedEof);
817 }
818 let max_length = src.get_u32_le();
819 Ok(TypeInfo {
820 max_length: Some(max_length),
821 ..Default::default()
822 })
823 }
824 }
825 }
826
827 fn decode_collation(src: &mut impl Buf) -> Result<Collation, ProtocolError> {
829 if src.remaining() < 5 {
830 return Err(ProtocolError::UnexpectedEof);
831 }
832 let lcid = src.get_u32_le();
834 let sort_id = src.get_u8();
835 Ok(Collation { lcid, sort_id })
836 }
837
838 #[must_use]
840 pub fn column_count(&self) -> usize {
841 self.columns.len()
842 }
843
844 #[must_use]
846 pub fn is_empty(&self) -> bool {
847 self.columns.is_empty()
848 }
849}
850
851impl ColumnData {
852 #[must_use]
854 pub fn is_nullable(&self) -> bool {
855 (self.flags & 0x0001) != 0
856 }
857
858 #[must_use]
862 pub fn fixed_size(&self) -> Option<usize> {
863 match self.type_id {
864 TypeId::Null => Some(0),
865 TypeId::Int1 | TypeId::Bit => Some(1),
866 TypeId::Int2 => Some(2),
867 TypeId::Int4 => Some(4),
868 TypeId::Int8 => Some(8),
869 TypeId::Float4 => Some(4),
870 TypeId::Float8 => Some(8),
871 TypeId::Money => Some(8),
872 TypeId::Money4 => Some(4),
873 TypeId::DateTime => Some(8),
874 TypeId::DateTime4 => Some(4),
875 TypeId::Date => Some(3),
876 _ => None,
877 }
878 }
879}
880
881impl RawRow {
886 pub fn decode(src: &mut impl Buf, metadata: &ColMetaData) -> Result<Self, ProtocolError> {
891 let mut data = bytes::BytesMut::new();
892
893 for col in &metadata.columns {
894 Self::decode_column_value(src, col, &mut data)?;
895 }
896
897 Ok(Self {
898 data: data.freeze(),
899 })
900 }
901
902 fn decode_column_value(
904 src: &mut impl Buf,
905 col: &ColumnData,
906 dst: &mut bytes::BytesMut,
907 ) -> Result<(), ProtocolError> {
908 match col.type_id {
909 TypeId::Null => {
911 }
913 TypeId::Int1 | TypeId::Bit => {
914 if src.remaining() < 1 {
915 return Err(ProtocolError::UnexpectedEof);
916 }
917 dst.extend_from_slice(&[src.get_u8()]);
918 }
919 TypeId::Int2 => {
920 if src.remaining() < 2 {
921 return Err(ProtocolError::UnexpectedEof);
922 }
923 dst.extend_from_slice(&src.get_u16_le().to_le_bytes());
924 }
925 TypeId::Int4 => {
926 if src.remaining() < 4 {
927 return Err(ProtocolError::UnexpectedEof);
928 }
929 dst.extend_from_slice(&src.get_u32_le().to_le_bytes());
930 }
931 TypeId::Int8 => {
932 if src.remaining() < 8 {
933 return Err(ProtocolError::UnexpectedEof);
934 }
935 dst.extend_from_slice(&src.get_u64_le().to_le_bytes());
936 }
937 TypeId::Float4 => {
938 if src.remaining() < 4 {
939 return Err(ProtocolError::UnexpectedEof);
940 }
941 dst.extend_from_slice(&src.get_u32_le().to_le_bytes());
942 }
943 TypeId::Float8 => {
944 if src.remaining() < 8 {
945 return Err(ProtocolError::UnexpectedEof);
946 }
947 dst.extend_from_slice(&src.get_u64_le().to_le_bytes());
948 }
949 TypeId::Money => {
950 if src.remaining() < 8 {
951 return Err(ProtocolError::UnexpectedEof);
952 }
953 let hi = src.get_u32_le();
954 let lo = src.get_u32_le();
955 dst.extend_from_slice(&hi.to_le_bytes());
956 dst.extend_from_slice(&lo.to_le_bytes());
957 }
958 TypeId::Money4 => {
959 if src.remaining() < 4 {
960 return Err(ProtocolError::UnexpectedEof);
961 }
962 dst.extend_from_slice(&src.get_u32_le().to_le_bytes());
963 }
964 TypeId::DateTime => {
965 if src.remaining() < 8 {
966 return Err(ProtocolError::UnexpectedEof);
967 }
968 let days = src.get_u32_le();
969 let time = src.get_u32_le();
970 dst.extend_from_slice(&days.to_le_bytes());
971 dst.extend_from_slice(&time.to_le_bytes());
972 }
973 TypeId::DateTime4 => {
974 if src.remaining() < 4 {
975 return Err(ProtocolError::UnexpectedEof);
976 }
977 dst.extend_from_slice(&src.get_u32_le().to_le_bytes());
978 }
979 TypeId::Date => {
981 Self::decode_bytelen_type(src, dst)?;
982 }
983
984 TypeId::IntN | TypeId::BitN | TypeId::FloatN | TypeId::MoneyN | TypeId::DateTimeN => {
986 Self::decode_bytelen_type(src, dst)?;
987 }
988
989 TypeId::Guid => {
990 Self::decode_bytelen_type(src, dst)?;
991 }
992
993 TypeId::Decimal | TypeId::Numeric | TypeId::DecimalN | TypeId::NumericN => {
994 Self::decode_bytelen_type(src, dst)?;
995 }
996
997 TypeId::Char | TypeId::VarChar | TypeId::Binary | TypeId::VarBinary => {
999 Self::decode_bytelen_type(src, dst)?;
1000 }
1001
1002 TypeId::BigVarChar | TypeId::BigVarBinary => {
1004 if col.type_info.max_length == Some(0xFFFF) {
1006 Self::decode_plp_type(src, dst)?;
1007 } else {
1008 Self::decode_ushortlen_type(src, dst)?;
1009 }
1010 }
1011
1012 TypeId::BigChar | TypeId::BigBinary => {
1014 Self::decode_ushortlen_type(src, dst)?;
1015 }
1016
1017 TypeId::NVarChar => {
1019 if col.type_info.max_length == Some(0xFFFF) {
1021 Self::decode_plp_type(src, dst)?;
1022 } else {
1023 Self::decode_ushortlen_type(src, dst)?;
1024 }
1025 }
1026
1027 TypeId::NChar => {
1029 Self::decode_ushortlen_type(src, dst)?;
1030 }
1031
1032 TypeId::Time | TypeId::DateTime2 | TypeId::DateTimeOffset => {
1034 Self::decode_bytelen_type(src, dst)?;
1035 }
1036
1037 TypeId::Text | TypeId::NText | TypeId::Image => {
1039 Self::decode_textptr_type(src, dst)?;
1040 }
1041
1042 TypeId::Xml => {
1044 Self::decode_plp_type(src, dst)?;
1045 }
1046
1047 TypeId::Variant => {
1049 Self::decode_intlen_type(src, dst)?;
1050 }
1051
1052 TypeId::Udt => {
1053 Self::decode_plp_type(src, dst)?;
1055 }
1056
1057 TypeId::Tvp => {
1058 return Err(ProtocolError::InvalidTokenType(col.col_type));
1060 }
1061 }
1062
1063 Ok(())
1064 }
1065
1066 fn decode_bytelen_type(
1068 src: &mut impl Buf,
1069 dst: &mut bytes::BytesMut,
1070 ) -> Result<(), ProtocolError> {
1071 if src.remaining() < 1 {
1072 return Err(ProtocolError::UnexpectedEof);
1073 }
1074 let len = src.get_u8() as usize;
1075 if len == 0xFF {
1076 dst.extend_from_slice(&[0xFF]);
1078 } else if len == 0 {
1079 dst.extend_from_slice(&[0x00]);
1081 } else {
1082 if src.remaining() < len {
1083 return Err(ProtocolError::UnexpectedEof);
1084 }
1085 dst.extend_from_slice(&[len as u8]);
1086 for _ in 0..len {
1087 dst.extend_from_slice(&[src.get_u8()]);
1088 }
1089 }
1090 Ok(())
1091 }
1092
1093 fn decode_ushortlen_type(
1095 src: &mut impl Buf,
1096 dst: &mut bytes::BytesMut,
1097 ) -> Result<(), ProtocolError> {
1098 if src.remaining() < 2 {
1099 return Err(ProtocolError::UnexpectedEof);
1100 }
1101 let len = src.get_u16_le() as usize;
1102 if len == 0xFFFF {
1103 dst.extend_from_slice(&0xFFFFu16.to_le_bytes());
1105 } else if len == 0 {
1106 dst.extend_from_slice(&0u16.to_le_bytes());
1108 } else {
1109 if src.remaining() < len {
1110 return Err(ProtocolError::UnexpectedEof);
1111 }
1112 dst.extend_from_slice(&(len as u16).to_le_bytes());
1113 for _ in 0..len {
1114 dst.extend_from_slice(&[src.get_u8()]);
1115 }
1116 }
1117 Ok(())
1118 }
1119
1120 fn decode_intlen_type(
1122 src: &mut impl Buf,
1123 dst: &mut bytes::BytesMut,
1124 ) -> Result<(), ProtocolError> {
1125 if src.remaining() < 4 {
1126 return Err(ProtocolError::UnexpectedEof);
1127 }
1128 let len = src.get_u32_le() as usize;
1129 if len == 0xFFFFFFFF {
1130 dst.extend_from_slice(&0xFFFFFFFFu32.to_le_bytes());
1132 } else if len == 0 {
1133 dst.extend_from_slice(&0u32.to_le_bytes());
1135 } else {
1136 if src.remaining() < len {
1137 return Err(ProtocolError::UnexpectedEof);
1138 }
1139 dst.extend_from_slice(&(len as u32).to_le_bytes());
1140 for _ in 0..len {
1141 dst.extend_from_slice(&[src.get_u8()]);
1142 }
1143 }
1144 Ok(())
1145 }
1146
1147 fn decode_textptr_type(
1162 src: &mut impl Buf,
1163 dst: &mut bytes::BytesMut,
1164 ) -> Result<(), ProtocolError> {
1165 if src.remaining() < 1 {
1166 return Err(ProtocolError::UnexpectedEof);
1167 }
1168
1169 let textptr_len = src.get_u8() as usize;
1170
1171 if textptr_len == 0 {
1172 dst.extend_from_slice(&0xFFFFFFFFFFFFFFFFu64.to_le_bytes());
1174 return Ok(());
1175 }
1176
1177 if src.remaining() < textptr_len {
1179 return Err(ProtocolError::UnexpectedEof);
1180 }
1181 src.advance(textptr_len);
1182
1183 if src.remaining() < 8 {
1185 return Err(ProtocolError::UnexpectedEof);
1186 }
1187 src.advance(8);
1188
1189 if src.remaining() < 4 {
1191 return Err(ProtocolError::UnexpectedEof);
1192 }
1193 let data_len = src.get_u32_le() as usize;
1194
1195 if src.remaining() < data_len {
1196 return Err(ProtocolError::UnexpectedEof);
1197 }
1198
1199 dst.extend_from_slice(&(data_len as u64).to_le_bytes());
1205 dst.extend_from_slice(&(data_len as u32).to_le_bytes());
1206 for _ in 0..data_len {
1207 dst.extend_from_slice(&[src.get_u8()]);
1208 }
1209 dst.extend_from_slice(&0u32.to_le_bytes()); Ok(())
1212 }
1213
1214 fn decode_plp_type(src: &mut impl Buf, dst: &mut bytes::BytesMut) -> Result<(), ProtocolError> {
1220 if src.remaining() < 8 {
1221 return Err(ProtocolError::UnexpectedEof);
1222 }
1223
1224 let total_len = src.get_u64_le();
1225
1226 dst.extend_from_slice(&total_len.to_le_bytes());
1228
1229 if total_len == 0xFFFFFFFFFFFFFFFF {
1230 return Ok(());
1232 }
1233
1234 loop {
1236 if src.remaining() < 4 {
1237 return Err(ProtocolError::UnexpectedEof);
1238 }
1239 let chunk_len = src.get_u32_le() as usize;
1240 dst.extend_from_slice(&(chunk_len as u32).to_le_bytes());
1241
1242 if chunk_len == 0 {
1243 break;
1245 }
1246
1247 if src.remaining() < chunk_len {
1248 return Err(ProtocolError::UnexpectedEof);
1249 }
1250
1251 for _ in 0..chunk_len {
1252 dst.extend_from_slice(&[src.get_u8()]);
1253 }
1254 }
1255
1256 Ok(())
1257 }
1258}
1259
1260impl NbcRow {
1265 pub fn decode(src: &mut impl Buf, metadata: &ColMetaData) -> Result<Self, ProtocolError> {
1270 let col_count = metadata.columns.len();
1271 let bitmap_len = (col_count + 7) / 8;
1272
1273 if src.remaining() < bitmap_len {
1274 return Err(ProtocolError::UnexpectedEof);
1275 }
1276
1277 let mut null_bitmap = vec![0u8; bitmap_len];
1279 for byte in &mut null_bitmap {
1280 *byte = src.get_u8();
1281 }
1282
1283 let mut data = bytes::BytesMut::new();
1285
1286 for (i, col) in metadata.columns.iter().enumerate() {
1287 let byte_idx = i / 8;
1288 let bit_idx = i % 8;
1289 let is_null = (null_bitmap[byte_idx] & (1 << bit_idx)) != 0;
1290
1291 if !is_null {
1292 RawRow::decode_column_value(src, col, &mut data)?;
1295 }
1296 }
1297
1298 Ok(Self {
1299 null_bitmap,
1300 data: data.freeze(),
1301 })
1302 }
1303
1304 #[must_use]
1306 pub fn is_null(&self, column_index: usize) -> bool {
1307 let byte_idx = column_index / 8;
1308 let bit_idx = column_index % 8;
1309 if byte_idx < self.null_bitmap.len() {
1310 (self.null_bitmap[byte_idx] & (1 << bit_idx)) != 0
1311 } else {
1312 true }
1314 }
1315}
1316
1317impl ReturnValue {
1322 pub fn decode(src: &mut impl Buf) -> Result<Self, ProtocolError> {
1324 if src.remaining() < 2 {
1326 return Err(ProtocolError::UnexpectedEof);
1327 }
1328 let _length = src.get_u16_le();
1329
1330 if src.remaining() < 2 {
1332 return Err(ProtocolError::UnexpectedEof);
1333 }
1334 let param_ordinal = src.get_u16_le();
1335
1336 let param_name = read_b_varchar(src).ok_or(ProtocolError::UnexpectedEof)?;
1338
1339 if src.remaining() < 1 {
1341 return Err(ProtocolError::UnexpectedEof);
1342 }
1343 let status = src.get_u8();
1344
1345 if src.remaining() < 7 {
1347 return Err(ProtocolError::UnexpectedEof);
1348 }
1349 let user_type = src.get_u32_le();
1350 let flags = src.get_u16_le();
1351 let col_type = src.get_u8();
1352
1353 let type_id = TypeId::from_u8(col_type).unwrap_or(TypeId::Null);
1354
1355 let type_info = ColMetaData::decode_type_info(src, type_id, col_type)?;
1357
1358 let mut value_buf = bytes::BytesMut::new();
1360
1361 let temp_col = ColumnData {
1363 name: String::new(),
1364 type_id,
1365 col_type,
1366 flags,
1367 user_type,
1368 type_info: type_info.clone(),
1369 };
1370
1371 RawRow::decode_column_value(src, &temp_col, &mut value_buf)?;
1372
1373 Ok(Self {
1374 param_ordinal,
1375 param_name,
1376 status,
1377 user_type,
1378 flags,
1379 type_info,
1380 value: value_buf.freeze(),
1381 })
1382 }
1383}
1384
1385impl SessionState {
1390 pub fn decode(src: &mut impl Buf) -> Result<Self, ProtocolError> {
1392 if src.remaining() < 4 {
1393 return Err(ProtocolError::UnexpectedEof);
1394 }
1395
1396 let length = src.get_u32_le() as usize;
1397
1398 if src.remaining() < length {
1399 return Err(ProtocolError::IncompletePacket {
1400 expected: length,
1401 actual: src.remaining(),
1402 });
1403 }
1404
1405 let data = src.copy_to_bytes(length);
1406
1407 Ok(Self { data })
1408 }
1409}
1410
1411mod done_status_bits {
1417 pub const DONE_MORE: u16 = 0x0001;
1418 pub const DONE_ERROR: u16 = 0x0002;
1419 pub const DONE_INXACT: u16 = 0x0004;
1420 pub const DONE_COUNT: u16 = 0x0010;
1421 pub const DONE_ATTN: u16 = 0x0020;
1422 pub const DONE_SRVERROR: u16 = 0x0100;
1423}
1424
1425impl DoneStatus {
1426 #[must_use]
1428 pub fn from_bits(bits: u16) -> Self {
1429 use done_status_bits::*;
1430 Self {
1431 more: (bits & DONE_MORE) != 0,
1432 error: (bits & DONE_ERROR) != 0,
1433 in_xact: (bits & DONE_INXACT) != 0,
1434 count: (bits & DONE_COUNT) != 0,
1435 attn: (bits & DONE_ATTN) != 0,
1436 srverror: (bits & DONE_SRVERROR) != 0,
1437 }
1438 }
1439
1440 #[must_use]
1442 pub fn to_bits(&self) -> u16 {
1443 use done_status_bits::*;
1444 let mut bits = 0u16;
1445 if self.more {
1446 bits |= DONE_MORE;
1447 }
1448 if self.error {
1449 bits |= DONE_ERROR;
1450 }
1451 if self.in_xact {
1452 bits |= DONE_INXACT;
1453 }
1454 if self.count {
1455 bits |= DONE_COUNT;
1456 }
1457 if self.attn {
1458 bits |= DONE_ATTN;
1459 }
1460 if self.srverror {
1461 bits |= DONE_SRVERROR;
1462 }
1463 bits
1464 }
1465}
1466
1467impl Done {
1468 pub const SIZE: usize = 12; pub fn decode(src: &mut impl Buf) -> Result<Self, ProtocolError> {
1473 if src.remaining() < Self::SIZE {
1474 return Err(ProtocolError::IncompletePacket {
1475 expected: Self::SIZE,
1476 actual: src.remaining(),
1477 });
1478 }
1479
1480 let status = DoneStatus::from_bits(src.get_u16_le());
1481 let cur_cmd = src.get_u16_le();
1482 let row_count = src.get_u64_le();
1483
1484 Ok(Self {
1485 status,
1486 cur_cmd,
1487 row_count,
1488 })
1489 }
1490
1491 pub fn encode(&self, dst: &mut impl BufMut) {
1493 dst.put_u8(TokenType::Done as u8);
1494 dst.put_u16_le(self.status.to_bits());
1495 dst.put_u16_le(self.cur_cmd);
1496 dst.put_u64_le(self.row_count);
1497 }
1498
1499 #[must_use]
1501 pub const fn has_more(&self) -> bool {
1502 self.status.more
1503 }
1504
1505 #[must_use]
1507 pub const fn has_error(&self) -> bool {
1508 self.status.error
1509 }
1510
1511 #[must_use]
1513 pub const fn has_count(&self) -> bool {
1514 self.status.count
1515 }
1516}
1517
1518impl DoneProc {
1519 pub const SIZE: usize = 12;
1521
1522 pub fn decode(src: &mut impl Buf) -> Result<Self, ProtocolError> {
1524 if src.remaining() < Self::SIZE {
1525 return Err(ProtocolError::IncompletePacket {
1526 expected: Self::SIZE,
1527 actual: src.remaining(),
1528 });
1529 }
1530
1531 let status = DoneStatus::from_bits(src.get_u16_le());
1532 let cur_cmd = src.get_u16_le();
1533 let row_count = src.get_u64_le();
1534
1535 Ok(Self {
1536 status,
1537 cur_cmd,
1538 row_count,
1539 })
1540 }
1541
1542 pub fn encode(&self, dst: &mut impl BufMut) {
1544 dst.put_u8(TokenType::DoneProc as u8);
1545 dst.put_u16_le(self.status.to_bits());
1546 dst.put_u16_le(self.cur_cmd);
1547 dst.put_u64_le(self.row_count);
1548 }
1549}
1550
1551impl DoneInProc {
1552 pub const SIZE: usize = 12;
1554
1555 pub fn decode(src: &mut impl Buf) -> Result<Self, ProtocolError> {
1557 if src.remaining() < Self::SIZE {
1558 return Err(ProtocolError::IncompletePacket {
1559 expected: Self::SIZE,
1560 actual: src.remaining(),
1561 });
1562 }
1563
1564 let status = DoneStatus::from_bits(src.get_u16_le());
1565 let cur_cmd = src.get_u16_le();
1566 let row_count = src.get_u64_le();
1567
1568 Ok(Self {
1569 status,
1570 cur_cmd,
1571 row_count,
1572 })
1573 }
1574
1575 pub fn encode(&self, dst: &mut impl BufMut) {
1577 dst.put_u8(TokenType::DoneInProc as u8);
1578 dst.put_u16_le(self.status.to_bits());
1579 dst.put_u16_le(self.cur_cmd);
1580 dst.put_u64_le(self.row_count);
1581 }
1582}
1583
1584impl ServerError {
1585 pub fn decode(src: &mut impl Buf) -> Result<Self, ProtocolError> {
1587 if src.remaining() < 2 {
1590 return Err(ProtocolError::UnexpectedEof);
1591 }
1592
1593 let _length = src.get_u16_le();
1594
1595 if src.remaining() < 6 {
1596 return Err(ProtocolError::UnexpectedEof);
1597 }
1598
1599 let number = src.get_i32_le();
1600 let state = src.get_u8();
1601 let class = src.get_u8();
1602
1603 let message = read_us_varchar(src).ok_or(ProtocolError::UnexpectedEof)?;
1604 let server = read_b_varchar(src).ok_or(ProtocolError::UnexpectedEof)?;
1605 let procedure = read_b_varchar(src).ok_or(ProtocolError::UnexpectedEof)?;
1606
1607 if src.remaining() < 4 {
1608 return Err(ProtocolError::UnexpectedEof);
1609 }
1610 let line = src.get_i32_le();
1611
1612 Ok(Self {
1613 number,
1614 state,
1615 class,
1616 message,
1617 server,
1618 procedure,
1619 line,
1620 })
1621 }
1622
1623 #[must_use]
1625 pub const fn is_fatal(&self) -> bool {
1626 self.class >= 20
1627 }
1628
1629 #[must_use]
1631 pub const fn is_batch_abort(&self) -> bool {
1632 self.class >= 16
1633 }
1634}
1635
1636impl ServerInfo {
1637 pub fn decode(src: &mut impl Buf) -> Result<Self, ProtocolError> {
1641 if src.remaining() < 2 {
1642 return Err(ProtocolError::UnexpectedEof);
1643 }
1644
1645 let _length = src.get_u16_le();
1646
1647 if src.remaining() < 6 {
1648 return Err(ProtocolError::UnexpectedEof);
1649 }
1650
1651 let number = src.get_i32_le();
1652 let state = src.get_u8();
1653 let class = src.get_u8();
1654
1655 let message = read_us_varchar(src).ok_or(ProtocolError::UnexpectedEof)?;
1656 let server = read_b_varchar(src).ok_or(ProtocolError::UnexpectedEof)?;
1657 let procedure = read_b_varchar(src).ok_or(ProtocolError::UnexpectedEof)?;
1658
1659 if src.remaining() < 4 {
1660 return Err(ProtocolError::UnexpectedEof);
1661 }
1662 let line = src.get_i32_le();
1663
1664 Ok(Self {
1665 number,
1666 state,
1667 class,
1668 message,
1669 server,
1670 procedure,
1671 line,
1672 })
1673 }
1674}
1675
1676impl LoginAck {
1677 pub fn decode(src: &mut impl Buf) -> Result<Self, ProtocolError> {
1679 if src.remaining() < 2 {
1681 return Err(ProtocolError::UnexpectedEof);
1682 }
1683
1684 let _length = src.get_u16_le();
1685
1686 if src.remaining() < 5 {
1687 return Err(ProtocolError::UnexpectedEof);
1688 }
1689
1690 let interface = src.get_u8();
1691 let tds_version = src.get_u32_le();
1692 let prog_name = read_b_varchar(src).ok_or(ProtocolError::UnexpectedEof)?;
1693
1694 if src.remaining() < 4 {
1695 return Err(ProtocolError::UnexpectedEof);
1696 }
1697 let prog_version = src.get_u32_le();
1698
1699 Ok(Self {
1700 interface,
1701 tds_version,
1702 prog_name,
1703 prog_version,
1704 })
1705 }
1706
1707 #[must_use]
1709 pub fn tds_version(&self) -> crate::version::TdsVersion {
1710 crate::version::TdsVersion::new(self.tds_version)
1711 }
1712}
1713
1714impl EnvChangeType {
1715 pub fn from_u8(value: u8) -> Option<Self> {
1717 match value {
1718 1 => Some(Self::Database),
1719 2 => Some(Self::Language),
1720 3 => Some(Self::CharacterSet),
1721 4 => Some(Self::PacketSize),
1722 5 => Some(Self::UnicodeSortingLocalId),
1723 6 => Some(Self::UnicodeComparisonFlags),
1724 7 => Some(Self::SqlCollation),
1725 8 => Some(Self::BeginTransaction),
1726 9 => Some(Self::CommitTransaction),
1727 10 => Some(Self::RollbackTransaction),
1728 11 => Some(Self::EnlistDtcTransaction),
1729 12 => Some(Self::DefectTransaction),
1730 13 => Some(Self::RealTimeLogShipping),
1731 15 => Some(Self::PromoteTransaction),
1732 16 => Some(Self::TransactionManagerAddress),
1733 17 => Some(Self::TransactionEnded),
1734 18 => Some(Self::ResetConnectionCompletionAck),
1735 19 => Some(Self::UserInstanceStarted),
1736 20 => Some(Self::Routing),
1737 _ => None,
1738 }
1739 }
1740}
1741
1742impl EnvChange {
1743 pub fn decode(src: &mut impl Buf) -> Result<Self, ProtocolError> {
1745 if src.remaining() < 3 {
1746 return Err(ProtocolError::UnexpectedEof);
1747 }
1748
1749 let length = src.get_u16_le() as usize;
1750 if src.remaining() < length {
1751 return Err(ProtocolError::IncompletePacket {
1752 expected: length,
1753 actual: src.remaining(),
1754 });
1755 }
1756
1757 let env_type_byte = src.get_u8();
1758 let env_type = EnvChangeType::from_u8(env_type_byte)
1759 .ok_or(ProtocolError::InvalidTokenType(env_type_byte))?;
1760
1761 let (new_value, old_value) = match env_type {
1762 EnvChangeType::Routing => {
1763 let new_value = Self::decode_routing_value(src)?;
1765 let old_value = EnvChangeValue::Binary(Bytes::new());
1766 (new_value, old_value)
1767 }
1768 EnvChangeType::BeginTransaction
1769 | EnvChangeType::CommitTransaction
1770 | EnvChangeType::RollbackTransaction
1771 | EnvChangeType::EnlistDtcTransaction
1772 | EnvChangeType::SqlCollation => {
1773 let new_len = src.get_u8() as usize;
1777 let new_value = if new_len > 0 && src.remaining() >= new_len {
1778 EnvChangeValue::Binary(src.copy_to_bytes(new_len))
1779 } else {
1780 EnvChangeValue::Binary(Bytes::new())
1781 };
1782
1783 let old_len = src.get_u8() as usize;
1784 let old_value = if old_len > 0 && src.remaining() >= old_len {
1785 EnvChangeValue::Binary(src.copy_to_bytes(old_len))
1786 } else {
1787 EnvChangeValue::Binary(Bytes::new())
1788 };
1789
1790 (new_value, old_value)
1791 }
1792 _ => {
1793 let new_value = read_b_varchar(src)
1795 .map(EnvChangeValue::String)
1796 .unwrap_or(EnvChangeValue::String(String::new()));
1797
1798 let old_value = read_b_varchar(src)
1799 .map(EnvChangeValue::String)
1800 .unwrap_or(EnvChangeValue::String(String::new()));
1801
1802 (new_value, old_value)
1803 }
1804 };
1805
1806 Ok(Self {
1807 env_type,
1808 new_value,
1809 old_value,
1810 })
1811 }
1812
1813 fn decode_routing_value(src: &mut impl Buf) -> Result<EnvChangeValue, ProtocolError> {
1814 if src.remaining() < 2 {
1816 return Err(ProtocolError::UnexpectedEof);
1817 }
1818
1819 let _routing_len = src.get_u16_le();
1820
1821 if src.remaining() < 5 {
1822 return Err(ProtocolError::UnexpectedEof);
1823 }
1824
1825 let _protocol = src.get_u8();
1826 let port = src.get_u16_le();
1827 let server_len = src.get_u16_le() as usize;
1828
1829 if src.remaining() < server_len * 2 {
1831 return Err(ProtocolError::UnexpectedEof);
1832 }
1833
1834 let mut chars = Vec::with_capacity(server_len);
1835 for _ in 0..server_len {
1836 chars.push(src.get_u16_le());
1837 }
1838
1839 let host = String::from_utf16(&chars).map_err(|_| {
1840 ProtocolError::StringEncoding(
1841 #[cfg(feature = "std")]
1842 "invalid UTF-16 in routing hostname".to_string(),
1843 #[cfg(not(feature = "std"))]
1844 "invalid UTF-16 in routing hostname",
1845 )
1846 })?;
1847
1848 Ok(EnvChangeValue::Routing { host, port })
1849 }
1850
1851 #[must_use]
1853 pub fn is_routing(&self) -> bool {
1854 self.env_type == EnvChangeType::Routing
1855 }
1856
1857 #[must_use]
1859 pub fn routing_info(&self) -> Option<(&str, u16)> {
1860 if let EnvChangeValue::Routing { host, port } = &self.new_value {
1861 Some((host, *port))
1862 } else {
1863 None
1864 }
1865 }
1866
1867 #[must_use]
1869 pub fn new_database(&self) -> Option<&str> {
1870 if self.env_type == EnvChangeType::Database {
1871 if let EnvChangeValue::String(s) = &self.new_value {
1872 return Some(s);
1873 }
1874 }
1875 None
1876 }
1877}
1878
1879impl Order {
1880 pub fn decode(src: &mut impl Buf) -> Result<Self, ProtocolError> {
1882 if src.remaining() < 2 {
1883 return Err(ProtocolError::UnexpectedEof);
1884 }
1885
1886 let length = src.get_u16_le() as usize;
1887 let column_count = length / 2;
1888
1889 if src.remaining() < length {
1890 return Err(ProtocolError::IncompletePacket {
1891 expected: length,
1892 actual: src.remaining(),
1893 });
1894 }
1895
1896 let mut columns = Vec::with_capacity(column_count);
1897 for _ in 0..column_count {
1898 columns.push(src.get_u16_le());
1899 }
1900
1901 Ok(Self { columns })
1902 }
1903}
1904
1905impl FeatureExtAck {
1906 pub const TERMINATOR: u8 = 0xFF;
1908
1909 pub fn decode(src: &mut impl Buf) -> Result<Self, ProtocolError> {
1911 let mut features = Vec::new();
1912
1913 loop {
1914 if !src.has_remaining() {
1915 return Err(ProtocolError::UnexpectedEof);
1916 }
1917
1918 let feature_id = src.get_u8();
1919 if feature_id == Self::TERMINATOR {
1920 break;
1921 }
1922
1923 if src.remaining() < 4 {
1924 return Err(ProtocolError::UnexpectedEof);
1925 }
1926
1927 let data_len = src.get_u32_le() as usize;
1928
1929 if src.remaining() < data_len {
1930 return Err(ProtocolError::IncompletePacket {
1931 expected: data_len,
1932 actual: src.remaining(),
1933 });
1934 }
1935
1936 let data = src.copy_to_bytes(data_len);
1937 features.push(FeatureAck { feature_id, data });
1938 }
1939
1940 Ok(Self { features })
1941 }
1942}
1943
1944impl SspiToken {
1945 pub fn decode(src: &mut impl Buf) -> Result<Self, ProtocolError> {
1947 if src.remaining() < 2 {
1948 return Err(ProtocolError::UnexpectedEof);
1949 }
1950
1951 let length = src.get_u16_le() as usize;
1952
1953 if src.remaining() < length {
1954 return Err(ProtocolError::IncompletePacket {
1955 expected: length,
1956 actual: src.remaining(),
1957 });
1958 }
1959
1960 let data = src.copy_to_bytes(length);
1961 Ok(Self { data })
1962 }
1963}
1964
1965impl FedAuthInfo {
1966 pub fn decode(src: &mut impl Buf) -> Result<Self, ProtocolError> {
1968 if src.remaining() < 4 {
1969 return Err(ProtocolError::UnexpectedEof);
1970 }
1971
1972 let _length = src.get_u32_le();
1973
1974 if src.remaining() < 5 {
1975 return Err(ProtocolError::UnexpectedEof);
1976 }
1977
1978 let _count = src.get_u8();
1979
1980 let mut sts_url = String::new();
1982 let mut spn = String::new();
1983
1984 while src.has_remaining() {
1986 if src.remaining() < 9 {
1987 break;
1988 }
1989
1990 let info_id = src.get_u8();
1991 let info_len = src.get_u32_le() as usize;
1992 let _info_offset = src.get_u32_le();
1993
1994 if src.remaining() < info_len {
1995 break;
1996 }
1997
1998 let char_count = info_len / 2;
2000 let mut chars = Vec::with_capacity(char_count);
2001 for _ in 0..char_count {
2002 chars.push(src.get_u16_le());
2003 }
2004
2005 if let Ok(value) = String::from_utf16(&chars) {
2006 match info_id {
2007 0x01 => spn = value,
2008 0x02 => sts_url = value,
2009 _ => {}
2010 }
2011 }
2012 }
2013
2014 Ok(Self { sts_url, spn })
2015 }
2016}
2017
2018pub struct TokenParser {
2059 data: Bytes,
2060 position: usize,
2061}
2062
2063impl TokenParser {
2064 #[must_use]
2066 pub fn new(data: Bytes) -> Self {
2067 Self { data, position: 0 }
2068 }
2069
2070 #[must_use]
2072 pub fn remaining(&self) -> usize {
2073 self.data.len().saturating_sub(self.position)
2074 }
2075
2076 #[must_use]
2078 pub fn has_remaining(&self) -> bool {
2079 self.position < self.data.len()
2080 }
2081
2082 #[must_use]
2084 pub fn peek_token_type(&self) -> Option<TokenType> {
2085 if self.position < self.data.len() {
2086 TokenType::from_u8(self.data[self.position])
2087 } else {
2088 None
2089 }
2090 }
2091
2092 pub fn next_token(&mut self) -> Result<Option<Token>, ProtocolError> {
2100 self.next_token_with_metadata(None)
2101 }
2102
2103 pub fn next_token_with_metadata(
2110 &mut self,
2111 metadata: Option<&ColMetaData>,
2112 ) -> Result<Option<Token>, ProtocolError> {
2113 if !self.has_remaining() {
2114 return Ok(None);
2115 }
2116
2117 let mut buf = &self.data[self.position..];
2118 let start_pos = self.position;
2119
2120 let token_type_byte = buf.get_u8();
2121 let token_type = TokenType::from_u8(token_type_byte);
2122
2123 let token = match token_type {
2124 Some(TokenType::Done) => {
2125 let done = Done::decode(&mut buf)?;
2126 Token::Done(done)
2127 }
2128 Some(TokenType::DoneProc) => {
2129 let done = DoneProc::decode(&mut buf)?;
2130 Token::DoneProc(done)
2131 }
2132 Some(TokenType::DoneInProc) => {
2133 let done = DoneInProc::decode(&mut buf)?;
2134 Token::DoneInProc(done)
2135 }
2136 Some(TokenType::Error) => {
2137 let error = ServerError::decode(&mut buf)?;
2138 Token::Error(error)
2139 }
2140 Some(TokenType::Info) => {
2141 let info = ServerInfo::decode(&mut buf)?;
2142 Token::Info(info)
2143 }
2144 Some(TokenType::LoginAck) => {
2145 let login_ack = LoginAck::decode(&mut buf)?;
2146 Token::LoginAck(login_ack)
2147 }
2148 Some(TokenType::EnvChange) => {
2149 let env_change = EnvChange::decode(&mut buf)?;
2150 Token::EnvChange(env_change)
2151 }
2152 Some(TokenType::Order) => {
2153 let order = Order::decode(&mut buf)?;
2154 Token::Order(order)
2155 }
2156 Some(TokenType::FeatureExtAck) => {
2157 let ack = FeatureExtAck::decode(&mut buf)?;
2158 Token::FeatureExtAck(ack)
2159 }
2160 Some(TokenType::Sspi) => {
2161 let sspi = SspiToken::decode(&mut buf)?;
2162 Token::Sspi(sspi)
2163 }
2164 Some(TokenType::FedAuthInfo) => {
2165 let info = FedAuthInfo::decode(&mut buf)?;
2166 Token::FedAuthInfo(info)
2167 }
2168 Some(TokenType::ReturnStatus) => {
2169 if buf.remaining() < 4 {
2170 return Err(ProtocolError::UnexpectedEof);
2171 }
2172 let status = buf.get_i32_le();
2173 Token::ReturnStatus(status)
2174 }
2175 Some(TokenType::ColMetaData) => {
2176 let col_meta = ColMetaData::decode(&mut buf)?;
2177 Token::ColMetaData(col_meta)
2178 }
2179 Some(TokenType::Row) => {
2180 let meta = metadata.ok_or_else(|| {
2181 ProtocolError::StringEncoding(
2182 #[cfg(feature = "std")]
2183 "Row token requires column metadata".to_string(),
2184 #[cfg(not(feature = "std"))]
2185 "Row token requires column metadata",
2186 )
2187 })?;
2188 let row = RawRow::decode(&mut buf, meta)?;
2189 Token::Row(row)
2190 }
2191 Some(TokenType::NbcRow) => {
2192 let meta = metadata.ok_or_else(|| {
2193 ProtocolError::StringEncoding(
2194 #[cfg(feature = "std")]
2195 "NbcRow token requires column metadata".to_string(),
2196 #[cfg(not(feature = "std"))]
2197 "NbcRow token requires column metadata",
2198 )
2199 })?;
2200 let row = NbcRow::decode(&mut buf, meta)?;
2201 Token::NbcRow(row)
2202 }
2203 Some(TokenType::ReturnValue) => {
2204 let ret_val = ReturnValue::decode(&mut buf)?;
2205 Token::ReturnValue(ret_val)
2206 }
2207 Some(TokenType::SessionState) => {
2208 let session = SessionState::decode(&mut buf)?;
2209 Token::SessionState(session)
2210 }
2211 Some(TokenType::ColInfo) | Some(TokenType::TabName) | Some(TokenType::Offset) => {
2212 if buf.remaining() < 2 {
2215 return Err(ProtocolError::UnexpectedEof);
2216 }
2217 let length = buf.get_u16_le() as usize;
2218 if buf.remaining() < length {
2219 return Err(ProtocolError::IncompletePacket {
2220 expected: length,
2221 actual: buf.remaining(),
2222 });
2223 }
2224 buf.advance(length);
2226 self.position = start_pos + (self.data.len() - start_pos - buf.remaining());
2228 return self.next_token_with_metadata(metadata);
2229 }
2230 None => {
2231 return Err(ProtocolError::InvalidTokenType(token_type_byte));
2232 }
2233 };
2234
2235 let consumed = self.data.len() - start_pos - buf.remaining();
2237 self.position = start_pos + consumed;
2238
2239 Ok(Some(token))
2240 }
2241
2242 pub fn skip_token(&mut self) -> Result<(), ProtocolError> {
2246 if !self.has_remaining() {
2247 return Ok(());
2248 }
2249
2250 let token_type_byte = self.data[self.position];
2251 let token_type = TokenType::from_u8(token_type_byte);
2252
2253 let skip_amount = match token_type {
2255 Some(TokenType::Done) | Some(TokenType::DoneProc) | Some(TokenType::DoneInProc) => {
2257 1 + Done::SIZE }
2259 Some(TokenType::ReturnStatus) => {
2260 1 + 4 }
2262 Some(TokenType::Error)
2264 | Some(TokenType::Info)
2265 | Some(TokenType::LoginAck)
2266 | Some(TokenType::EnvChange)
2267 | Some(TokenType::Order)
2268 | Some(TokenType::Sspi)
2269 | Some(TokenType::ColInfo)
2270 | Some(TokenType::TabName)
2271 | Some(TokenType::Offset)
2272 | Some(TokenType::ReturnValue) => {
2273 if self.remaining() < 3 {
2274 return Err(ProtocolError::UnexpectedEof);
2275 }
2276 let length = u16::from_le_bytes([
2277 self.data[self.position + 1],
2278 self.data[self.position + 2],
2279 ]) as usize;
2280 1 + 2 + length }
2282 Some(TokenType::SessionState) | Some(TokenType::FedAuthInfo) => {
2284 if self.remaining() < 5 {
2285 return Err(ProtocolError::UnexpectedEof);
2286 }
2287 let length = u32::from_le_bytes([
2288 self.data[self.position + 1],
2289 self.data[self.position + 2],
2290 self.data[self.position + 3],
2291 self.data[self.position + 4],
2292 ]) as usize;
2293 1 + 4 + length
2294 }
2295 Some(TokenType::FeatureExtAck) => {
2297 let mut buf = &self.data[self.position + 1..];
2299 let _ = FeatureExtAck::decode(&mut buf)?;
2300 self.data.len() - self.position - buf.remaining()
2301 }
2302 Some(TokenType::ColMetaData) | Some(TokenType::Row) | Some(TokenType::NbcRow) => {
2304 return Err(ProtocolError::InvalidTokenType(token_type_byte));
2305 }
2306 None => {
2307 return Err(ProtocolError::InvalidTokenType(token_type_byte));
2308 }
2309 };
2310
2311 if self.remaining() < skip_amount {
2312 return Err(ProtocolError::UnexpectedEof);
2313 }
2314
2315 self.position += skip_amount;
2316 Ok(())
2317 }
2318
2319 #[must_use]
2321 pub fn position(&self) -> usize {
2322 self.position
2323 }
2324
2325 pub fn reset(&mut self) {
2327 self.position = 0;
2328 }
2329}
2330
2331#[cfg(not(feature = "std"))]
2336use alloc::string::String;
2337#[cfg(not(feature = "std"))]
2338use alloc::vec::Vec;
2339
2340#[cfg(test)]
2345#[allow(clippy::unwrap_used, clippy::panic)]
2346mod tests {
2347 use super::*;
2348 use bytes::BytesMut;
2349
2350 #[test]
2351 fn test_done_roundtrip() {
2352 let done = Done {
2353 status: DoneStatus {
2354 more: false,
2355 error: false,
2356 in_xact: false,
2357 count: true,
2358 attn: false,
2359 srverror: false,
2360 },
2361 cur_cmd: 193, row_count: 42,
2363 };
2364
2365 let mut buf = BytesMut::new();
2366 done.encode(&mut buf);
2367
2368 let mut cursor = &buf[1..];
2370 let decoded = Done::decode(&mut cursor).unwrap();
2371
2372 assert_eq!(decoded.status.count, done.status.count);
2373 assert_eq!(decoded.cur_cmd, done.cur_cmd);
2374 assert_eq!(decoded.row_count, done.row_count);
2375 }
2376
2377 #[test]
2378 fn test_done_status_bits() {
2379 let status = DoneStatus {
2380 more: true,
2381 error: true,
2382 in_xact: true,
2383 count: true,
2384 attn: false,
2385 srverror: false,
2386 };
2387
2388 let bits = status.to_bits();
2389 let restored = DoneStatus::from_bits(bits);
2390
2391 assert_eq!(status.more, restored.more);
2392 assert_eq!(status.error, restored.error);
2393 assert_eq!(status.in_xact, restored.in_xact);
2394 assert_eq!(status.count, restored.count);
2395 }
2396
2397 #[test]
2398 fn test_token_parser_done() {
2399 let data = Bytes::from_static(&[
2401 0xFD, 0x10, 0x00, 0xC1, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ]);
2406
2407 let mut parser = TokenParser::new(data);
2408 let token = parser.next_token().unwrap().unwrap();
2409
2410 match token {
2411 Token::Done(done) => {
2412 assert!(done.status.count);
2413 assert!(!done.status.more);
2414 assert_eq!(done.cur_cmd, 193);
2415 assert_eq!(done.row_count, 5);
2416 }
2417 _ => panic!("Expected Done token"),
2418 }
2419
2420 assert!(parser.next_token().unwrap().is_none());
2422 }
2423
2424 #[test]
2425 fn test_env_change_type_from_u8() {
2426 assert_eq!(EnvChangeType::from_u8(1), Some(EnvChangeType::Database));
2427 assert_eq!(EnvChangeType::from_u8(20), Some(EnvChangeType::Routing));
2428 assert_eq!(EnvChangeType::from_u8(100), None);
2429 }
2430
2431 #[test]
2432 fn test_colmetadata_no_columns() {
2433 let data = Bytes::from_static(&[0xFF, 0xFF]);
2435 let mut cursor: &[u8] = &data;
2436 let meta = ColMetaData::decode(&mut cursor).unwrap();
2437 assert!(meta.is_empty());
2438 assert_eq!(meta.column_count(), 0);
2439 }
2440
2441 #[test]
2442 fn test_colmetadata_single_int_column() {
2443 let mut data = BytesMut::new();
2446 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;
2455 let meta = ColMetaData::decode(&mut cursor).unwrap();
2456
2457 assert_eq!(meta.column_count(), 1);
2458 assert_eq!(meta.columns[0].name, "id");
2459 assert_eq!(meta.columns[0].type_id, TypeId::Int4);
2460 assert!(meta.columns[0].is_nullable());
2461 }
2462
2463 #[test]
2464 fn test_colmetadata_nvarchar_column() {
2465 let mut data = BytesMut::new();
2467 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]);
2477
2478 let mut cursor: &[u8] = &data;
2479 let meta = ColMetaData::decode(&mut cursor).unwrap();
2480
2481 assert_eq!(meta.column_count(), 1);
2482 assert_eq!(meta.columns[0].name, "name");
2483 assert_eq!(meta.columns[0].type_id, TypeId::NVarChar);
2484 assert_eq!(meta.columns[0].type_info.max_length, Some(100));
2485 assert!(meta.columns[0].type_info.collation.is_some());
2486 }
2487
2488 #[test]
2489 fn test_raw_row_decode_int() {
2490 let metadata = ColMetaData {
2492 columns: vec![ColumnData {
2493 name: "id".to_string(),
2494 type_id: TypeId::Int4,
2495 col_type: 0x38,
2496 flags: 0,
2497 user_type: 0,
2498 type_info: TypeInfo::default(),
2499 }],
2500 };
2501
2502 let data = Bytes::from_static(&[0x2A, 0x00, 0x00, 0x00]); let mut cursor: &[u8] = &data;
2505 let row = RawRow::decode(&mut cursor, &metadata).unwrap();
2506
2507 assert_eq!(row.data.len(), 4);
2509 assert_eq!(&row.data[..], &[0x2A, 0x00, 0x00, 0x00]);
2510 }
2511
2512 #[test]
2513 fn test_raw_row_decode_nullable_int() {
2514 let metadata = ColMetaData {
2516 columns: vec![ColumnData {
2517 name: "id".to_string(),
2518 type_id: TypeId::IntN,
2519 col_type: 0x26,
2520 flags: 0x01, user_type: 0,
2522 type_info: TypeInfo {
2523 max_length: Some(4),
2524 ..Default::default()
2525 },
2526 }],
2527 };
2528
2529 let data = Bytes::from_static(&[0x04, 0x2A, 0x00, 0x00, 0x00]); let mut cursor: &[u8] = &data;
2532 let row = RawRow::decode(&mut cursor, &metadata).unwrap();
2533
2534 assert_eq!(row.data.len(), 5);
2535 assert_eq!(row.data[0], 4); assert_eq!(&row.data[1..], &[0x2A, 0x00, 0x00, 0x00]);
2537 }
2538
2539 #[test]
2540 fn test_raw_row_decode_null_value() {
2541 let metadata = ColMetaData {
2543 columns: vec![ColumnData {
2544 name: "id".to_string(),
2545 type_id: TypeId::IntN,
2546 col_type: 0x26,
2547 flags: 0x01, user_type: 0,
2549 type_info: TypeInfo {
2550 max_length: Some(4),
2551 ..Default::default()
2552 },
2553 }],
2554 };
2555
2556 let data = Bytes::from_static(&[0xFF]);
2558 let mut cursor: &[u8] = &data;
2559 let row = RawRow::decode(&mut cursor, &metadata).unwrap();
2560
2561 assert_eq!(row.data.len(), 1);
2562 assert_eq!(row.data[0], 0xFF); }
2564
2565 #[test]
2566 fn test_nbcrow_null_bitmap() {
2567 let row = NbcRow {
2568 null_bitmap: vec![0b00000101], data: Bytes::new(),
2570 };
2571
2572 assert!(row.is_null(0));
2573 assert!(!row.is_null(1));
2574 assert!(row.is_null(2));
2575 assert!(!row.is_null(3));
2576 }
2577
2578 #[test]
2579 fn test_token_parser_colmetadata() {
2580 let mut data = BytesMut::new();
2582 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());
2591 let token = parser.next_token().unwrap().unwrap();
2592
2593 match token {
2594 Token::ColMetaData(meta) => {
2595 assert_eq!(meta.column_count(), 1);
2596 assert_eq!(meta.columns[0].name, "id");
2597 assert_eq!(meta.columns[0].type_id, TypeId::Int4);
2598 }
2599 _ => panic!("Expected ColMetaData token"),
2600 }
2601 }
2602
2603 #[test]
2604 fn test_token_parser_row_with_metadata() {
2605 let metadata = ColMetaData {
2607 columns: vec![ColumnData {
2608 name: "id".to_string(),
2609 type_id: TypeId::Int4,
2610 col_type: 0x38,
2611 flags: 0,
2612 user_type: 0,
2613 type_info: TypeInfo::default(),
2614 }],
2615 };
2616
2617 let mut data = BytesMut::new();
2619 data.extend_from_slice(&[0xD1]); data.extend_from_slice(&[0x2A, 0x00, 0x00, 0x00]); let mut parser = TokenParser::new(data.freeze());
2623 let token = parser
2624 .next_token_with_metadata(Some(&metadata))
2625 .unwrap()
2626 .unwrap();
2627
2628 match token {
2629 Token::Row(row) => {
2630 assert_eq!(row.data.len(), 4);
2631 }
2632 _ => panic!("Expected Row token"),
2633 }
2634 }
2635
2636 #[test]
2637 fn test_token_parser_row_without_metadata_fails() {
2638 let mut data = BytesMut::new();
2640 data.extend_from_slice(&[0xD1]); data.extend_from_slice(&[0x2A, 0x00, 0x00, 0x00]); let mut parser = TokenParser::new(data.freeze());
2644 let result = parser.next_token(); assert!(result.is_err());
2647 }
2648
2649 #[test]
2650 fn test_token_parser_peek() {
2651 let data = Bytes::from_static(&[
2652 0xFD, 0x10, 0x00, 0xC1, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ]);
2657
2658 let parser = TokenParser::new(data);
2659 assert_eq!(parser.peek_token_type(), Some(TokenType::Done));
2660 }
2661
2662 #[test]
2663 fn test_column_data_fixed_size() {
2664 let col = ColumnData {
2665 name: String::new(),
2666 type_id: TypeId::Int4,
2667 col_type: 0x38,
2668 flags: 0,
2669 user_type: 0,
2670 type_info: TypeInfo::default(),
2671 };
2672 assert_eq!(col.fixed_size(), Some(4));
2673
2674 let col2 = ColumnData {
2675 name: String::new(),
2676 type_id: TypeId::NVarChar,
2677 col_type: 0xE7,
2678 flags: 0,
2679 user_type: 0,
2680 type_info: TypeInfo::default(),
2681 };
2682 assert_eq!(col2.fixed_size(), None);
2683 }
2684
2685 #[test]
2693 fn test_decode_nvarchar_then_intn_roundtrip() {
2694 let mut wire_data = BytesMut::new();
2699
2700 let word = "World";
2703 let utf16: Vec<u16> = word.encode_utf16().collect();
2704 wire_data.put_u16_le((utf16.len() * 2) as u16); for code_unit in &utf16 {
2706 wire_data.put_u16_le(*code_unit);
2707 }
2708
2709 wire_data.put_u8(4); wire_data.put_i32_le(42);
2712
2713 let metadata = ColMetaData {
2715 columns: vec![
2716 ColumnData {
2717 name: "greeting".to_string(),
2718 type_id: TypeId::NVarChar,
2719 col_type: 0xE7,
2720 flags: 0x01,
2721 user_type: 0,
2722 type_info: TypeInfo {
2723 max_length: Some(10), precision: None,
2725 scale: None,
2726 collation: None,
2727 },
2728 },
2729 ColumnData {
2730 name: "number".to_string(),
2731 type_id: TypeId::IntN,
2732 col_type: 0x26,
2733 flags: 0x01,
2734 user_type: 0,
2735 type_info: TypeInfo {
2736 max_length: Some(4),
2737 precision: None,
2738 scale: None,
2739 collation: None,
2740 },
2741 },
2742 ],
2743 };
2744
2745 let mut wire_cursor = wire_data.freeze();
2747 let raw_row = RawRow::decode(&mut wire_cursor, &metadata).unwrap();
2748
2749 assert_eq!(
2751 wire_cursor.remaining(),
2752 0,
2753 "wire data should be fully consumed"
2754 );
2755
2756 let mut stored_cursor: &[u8] = &raw_row.data;
2758
2759 assert!(
2762 stored_cursor.remaining() >= 2,
2763 "need at least 2 bytes for length"
2764 );
2765 let len0 = stored_cursor.get_u16_le() as usize;
2766 assert_eq!(len0, 10, "NVarChar length should be 10 bytes");
2767 assert!(
2768 stored_cursor.remaining() >= len0,
2769 "need {len0} bytes for data"
2770 );
2771
2772 let mut utf16_read = Vec::new();
2774 for _ in 0..(len0 / 2) {
2775 utf16_read.push(stored_cursor.get_u16_le());
2776 }
2777 let string0 = String::from_utf16(&utf16_read).unwrap();
2778 assert_eq!(string0, "World", "column 0 should be 'World'");
2779
2780 assert!(
2783 stored_cursor.remaining() >= 1,
2784 "need at least 1 byte for length"
2785 );
2786 let len1 = stored_cursor.get_u8();
2787 assert_eq!(len1, 4, "IntN length should be 4");
2788 assert!(stored_cursor.remaining() >= 4, "need 4 bytes for INT data");
2789 let int1 = stored_cursor.get_i32_le();
2790 assert_eq!(int1, 42, "column 1 should be 42");
2791
2792 assert_eq!(
2794 stored_cursor.remaining(),
2795 0,
2796 "stored data should be fully consumed"
2797 );
2798 }
2799
2800 #[test]
2801 fn test_decode_nvarchar_max_then_intn_roundtrip() {
2802 let mut wire_data = BytesMut::new();
2806
2807 let word = "Hello";
2810 let utf16: Vec<u16> = word.encode_utf16().collect();
2811 let byte_len = (utf16.len() * 2) as u64;
2812
2813 wire_data.put_u64_le(byte_len); wire_data.put_u32_le(byte_len as u32); for code_unit in &utf16 {
2816 wire_data.put_u16_le(*code_unit);
2817 }
2818 wire_data.put_u32_le(0); wire_data.put_u8(4);
2822 wire_data.put_i32_le(99);
2823
2824 let metadata = ColMetaData {
2826 columns: vec![
2827 ColumnData {
2828 name: "text".to_string(),
2829 type_id: TypeId::NVarChar,
2830 col_type: 0xE7,
2831 flags: 0x01,
2832 user_type: 0,
2833 type_info: TypeInfo {
2834 max_length: Some(0xFFFF), precision: None,
2836 scale: None,
2837 collation: None,
2838 },
2839 },
2840 ColumnData {
2841 name: "num".to_string(),
2842 type_id: TypeId::IntN,
2843 col_type: 0x26,
2844 flags: 0x01,
2845 user_type: 0,
2846 type_info: TypeInfo {
2847 max_length: Some(4),
2848 precision: None,
2849 scale: None,
2850 collation: None,
2851 },
2852 },
2853 ],
2854 };
2855
2856 let mut wire_cursor = wire_data.freeze();
2858 let raw_row = RawRow::decode(&mut wire_cursor, &metadata).unwrap();
2859
2860 assert_eq!(
2862 wire_cursor.remaining(),
2863 0,
2864 "wire data should be fully consumed"
2865 );
2866
2867 let mut stored_cursor: &[u8] = &raw_row.data;
2869
2870 let total_len = stored_cursor.get_u64_le();
2872 assert_eq!(total_len, 10, "PLP total length should be 10");
2873
2874 let chunk_len = stored_cursor.get_u32_le();
2875 assert_eq!(chunk_len, 10, "PLP chunk length should be 10");
2876
2877 let mut utf16_read = Vec::new();
2878 for _ in 0..(chunk_len / 2) {
2879 utf16_read.push(stored_cursor.get_u16_le());
2880 }
2881 let string0 = String::from_utf16(&utf16_read).unwrap();
2882 assert_eq!(string0, "Hello", "column 0 should be 'Hello'");
2883
2884 let terminator = stored_cursor.get_u32_le();
2885 assert_eq!(terminator, 0, "PLP should end with 0");
2886
2887 let len1 = stored_cursor.get_u8();
2889 assert_eq!(len1, 4);
2890 let int1 = stored_cursor.get_i32_le();
2891 assert_eq!(int1, 99, "column 1 should be 99");
2892
2893 assert_eq!(
2895 stored_cursor.remaining(),
2896 0,
2897 "stored data should be fully consumed"
2898 );
2899 }
2900}