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)]
192pub struct Collation {
193 pub lcid: u32,
195 pub sort_id: u8,
197}
198
199#[derive(Debug, Clone)]
201pub struct RawRow {
202 pub data: bytes::Bytes,
204}
205
206#[derive(Debug, Clone)]
208pub struct NbcRow {
209 pub null_bitmap: Vec<u8>,
211 pub data: bytes::Bytes,
213}
214
215#[derive(Debug, Clone, Copy)]
217pub struct Done {
218 pub status: DoneStatus,
220 pub cur_cmd: u16,
222 pub row_count: u64,
224}
225
226#[derive(Debug, Clone, Copy, Default)]
228pub struct DoneStatus {
229 pub more: bool,
231 pub error: bool,
233 pub in_xact: bool,
235 pub count: bool,
237 pub attn: bool,
239 pub srverror: bool,
241}
242
243#[derive(Debug, Clone, Copy)]
245pub struct DoneInProc {
246 pub status: DoneStatus,
248 pub cur_cmd: u16,
250 pub row_count: u64,
252}
253
254#[derive(Debug, Clone, Copy)]
256pub struct DoneProc {
257 pub status: DoneStatus,
259 pub cur_cmd: u16,
261 pub row_count: u64,
263}
264
265#[derive(Debug, Clone)]
267pub struct ReturnValue {
268 pub param_ordinal: u16,
270 pub param_name: String,
272 pub status: u8,
274 pub user_type: u32,
276 pub flags: u16,
278 pub type_info: TypeInfo,
280 pub value: bytes::Bytes,
282}
283
284#[derive(Debug, Clone)]
286pub struct ServerError {
287 pub number: i32,
289 pub state: u8,
291 pub class: u8,
293 pub message: String,
295 pub server: String,
297 pub procedure: String,
299 pub line: i32,
301}
302
303#[derive(Debug, Clone)]
305pub struct ServerInfo {
306 pub number: i32,
308 pub state: u8,
310 pub class: u8,
312 pub message: String,
314 pub server: String,
316 pub procedure: String,
318 pub line: i32,
320}
321
322#[derive(Debug, Clone)]
324pub struct LoginAck {
325 pub interface: u8,
327 pub tds_version: u32,
329 pub prog_name: String,
331 pub prog_version: u32,
333}
334
335#[derive(Debug, Clone)]
337pub struct EnvChange {
338 pub env_type: EnvChangeType,
340 pub new_value: EnvChangeValue,
342 pub old_value: EnvChangeValue,
344}
345
346#[derive(Debug, Clone, Copy, PartialEq, Eq)]
348#[repr(u8)]
349pub enum EnvChangeType {
350 Database = 1,
352 Language = 2,
354 CharacterSet = 3,
356 PacketSize = 4,
358 UnicodeSortingLocalId = 5,
360 UnicodeComparisonFlags = 6,
362 SqlCollation = 7,
364 BeginTransaction = 8,
366 CommitTransaction = 9,
368 RollbackTransaction = 10,
370 EnlistDtcTransaction = 11,
372 DefectTransaction = 12,
374 RealTimeLogShipping = 13,
376 PromoteTransaction = 15,
378 TransactionManagerAddress = 16,
380 TransactionEnded = 17,
382 ResetConnectionCompletionAck = 18,
384 UserInstanceStarted = 19,
386 Routing = 20,
388}
389
390#[derive(Debug, Clone)]
392pub enum EnvChangeValue {
393 String(String),
395 Binary(bytes::Bytes),
397 Routing {
399 host: String,
401 port: u16,
403 },
404}
405
406#[derive(Debug, Clone)]
408pub struct Order {
409 pub columns: Vec<u16>,
411}
412
413#[derive(Debug, Clone)]
415pub struct FeatureExtAck {
416 pub features: Vec<FeatureAck>,
418}
419
420#[derive(Debug, Clone)]
422pub struct FeatureAck {
423 pub feature_id: u8,
425 pub data: bytes::Bytes,
427}
428
429#[derive(Debug, Clone)]
431pub struct SspiToken {
432 pub data: bytes::Bytes,
434}
435
436#[derive(Debug, Clone)]
438pub struct SessionState {
439 pub data: bytes::Bytes,
441}
442
443#[derive(Debug, Clone)]
445pub struct FedAuthInfo {
446 pub sts_url: String,
448 pub spn: String,
450}
451
452impl ColMetaData {
457 pub const NO_METADATA: u16 = 0xFFFF;
459
460 pub fn decode(src: &mut impl Buf) -> Result<Self, ProtocolError> {
462 if src.remaining() < 2 {
463 return Err(ProtocolError::UnexpectedEof);
464 }
465
466 let column_count = src.get_u16_le();
467
468 if column_count == Self::NO_METADATA {
470 return Ok(Self {
471 columns: Vec::new(),
472 });
473 }
474
475 let mut columns = Vec::with_capacity(column_count as usize);
476
477 for _ in 0..column_count {
478 let column = Self::decode_column(src)?;
479 columns.push(column);
480 }
481
482 Ok(Self { columns })
483 }
484
485 fn decode_column(src: &mut impl Buf) -> Result<ColumnData, ProtocolError> {
487 if src.remaining() < 7 {
489 return Err(ProtocolError::UnexpectedEof);
490 }
491
492 let user_type = src.get_u32_le();
493 let flags = src.get_u16_le();
494 let col_type = src.get_u8();
495
496 let type_id = TypeId::from_u8(col_type).unwrap_or(TypeId::Null); let type_info = Self::decode_type_info(src, type_id, col_type)?;
500
501 let name = read_b_varchar(src).ok_or(ProtocolError::UnexpectedEof)?;
503
504 Ok(ColumnData {
505 name,
506 type_id,
507 col_type,
508 flags,
509 user_type,
510 type_info,
511 })
512 }
513
514 fn decode_type_info(
516 src: &mut impl Buf,
517 type_id: TypeId,
518 col_type: u8,
519 ) -> Result<TypeInfo, ProtocolError> {
520 match type_id {
521 TypeId::Null => Ok(TypeInfo::default()),
523 TypeId::Int1 | TypeId::Bit => Ok(TypeInfo::default()),
524 TypeId::Int2 => Ok(TypeInfo::default()),
525 TypeId::Int4 => Ok(TypeInfo::default()),
526 TypeId::Int8 => Ok(TypeInfo::default()),
527 TypeId::Float4 => Ok(TypeInfo::default()),
528 TypeId::Float8 => Ok(TypeInfo::default()),
529 TypeId::Money => Ok(TypeInfo::default()),
530 TypeId::Money4 => Ok(TypeInfo::default()),
531 TypeId::DateTime => Ok(TypeInfo::default()),
532 TypeId::DateTime4 => Ok(TypeInfo::default()),
533
534 TypeId::IntN | TypeId::BitN | TypeId::FloatN | TypeId::MoneyN | TypeId::DateTimeN => {
536 if src.remaining() < 1 {
537 return Err(ProtocolError::UnexpectedEof);
538 }
539 let max_length = src.get_u8() as u32;
540 Ok(TypeInfo {
541 max_length: Some(max_length),
542 ..Default::default()
543 })
544 }
545
546 TypeId::Guid => {
548 if src.remaining() < 1 {
549 return Err(ProtocolError::UnexpectedEof);
550 }
551 let max_length = src.get_u8() as u32;
552 Ok(TypeInfo {
553 max_length: Some(max_length),
554 ..Default::default()
555 })
556 }
557
558 TypeId::Decimal | TypeId::Numeric | TypeId::DecimalN | TypeId::NumericN => {
560 if src.remaining() < 3 {
561 return Err(ProtocolError::UnexpectedEof);
562 }
563 let max_length = src.get_u8() as u32;
564 let precision = src.get_u8();
565 let scale = src.get_u8();
566 Ok(TypeInfo {
567 max_length: Some(max_length),
568 precision: Some(precision),
569 scale: Some(scale),
570 ..Default::default()
571 })
572 }
573
574 TypeId::Char | TypeId::VarChar | TypeId::Binary | TypeId::VarBinary => {
576 if src.remaining() < 1 {
577 return Err(ProtocolError::UnexpectedEof);
578 }
579 let max_length = src.get_u8() as u32;
580 Ok(TypeInfo {
581 max_length: Some(max_length),
582 ..Default::default()
583 })
584 }
585
586 TypeId::BigVarChar | TypeId::BigChar => {
588 if src.remaining() < 7 {
589 return Err(ProtocolError::UnexpectedEof);
591 }
592 let max_length = src.get_u16_le() as u32;
593 let collation = Self::decode_collation(src)?;
594 Ok(TypeInfo {
595 max_length: Some(max_length),
596 collation: Some(collation),
597 ..Default::default()
598 })
599 }
600
601 TypeId::BigVarBinary | TypeId::BigBinary => {
603 if src.remaining() < 2 {
604 return Err(ProtocolError::UnexpectedEof);
605 }
606 let max_length = src.get_u16_le() as u32;
607 Ok(TypeInfo {
608 max_length: Some(max_length),
609 ..Default::default()
610 })
611 }
612
613 TypeId::NChar | TypeId::NVarChar => {
615 if src.remaining() < 7 {
616 return Err(ProtocolError::UnexpectedEof);
618 }
619 let max_length = src.get_u16_le() as u32;
620 let collation = Self::decode_collation(src)?;
621 Ok(TypeInfo {
622 max_length: Some(max_length),
623 collation: Some(collation),
624 ..Default::default()
625 })
626 }
627
628 TypeId::Date => Ok(TypeInfo::default()),
630
631 TypeId::Time | TypeId::DateTime2 | TypeId::DateTimeOffset => {
633 if src.remaining() < 1 {
634 return Err(ProtocolError::UnexpectedEof);
635 }
636 let scale = src.get_u8();
637 Ok(TypeInfo {
638 scale: Some(scale),
639 ..Default::default()
640 })
641 }
642
643 TypeId::Text | TypeId::NText | TypeId::Image => {
645 if src.remaining() < 4 {
647 return Err(ProtocolError::UnexpectedEof);
648 }
649 let max_length = src.get_u32_le();
650
651 let collation = if type_id == TypeId::Text || type_id == TypeId::NText {
653 if src.remaining() < 5 {
654 return Err(ProtocolError::UnexpectedEof);
655 }
656 Some(Self::decode_collation(src)?)
657 } else {
658 None
659 };
660
661 if src.remaining() < 1 {
664 return Err(ProtocolError::UnexpectedEof);
665 }
666 let num_parts = src.get_u8();
667 for _ in 0..num_parts {
668 let _ = read_us_varchar(src).ok_or(ProtocolError::UnexpectedEof)?;
670 }
671
672 Ok(TypeInfo {
673 max_length: Some(max_length),
674 collation,
675 ..Default::default()
676 })
677 }
678
679 TypeId::Xml => {
681 if src.remaining() < 1 {
682 return Err(ProtocolError::UnexpectedEof);
683 }
684 let schema_present = src.get_u8();
685
686 if schema_present != 0 {
687 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)?; }
692
693 Ok(TypeInfo::default())
694 }
695
696 TypeId::Udt => {
698 if src.remaining() < 2 {
700 return Err(ProtocolError::UnexpectedEof);
701 }
702 let max_length = src.get_u16_le() as u32;
703
704 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 {
711 max_length: Some(max_length),
712 ..Default::default()
713 })
714 }
715
716 TypeId::Tvp => {
718 Err(ProtocolError::InvalidTokenType(col_type))
721 }
722
723 TypeId::Variant => {
725 if src.remaining() < 4 {
726 return Err(ProtocolError::UnexpectedEof);
727 }
728 let max_length = src.get_u32_le();
729 Ok(TypeInfo {
730 max_length: Some(max_length),
731 ..Default::default()
732 })
733 }
734 }
735 }
736
737 fn decode_collation(src: &mut impl Buf) -> Result<Collation, ProtocolError> {
739 if src.remaining() < 5 {
740 return Err(ProtocolError::UnexpectedEof);
741 }
742 let lcid = src.get_u32_le();
744 let sort_id = src.get_u8();
745 Ok(Collation { lcid, sort_id })
746 }
747
748 #[must_use]
750 pub fn column_count(&self) -> usize {
751 self.columns.len()
752 }
753
754 #[must_use]
756 pub fn is_empty(&self) -> bool {
757 self.columns.is_empty()
758 }
759}
760
761impl ColumnData {
762 #[must_use]
764 pub fn is_nullable(&self) -> bool {
765 (self.flags & 0x0001) != 0
766 }
767
768 #[must_use]
772 pub fn fixed_size(&self) -> Option<usize> {
773 match self.type_id {
774 TypeId::Null => Some(0),
775 TypeId::Int1 | TypeId::Bit => Some(1),
776 TypeId::Int2 => Some(2),
777 TypeId::Int4 => Some(4),
778 TypeId::Int8 => Some(8),
779 TypeId::Float4 => Some(4),
780 TypeId::Float8 => Some(8),
781 TypeId::Money => Some(8),
782 TypeId::Money4 => Some(4),
783 TypeId::DateTime => Some(8),
784 TypeId::DateTime4 => Some(4),
785 TypeId::Date => Some(3),
786 _ => None,
787 }
788 }
789}
790
791impl RawRow {
796 pub fn decode(src: &mut impl Buf, metadata: &ColMetaData) -> Result<Self, ProtocolError> {
801 let mut data = bytes::BytesMut::new();
802
803 for col in &metadata.columns {
804 Self::decode_column_value(src, col, &mut data)?;
805 }
806
807 Ok(Self {
808 data: data.freeze(),
809 })
810 }
811
812 fn decode_column_value(
814 src: &mut impl Buf,
815 col: &ColumnData,
816 dst: &mut bytes::BytesMut,
817 ) -> Result<(), ProtocolError> {
818 match col.type_id {
819 TypeId::Null => {
821 }
823 TypeId::Int1 | TypeId::Bit => {
824 if src.remaining() < 1 {
825 return Err(ProtocolError::UnexpectedEof);
826 }
827 dst.extend_from_slice(&[src.get_u8()]);
828 }
829 TypeId::Int2 => {
830 if src.remaining() < 2 {
831 return Err(ProtocolError::UnexpectedEof);
832 }
833 dst.extend_from_slice(&src.get_u16_le().to_le_bytes());
834 }
835 TypeId::Int4 => {
836 if src.remaining() < 4 {
837 return Err(ProtocolError::UnexpectedEof);
838 }
839 dst.extend_from_slice(&src.get_u32_le().to_le_bytes());
840 }
841 TypeId::Int8 => {
842 if src.remaining() < 8 {
843 return Err(ProtocolError::UnexpectedEof);
844 }
845 dst.extend_from_slice(&src.get_u64_le().to_le_bytes());
846 }
847 TypeId::Float4 => {
848 if src.remaining() < 4 {
849 return Err(ProtocolError::UnexpectedEof);
850 }
851 dst.extend_from_slice(&src.get_u32_le().to_le_bytes());
852 }
853 TypeId::Float8 => {
854 if src.remaining() < 8 {
855 return Err(ProtocolError::UnexpectedEof);
856 }
857 dst.extend_from_slice(&src.get_u64_le().to_le_bytes());
858 }
859 TypeId::Money => {
860 if src.remaining() < 8 {
861 return Err(ProtocolError::UnexpectedEof);
862 }
863 let hi = src.get_u32_le();
864 let lo = src.get_u32_le();
865 dst.extend_from_slice(&hi.to_le_bytes());
866 dst.extend_from_slice(&lo.to_le_bytes());
867 }
868 TypeId::Money4 => {
869 if src.remaining() < 4 {
870 return Err(ProtocolError::UnexpectedEof);
871 }
872 dst.extend_from_slice(&src.get_u32_le().to_le_bytes());
873 }
874 TypeId::DateTime => {
875 if src.remaining() < 8 {
876 return Err(ProtocolError::UnexpectedEof);
877 }
878 let days = src.get_u32_le();
879 let time = src.get_u32_le();
880 dst.extend_from_slice(&days.to_le_bytes());
881 dst.extend_from_slice(&time.to_le_bytes());
882 }
883 TypeId::DateTime4 => {
884 if src.remaining() < 4 {
885 return Err(ProtocolError::UnexpectedEof);
886 }
887 dst.extend_from_slice(&src.get_u32_le().to_le_bytes());
888 }
889 TypeId::Date => {
891 Self::decode_bytelen_type(src, dst)?;
892 }
893
894 TypeId::IntN | TypeId::BitN | TypeId::FloatN | TypeId::MoneyN | TypeId::DateTimeN => {
896 Self::decode_bytelen_type(src, dst)?;
897 }
898
899 TypeId::Guid => {
900 Self::decode_bytelen_type(src, dst)?;
901 }
902
903 TypeId::Decimal | TypeId::Numeric | TypeId::DecimalN | TypeId::NumericN => {
904 Self::decode_bytelen_type(src, dst)?;
905 }
906
907 TypeId::Char | TypeId::VarChar | TypeId::Binary | TypeId::VarBinary => {
909 Self::decode_bytelen_type(src, dst)?;
910 }
911
912 TypeId::BigVarChar | TypeId::BigVarBinary => {
914 if col.type_info.max_length == Some(0xFFFF) {
916 Self::decode_plp_type(src, dst)?;
917 } else {
918 Self::decode_ushortlen_type(src, dst)?;
919 }
920 }
921
922 TypeId::BigChar | TypeId::BigBinary => {
924 Self::decode_ushortlen_type(src, dst)?;
925 }
926
927 TypeId::NVarChar => {
929 if col.type_info.max_length == Some(0xFFFF) {
931 Self::decode_plp_type(src, dst)?;
932 } else {
933 Self::decode_ushortlen_type(src, dst)?;
934 }
935 }
936
937 TypeId::NChar => {
939 Self::decode_ushortlen_type(src, dst)?;
940 }
941
942 TypeId::Time | TypeId::DateTime2 | TypeId::DateTimeOffset => {
944 Self::decode_bytelen_type(src, dst)?;
945 }
946
947 TypeId::Text | TypeId::NText | TypeId::Image => {
949 Self::decode_textptr_type(src, dst)?;
950 }
951
952 TypeId::Xml => {
954 Self::decode_plp_type(src, dst)?;
955 }
956
957 TypeId::Variant => {
959 Self::decode_intlen_type(src, dst)?;
960 }
961
962 TypeId::Udt => {
963 Self::decode_plp_type(src, dst)?;
965 }
966
967 TypeId::Tvp => {
968 return Err(ProtocolError::InvalidTokenType(col.col_type));
970 }
971 }
972
973 Ok(())
974 }
975
976 fn decode_bytelen_type(
978 src: &mut impl Buf,
979 dst: &mut bytes::BytesMut,
980 ) -> Result<(), ProtocolError> {
981 if src.remaining() < 1 {
982 return Err(ProtocolError::UnexpectedEof);
983 }
984 let len = src.get_u8() as usize;
985 if len == 0xFF {
986 dst.extend_from_slice(&[0xFF]);
988 } else if len == 0 {
989 dst.extend_from_slice(&[0x00]);
991 } else {
992 if src.remaining() < len {
993 return Err(ProtocolError::UnexpectedEof);
994 }
995 dst.extend_from_slice(&[len as u8]);
996 for _ in 0..len {
997 dst.extend_from_slice(&[src.get_u8()]);
998 }
999 }
1000 Ok(())
1001 }
1002
1003 fn decode_ushortlen_type(
1005 src: &mut impl Buf,
1006 dst: &mut bytes::BytesMut,
1007 ) -> Result<(), ProtocolError> {
1008 if src.remaining() < 2 {
1009 return Err(ProtocolError::UnexpectedEof);
1010 }
1011 let len = src.get_u16_le() as usize;
1012 if len == 0xFFFF {
1013 dst.extend_from_slice(&0xFFFFu16.to_le_bytes());
1015 } else if len == 0 {
1016 dst.extend_from_slice(&0u16.to_le_bytes());
1018 } else {
1019 if src.remaining() < len {
1020 return Err(ProtocolError::UnexpectedEof);
1021 }
1022 dst.extend_from_slice(&(len as u16).to_le_bytes());
1023 for _ in 0..len {
1024 dst.extend_from_slice(&[src.get_u8()]);
1025 }
1026 }
1027 Ok(())
1028 }
1029
1030 fn decode_intlen_type(
1032 src: &mut impl Buf,
1033 dst: &mut bytes::BytesMut,
1034 ) -> Result<(), ProtocolError> {
1035 if src.remaining() < 4 {
1036 return Err(ProtocolError::UnexpectedEof);
1037 }
1038 let len = src.get_u32_le() as usize;
1039 if len == 0xFFFFFFFF {
1040 dst.extend_from_slice(&0xFFFFFFFFu32.to_le_bytes());
1042 } else if len == 0 {
1043 dst.extend_from_slice(&0u32.to_le_bytes());
1045 } else {
1046 if src.remaining() < len {
1047 return Err(ProtocolError::UnexpectedEof);
1048 }
1049 dst.extend_from_slice(&(len as u32).to_le_bytes());
1050 for _ in 0..len {
1051 dst.extend_from_slice(&[src.get_u8()]);
1052 }
1053 }
1054 Ok(())
1055 }
1056
1057 fn decode_textptr_type(
1072 src: &mut impl Buf,
1073 dst: &mut bytes::BytesMut,
1074 ) -> Result<(), ProtocolError> {
1075 if src.remaining() < 1 {
1076 return Err(ProtocolError::UnexpectedEof);
1077 }
1078
1079 let textptr_len = src.get_u8() as usize;
1080
1081 if textptr_len == 0 {
1082 dst.extend_from_slice(&0xFFFFFFFFFFFFFFFFu64.to_le_bytes());
1084 return Ok(());
1085 }
1086
1087 if src.remaining() < textptr_len {
1089 return Err(ProtocolError::UnexpectedEof);
1090 }
1091 src.advance(textptr_len);
1092
1093 if src.remaining() < 8 {
1095 return Err(ProtocolError::UnexpectedEof);
1096 }
1097 src.advance(8);
1098
1099 if src.remaining() < 4 {
1101 return Err(ProtocolError::UnexpectedEof);
1102 }
1103 let data_len = src.get_u32_le() as usize;
1104
1105 if src.remaining() < data_len {
1106 return Err(ProtocolError::UnexpectedEof);
1107 }
1108
1109 dst.extend_from_slice(&(data_len as u64).to_le_bytes());
1115 dst.extend_from_slice(&(data_len as u32).to_le_bytes());
1116 for _ in 0..data_len {
1117 dst.extend_from_slice(&[src.get_u8()]);
1118 }
1119 dst.extend_from_slice(&0u32.to_le_bytes()); Ok(())
1122 }
1123
1124 fn decode_plp_type(src: &mut impl Buf, dst: &mut bytes::BytesMut) -> Result<(), ProtocolError> {
1130 if src.remaining() < 8 {
1131 return Err(ProtocolError::UnexpectedEof);
1132 }
1133
1134 let total_len = src.get_u64_le();
1135
1136 dst.extend_from_slice(&total_len.to_le_bytes());
1138
1139 if total_len == 0xFFFFFFFFFFFFFFFF {
1140 return Ok(());
1142 }
1143
1144 loop {
1146 if src.remaining() < 4 {
1147 return Err(ProtocolError::UnexpectedEof);
1148 }
1149 let chunk_len = src.get_u32_le() as usize;
1150 dst.extend_from_slice(&(chunk_len as u32).to_le_bytes());
1151
1152 if chunk_len == 0 {
1153 break;
1155 }
1156
1157 if src.remaining() < chunk_len {
1158 return Err(ProtocolError::UnexpectedEof);
1159 }
1160
1161 for _ in 0..chunk_len {
1162 dst.extend_from_slice(&[src.get_u8()]);
1163 }
1164 }
1165
1166 Ok(())
1167 }
1168}
1169
1170impl NbcRow {
1175 pub fn decode(src: &mut impl Buf, metadata: &ColMetaData) -> Result<Self, ProtocolError> {
1180 let col_count = metadata.columns.len();
1181 let bitmap_len = (col_count + 7) / 8;
1182
1183 if src.remaining() < bitmap_len {
1184 return Err(ProtocolError::UnexpectedEof);
1185 }
1186
1187 let mut null_bitmap = vec![0u8; bitmap_len];
1189 for byte in &mut null_bitmap {
1190 *byte = src.get_u8();
1191 }
1192
1193 let mut data = bytes::BytesMut::new();
1195
1196 for (i, col) in metadata.columns.iter().enumerate() {
1197 let byte_idx = i / 8;
1198 let bit_idx = i % 8;
1199 let is_null = (null_bitmap[byte_idx] & (1 << bit_idx)) != 0;
1200
1201 if !is_null {
1202 RawRow::decode_column_value(src, col, &mut data)?;
1205 }
1206 }
1207
1208 Ok(Self {
1209 null_bitmap,
1210 data: data.freeze(),
1211 })
1212 }
1213
1214 #[must_use]
1216 pub fn is_null(&self, column_index: usize) -> bool {
1217 let byte_idx = column_index / 8;
1218 let bit_idx = column_index % 8;
1219 if byte_idx < self.null_bitmap.len() {
1220 (self.null_bitmap[byte_idx] & (1 << bit_idx)) != 0
1221 } else {
1222 true }
1224 }
1225}
1226
1227impl ReturnValue {
1232 pub fn decode(src: &mut impl Buf) -> Result<Self, ProtocolError> {
1234 if src.remaining() < 2 {
1236 return Err(ProtocolError::UnexpectedEof);
1237 }
1238 let _length = src.get_u16_le();
1239
1240 if src.remaining() < 2 {
1242 return Err(ProtocolError::UnexpectedEof);
1243 }
1244 let param_ordinal = src.get_u16_le();
1245
1246 let param_name = read_b_varchar(src).ok_or(ProtocolError::UnexpectedEof)?;
1248
1249 if src.remaining() < 1 {
1251 return Err(ProtocolError::UnexpectedEof);
1252 }
1253 let status = src.get_u8();
1254
1255 if src.remaining() < 7 {
1257 return Err(ProtocolError::UnexpectedEof);
1258 }
1259 let user_type = src.get_u32_le();
1260 let flags = src.get_u16_le();
1261 let col_type = src.get_u8();
1262
1263 let type_id = TypeId::from_u8(col_type).unwrap_or(TypeId::Null);
1264
1265 let type_info = ColMetaData::decode_type_info(src, type_id, col_type)?;
1267
1268 let mut value_buf = bytes::BytesMut::new();
1270
1271 let temp_col = ColumnData {
1273 name: String::new(),
1274 type_id,
1275 col_type,
1276 flags,
1277 user_type,
1278 type_info: type_info.clone(),
1279 };
1280
1281 RawRow::decode_column_value(src, &temp_col, &mut value_buf)?;
1282
1283 Ok(Self {
1284 param_ordinal,
1285 param_name,
1286 status,
1287 user_type,
1288 flags,
1289 type_info,
1290 value: value_buf.freeze(),
1291 })
1292 }
1293}
1294
1295impl SessionState {
1300 pub fn decode(src: &mut impl Buf) -> Result<Self, ProtocolError> {
1302 if src.remaining() < 4 {
1303 return Err(ProtocolError::UnexpectedEof);
1304 }
1305
1306 let length = src.get_u32_le() as usize;
1307
1308 if src.remaining() < length {
1309 return Err(ProtocolError::IncompletePacket {
1310 expected: length,
1311 actual: src.remaining(),
1312 });
1313 }
1314
1315 let data = src.copy_to_bytes(length);
1316
1317 Ok(Self { data })
1318 }
1319}
1320
1321mod done_status_bits {
1327 pub const DONE_MORE: u16 = 0x0001;
1328 pub const DONE_ERROR: u16 = 0x0002;
1329 pub const DONE_INXACT: u16 = 0x0004;
1330 pub const DONE_COUNT: u16 = 0x0010;
1331 pub const DONE_ATTN: u16 = 0x0020;
1332 pub const DONE_SRVERROR: u16 = 0x0100;
1333}
1334
1335impl DoneStatus {
1336 #[must_use]
1338 pub fn from_bits(bits: u16) -> Self {
1339 use done_status_bits::*;
1340 Self {
1341 more: (bits & DONE_MORE) != 0,
1342 error: (bits & DONE_ERROR) != 0,
1343 in_xact: (bits & DONE_INXACT) != 0,
1344 count: (bits & DONE_COUNT) != 0,
1345 attn: (bits & DONE_ATTN) != 0,
1346 srverror: (bits & DONE_SRVERROR) != 0,
1347 }
1348 }
1349
1350 #[must_use]
1352 pub fn to_bits(&self) -> u16 {
1353 use done_status_bits::*;
1354 let mut bits = 0u16;
1355 if self.more {
1356 bits |= DONE_MORE;
1357 }
1358 if self.error {
1359 bits |= DONE_ERROR;
1360 }
1361 if self.in_xact {
1362 bits |= DONE_INXACT;
1363 }
1364 if self.count {
1365 bits |= DONE_COUNT;
1366 }
1367 if self.attn {
1368 bits |= DONE_ATTN;
1369 }
1370 if self.srverror {
1371 bits |= DONE_SRVERROR;
1372 }
1373 bits
1374 }
1375}
1376
1377impl Done {
1378 pub const SIZE: usize = 12; pub fn decode(src: &mut impl Buf) -> Result<Self, ProtocolError> {
1383 if src.remaining() < Self::SIZE {
1384 return Err(ProtocolError::IncompletePacket {
1385 expected: Self::SIZE,
1386 actual: src.remaining(),
1387 });
1388 }
1389
1390 let status = DoneStatus::from_bits(src.get_u16_le());
1391 let cur_cmd = src.get_u16_le();
1392 let row_count = src.get_u64_le();
1393
1394 Ok(Self {
1395 status,
1396 cur_cmd,
1397 row_count,
1398 })
1399 }
1400
1401 pub fn encode(&self, dst: &mut impl BufMut) {
1403 dst.put_u8(TokenType::Done as u8);
1404 dst.put_u16_le(self.status.to_bits());
1405 dst.put_u16_le(self.cur_cmd);
1406 dst.put_u64_le(self.row_count);
1407 }
1408
1409 #[must_use]
1411 pub const fn has_more(&self) -> bool {
1412 self.status.more
1413 }
1414
1415 #[must_use]
1417 pub const fn has_error(&self) -> bool {
1418 self.status.error
1419 }
1420
1421 #[must_use]
1423 pub const fn has_count(&self) -> bool {
1424 self.status.count
1425 }
1426}
1427
1428impl DoneProc {
1429 pub const SIZE: usize = 12;
1431
1432 pub fn decode(src: &mut impl Buf) -> Result<Self, ProtocolError> {
1434 if src.remaining() < Self::SIZE {
1435 return Err(ProtocolError::IncompletePacket {
1436 expected: Self::SIZE,
1437 actual: src.remaining(),
1438 });
1439 }
1440
1441 let status = DoneStatus::from_bits(src.get_u16_le());
1442 let cur_cmd = src.get_u16_le();
1443 let row_count = src.get_u64_le();
1444
1445 Ok(Self {
1446 status,
1447 cur_cmd,
1448 row_count,
1449 })
1450 }
1451
1452 pub fn encode(&self, dst: &mut impl BufMut) {
1454 dst.put_u8(TokenType::DoneProc as u8);
1455 dst.put_u16_le(self.status.to_bits());
1456 dst.put_u16_le(self.cur_cmd);
1457 dst.put_u64_le(self.row_count);
1458 }
1459}
1460
1461impl DoneInProc {
1462 pub const SIZE: usize = 12;
1464
1465 pub fn decode(src: &mut impl Buf) -> Result<Self, ProtocolError> {
1467 if src.remaining() < Self::SIZE {
1468 return Err(ProtocolError::IncompletePacket {
1469 expected: Self::SIZE,
1470 actual: src.remaining(),
1471 });
1472 }
1473
1474 let status = DoneStatus::from_bits(src.get_u16_le());
1475 let cur_cmd = src.get_u16_le();
1476 let row_count = src.get_u64_le();
1477
1478 Ok(Self {
1479 status,
1480 cur_cmd,
1481 row_count,
1482 })
1483 }
1484
1485 pub fn encode(&self, dst: &mut impl BufMut) {
1487 dst.put_u8(TokenType::DoneInProc as u8);
1488 dst.put_u16_le(self.status.to_bits());
1489 dst.put_u16_le(self.cur_cmd);
1490 dst.put_u64_le(self.row_count);
1491 }
1492}
1493
1494impl ServerError {
1495 pub fn decode(src: &mut impl Buf) -> Result<Self, ProtocolError> {
1497 if src.remaining() < 2 {
1500 return Err(ProtocolError::UnexpectedEof);
1501 }
1502
1503 let _length = src.get_u16_le();
1504
1505 if src.remaining() < 6 {
1506 return Err(ProtocolError::UnexpectedEof);
1507 }
1508
1509 let number = src.get_i32_le();
1510 let state = src.get_u8();
1511 let class = src.get_u8();
1512
1513 let message = read_us_varchar(src).ok_or(ProtocolError::UnexpectedEof)?;
1514 let server = read_b_varchar(src).ok_or(ProtocolError::UnexpectedEof)?;
1515 let procedure = read_b_varchar(src).ok_or(ProtocolError::UnexpectedEof)?;
1516
1517 if src.remaining() < 4 {
1518 return Err(ProtocolError::UnexpectedEof);
1519 }
1520 let line = src.get_i32_le();
1521
1522 Ok(Self {
1523 number,
1524 state,
1525 class,
1526 message,
1527 server,
1528 procedure,
1529 line,
1530 })
1531 }
1532
1533 #[must_use]
1535 pub const fn is_fatal(&self) -> bool {
1536 self.class >= 20
1537 }
1538
1539 #[must_use]
1541 pub const fn is_batch_abort(&self) -> bool {
1542 self.class >= 16
1543 }
1544}
1545
1546impl ServerInfo {
1547 pub fn decode(src: &mut impl Buf) -> Result<Self, ProtocolError> {
1551 if src.remaining() < 2 {
1552 return Err(ProtocolError::UnexpectedEof);
1553 }
1554
1555 let _length = src.get_u16_le();
1556
1557 if src.remaining() < 6 {
1558 return Err(ProtocolError::UnexpectedEof);
1559 }
1560
1561 let number = src.get_i32_le();
1562 let state = src.get_u8();
1563 let class = src.get_u8();
1564
1565 let message = read_us_varchar(src).ok_or(ProtocolError::UnexpectedEof)?;
1566 let server = read_b_varchar(src).ok_or(ProtocolError::UnexpectedEof)?;
1567 let procedure = read_b_varchar(src).ok_or(ProtocolError::UnexpectedEof)?;
1568
1569 if src.remaining() < 4 {
1570 return Err(ProtocolError::UnexpectedEof);
1571 }
1572 let line = src.get_i32_le();
1573
1574 Ok(Self {
1575 number,
1576 state,
1577 class,
1578 message,
1579 server,
1580 procedure,
1581 line,
1582 })
1583 }
1584}
1585
1586impl LoginAck {
1587 pub fn decode(src: &mut impl Buf) -> Result<Self, ProtocolError> {
1589 if src.remaining() < 2 {
1591 return Err(ProtocolError::UnexpectedEof);
1592 }
1593
1594 let _length = src.get_u16_le();
1595
1596 if src.remaining() < 5 {
1597 return Err(ProtocolError::UnexpectedEof);
1598 }
1599
1600 let interface = src.get_u8();
1601 let tds_version = src.get_u32_le();
1602 let prog_name = read_b_varchar(src).ok_or(ProtocolError::UnexpectedEof)?;
1603
1604 if src.remaining() < 4 {
1605 return Err(ProtocolError::UnexpectedEof);
1606 }
1607 let prog_version = src.get_u32_le();
1608
1609 Ok(Self {
1610 interface,
1611 tds_version,
1612 prog_name,
1613 prog_version,
1614 })
1615 }
1616
1617 #[must_use]
1619 pub fn tds_version(&self) -> crate::version::TdsVersion {
1620 crate::version::TdsVersion::new(self.tds_version)
1621 }
1622}
1623
1624impl EnvChangeType {
1625 pub fn from_u8(value: u8) -> Option<Self> {
1627 match value {
1628 1 => Some(Self::Database),
1629 2 => Some(Self::Language),
1630 3 => Some(Self::CharacterSet),
1631 4 => Some(Self::PacketSize),
1632 5 => Some(Self::UnicodeSortingLocalId),
1633 6 => Some(Self::UnicodeComparisonFlags),
1634 7 => Some(Self::SqlCollation),
1635 8 => Some(Self::BeginTransaction),
1636 9 => Some(Self::CommitTransaction),
1637 10 => Some(Self::RollbackTransaction),
1638 11 => Some(Self::EnlistDtcTransaction),
1639 12 => Some(Self::DefectTransaction),
1640 13 => Some(Self::RealTimeLogShipping),
1641 15 => Some(Self::PromoteTransaction),
1642 16 => Some(Self::TransactionManagerAddress),
1643 17 => Some(Self::TransactionEnded),
1644 18 => Some(Self::ResetConnectionCompletionAck),
1645 19 => Some(Self::UserInstanceStarted),
1646 20 => Some(Self::Routing),
1647 _ => None,
1648 }
1649 }
1650}
1651
1652impl EnvChange {
1653 pub fn decode(src: &mut impl Buf) -> Result<Self, ProtocolError> {
1655 if src.remaining() < 3 {
1656 return Err(ProtocolError::UnexpectedEof);
1657 }
1658
1659 let length = src.get_u16_le() as usize;
1660 if src.remaining() < length {
1661 return Err(ProtocolError::IncompletePacket {
1662 expected: length,
1663 actual: src.remaining(),
1664 });
1665 }
1666
1667 let env_type_byte = src.get_u8();
1668 let env_type = EnvChangeType::from_u8(env_type_byte)
1669 .ok_or(ProtocolError::InvalidTokenType(env_type_byte))?;
1670
1671 let (new_value, old_value) = match env_type {
1672 EnvChangeType::Routing => {
1673 let new_value = Self::decode_routing_value(src)?;
1675 let old_value = EnvChangeValue::Binary(Bytes::new());
1676 (new_value, old_value)
1677 }
1678 EnvChangeType::BeginTransaction
1679 | EnvChangeType::CommitTransaction
1680 | EnvChangeType::RollbackTransaction
1681 | EnvChangeType::EnlistDtcTransaction
1682 | EnvChangeType::SqlCollation => {
1683 let new_len = src.get_u8() as usize;
1687 let new_value = if new_len > 0 && src.remaining() >= new_len {
1688 EnvChangeValue::Binary(src.copy_to_bytes(new_len))
1689 } else {
1690 EnvChangeValue::Binary(Bytes::new())
1691 };
1692
1693 let old_len = src.get_u8() as usize;
1694 let old_value = if old_len > 0 && src.remaining() >= old_len {
1695 EnvChangeValue::Binary(src.copy_to_bytes(old_len))
1696 } else {
1697 EnvChangeValue::Binary(Bytes::new())
1698 };
1699
1700 (new_value, old_value)
1701 }
1702 _ => {
1703 let new_value = read_b_varchar(src)
1705 .map(EnvChangeValue::String)
1706 .unwrap_or(EnvChangeValue::String(String::new()));
1707
1708 let old_value = read_b_varchar(src)
1709 .map(EnvChangeValue::String)
1710 .unwrap_or(EnvChangeValue::String(String::new()));
1711
1712 (new_value, old_value)
1713 }
1714 };
1715
1716 Ok(Self {
1717 env_type,
1718 new_value,
1719 old_value,
1720 })
1721 }
1722
1723 fn decode_routing_value(src: &mut impl Buf) -> Result<EnvChangeValue, ProtocolError> {
1724 if src.remaining() < 2 {
1726 return Err(ProtocolError::UnexpectedEof);
1727 }
1728
1729 let _routing_len = src.get_u16_le();
1730
1731 if src.remaining() < 5 {
1732 return Err(ProtocolError::UnexpectedEof);
1733 }
1734
1735 let _protocol = src.get_u8();
1736 let port = src.get_u16_le();
1737 let server_len = src.get_u16_le() as usize;
1738
1739 if src.remaining() < server_len * 2 {
1741 return Err(ProtocolError::UnexpectedEof);
1742 }
1743
1744 let mut chars = Vec::with_capacity(server_len);
1745 for _ in 0..server_len {
1746 chars.push(src.get_u16_le());
1747 }
1748
1749 let host = String::from_utf16(&chars).map_err(|_| {
1750 ProtocolError::StringEncoding(
1751 #[cfg(feature = "std")]
1752 "invalid UTF-16 in routing hostname".to_string(),
1753 #[cfg(not(feature = "std"))]
1754 "invalid UTF-16 in routing hostname",
1755 )
1756 })?;
1757
1758 Ok(EnvChangeValue::Routing { host, port })
1759 }
1760
1761 #[must_use]
1763 pub fn is_routing(&self) -> bool {
1764 self.env_type == EnvChangeType::Routing
1765 }
1766
1767 #[must_use]
1769 pub fn routing_info(&self) -> Option<(&str, u16)> {
1770 if let EnvChangeValue::Routing { host, port } = &self.new_value {
1771 Some((host, *port))
1772 } else {
1773 None
1774 }
1775 }
1776
1777 #[must_use]
1779 pub fn new_database(&self) -> Option<&str> {
1780 if self.env_type == EnvChangeType::Database {
1781 if let EnvChangeValue::String(s) = &self.new_value {
1782 return Some(s);
1783 }
1784 }
1785 None
1786 }
1787}
1788
1789impl Order {
1790 pub fn decode(src: &mut impl Buf) -> Result<Self, ProtocolError> {
1792 if src.remaining() < 2 {
1793 return Err(ProtocolError::UnexpectedEof);
1794 }
1795
1796 let length = src.get_u16_le() as usize;
1797 let column_count = length / 2;
1798
1799 if src.remaining() < length {
1800 return Err(ProtocolError::IncompletePacket {
1801 expected: length,
1802 actual: src.remaining(),
1803 });
1804 }
1805
1806 let mut columns = Vec::with_capacity(column_count);
1807 for _ in 0..column_count {
1808 columns.push(src.get_u16_le());
1809 }
1810
1811 Ok(Self { columns })
1812 }
1813}
1814
1815impl FeatureExtAck {
1816 pub const TERMINATOR: u8 = 0xFF;
1818
1819 pub fn decode(src: &mut impl Buf) -> Result<Self, ProtocolError> {
1821 let mut features = Vec::new();
1822
1823 loop {
1824 if !src.has_remaining() {
1825 return Err(ProtocolError::UnexpectedEof);
1826 }
1827
1828 let feature_id = src.get_u8();
1829 if feature_id == Self::TERMINATOR {
1830 break;
1831 }
1832
1833 if src.remaining() < 4 {
1834 return Err(ProtocolError::UnexpectedEof);
1835 }
1836
1837 let data_len = src.get_u32_le() as usize;
1838
1839 if src.remaining() < data_len {
1840 return Err(ProtocolError::IncompletePacket {
1841 expected: data_len,
1842 actual: src.remaining(),
1843 });
1844 }
1845
1846 let data = src.copy_to_bytes(data_len);
1847 features.push(FeatureAck { feature_id, data });
1848 }
1849
1850 Ok(Self { features })
1851 }
1852}
1853
1854impl SspiToken {
1855 pub fn decode(src: &mut impl Buf) -> Result<Self, ProtocolError> {
1857 if src.remaining() < 2 {
1858 return Err(ProtocolError::UnexpectedEof);
1859 }
1860
1861 let length = src.get_u16_le() as usize;
1862
1863 if src.remaining() < length {
1864 return Err(ProtocolError::IncompletePacket {
1865 expected: length,
1866 actual: src.remaining(),
1867 });
1868 }
1869
1870 let data = src.copy_to_bytes(length);
1871 Ok(Self { data })
1872 }
1873}
1874
1875impl FedAuthInfo {
1876 pub fn decode(src: &mut impl Buf) -> Result<Self, ProtocolError> {
1878 if src.remaining() < 4 {
1879 return Err(ProtocolError::UnexpectedEof);
1880 }
1881
1882 let _length = src.get_u32_le();
1883
1884 if src.remaining() < 5 {
1885 return Err(ProtocolError::UnexpectedEof);
1886 }
1887
1888 let _count = src.get_u8();
1889
1890 let mut sts_url = String::new();
1892 let mut spn = String::new();
1893
1894 while src.has_remaining() {
1896 if src.remaining() < 9 {
1897 break;
1898 }
1899
1900 let info_id = src.get_u8();
1901 let info_len = src.get_u32_le() as usize;
1902 let _info_offset = src.get_u32_le();
1903
1904 if src.remaining() < info_len {
1905 break;
1906 }
1907
1908 let char_count = info_len / 2;
1910 let mut chars = Vec::with_capacity(char_count);
1911 for _ in 0..char_count {
1912 chars.push(src.get_u16_le());
1913 }
1914
1915 if let Ok(value) = String::from_utf16(&chars) {
1916 match info_id {
1917 0x01 => spn = value,
1918 0x02 => sts_url = value,
1919 _ => {}
1920 }
1921 }
1922 }
1923
1924 Ok(Self { sts_url, spn })
1925 }
1926}
1927
1928pub struct TokenParser {
1969 data: Bytes,
1970 position: usize,
1971}
1972
1973impl TokenParser {
1974 #[must_use]
1976 pub fn new(data: Bytes) -> Self {
1977 Self { data, position: 0 }
1978 }
1979
1980 #[must_use]
1982 pub fn remaining(&self) -> usize {
1983 self.data.len().saturating_sub(self.position)
1984 }
1985
1986 #[must_use]
1988 pub fn has_remaining(&self) -> bool {
1989 self.position < self.data.len()
1990 }
1991
1992 #[must_use]
1994 pub fn peek_token_type(&self) -> Option<TokenType> {
1995 if self.position < self.data.len() {
1996 TokenType::from_u8(self.data[self.position])
1997 } else {
1998 None
1999 }
2000 }
2001
2002 pub fn next_token(&mut self) -> Result<Option<Token>, ProtocolError> {
2010 self.next_token_with_metadata(None)
2011 }
2012
2013 pub fn next_token_with_metadata(
2020 &mut self,
2021 metadata: Option<&ColMetaData>,
2022 ) -> Result<Option<Token>, ProtocolError> {
2023 if !self.has_remaining() {
2024 return Ok(None);
2025 }
2026
2027 let mut buf = &self.data[self.position..];
2028 let start_pos = self.position;
2029
2030 let token_type_byte = buf.get_u8();
2031 let token_type = TokenType::from_u8(token_type_byte);
2032
2033 let token = match token_type {
2034 Some(TokenType::Done) => {
2035 let done = Done::decode(&mut buf)?;
2036 Token::Done(done)
2037 }
2038 Some(TokenType::DoneProc) => {
2039 let done = DoneProc::decode(&mut buf)?;
2040 Token::DoneProc(done)
2041 }
2042 Some(TokenType::DoneInProc) => {
2043 let done = DoneInProc::decode(&mut buf)?;
2044 Token::DoneInProc(done)
2045 }
2046 Some(TokenType::Error) => {
2047 let error = ServerError::decode(&mut buf)?;
2048 Token::Error(error)
2049 }
2050 Some(TokenType::Info) => {
2051 let info = ServerInfo::decode(&mut buf)?;
2052 Token::Info(info)
2053 }
2054 Some(TokenType::LoginAck) => {
2055 let login_ack = LoginAck::decode(&mut buf)?;
2056 Token::LoginAck(login_ack)
2057 }
2058 Some(TokenType::EnvChange) => {
2059 let env_change = EnvChange::decode(&mut buf)?;
2060 Token::EnvChange(env_change)
2061 }
2062 Some(TokenType::Order) => {
2063 let order = Order::decode(&mut buf)?;
2064 Token::Order(order)
2065 }
2066 Some(TokenType::FeatureExtAck) => {
2067 let ack = FeatureExtAck::decode(&mut buf)?;
2068 Token::FeatureExtAck(ack)
2069 }
2070 Some(TokenType::Sspi) => {
2071 let sspi = SspiToken::decode(&mut buf)?;
2072 Token::Sspi(sspi)
2073 }
2074 Some(TokenType::FedAuthInfo) => {
2075 let info = FedAuthInfo::decode(&mut buf)?;
2076 Token::FedAuthInfo(info)
2077 }
2078 Some(TokenType::ReturnStatus) => {
2079 if buf.remaining() < 4 {
2080 return Err(ProtocolError::UnexpectedEof);
2081 }
2082 let status = buf.get_i32_le();
2083 Token::ReturnStatus(status)
2084 }
2085 Some(TokenType::ColMetaData) => {
2086 let col_meta = ColMetaData::decode(&mut buf)?;
2087 Token::ColMetaData(col_meta)
2088 }
2089 Some(TokenType::Row) => {
2090 let meta = metadata.ok_or_else(|| {
2091 ProtocolError::StringEncoding(
2092 #[cfg(feature = "std")]
2093 "Row token requires column metadata".to_string(),
2094 #[cfg(not(feature = "std"))]
2095 "Row token requires column metadata",
2096 )
2097 })?;
2098 let row = RawRow::decode(&mut buf, meta)?;
2099 Token::Row(row)
2100 }
2101 Some(TokenType::NbcRow) => {
2102 let meta = metadata.ok_or_else(|| {
2103 ProtocolError::StringEncoding(
2104 #[cfg(feature = "std")]
2105 "NbcRow token requires column metadata".to_string(),
2106 #[cfg(not(feature = "std"))]
2107 "NbcRow token requires column metadata",
2108 )
2109 })?;
2110 let row = NbcRow::decode(&mut buf, meta)?;
2111 Token::NbcRow(row)
2112 }
2113 Some(TokenType::ReturnValue) => {
2114 let ret_val = ReturnValue::decode(&mut buf)?;
2115 Token::ReturnValue(ret_val)
2116 }
2117 Some(TokenType::SessionState) => {
2118 let session = SessionState::decode(&mut buf)?;
2119 Token::SessionState(session)
2120 }
2121 Some(TokenType::ColInfo) | Some(TokenType::TabName) | Some(TokenType::Offset) => {
2122 if buf.remaining() < 2 {
2125 return Err(ProtocolError::UnexpectedEof);
2126 }
2127 let length = buf.get_u16_le() as usize;
2128 if buf.remaining() < length {
2129 return Err(ProtocolError::IncompletePacket {
2130 expected: length,
2131 actual: buf.remaining(),
2132 });
2133 }
2134 buf.advance(length);
2136 self.position = start_pos + (self.data.len() - start_pos - buf.remaining());
2138 return self.next_token_with_metadata(metadata);
2139 }
2140 None => {
2141 return Err(ProtocolError::InvalidTokenType(token_type_byte));
2142 }
2143 };
2144
2145 let consumed = self.data.len() - start_pos - buf.remaining();
2147 self.position = start_pos + consumed;
2148
2149 Ok(Some(token))
2150 }
2151
2152 pub fn skip_token(&mut self) -> Result<(), ProtocolError> {
2156 if !self.has_remaining() {
2157 return Ok(());
2158 }
2159
2160 let token_type_byte = self.data[self.position];
2161 let token_type = TokenType::from_u8(token_type_byte);
2162
2163 let skip_amount = match token_type {
2165 Some(TokenType::Done) | Some(TokenType::DoneProc) | Some(TokenType::DoneInProc) => {
2167 1 + Done::SIZE }
2169 Some(TokenType::ReturnStatus) => {
2170 1 + 4 }
2172 Some(TokenType::Error)
2174 | Some(TokenType::Info)
2175 | Some(TokenType::LoginAck)
2176 | Some(TokenType::EnvChange)
2177 | Some(TokenType::Order)
2178 | Some(TokenType::Sspi)
2179 | Some(TokenType::ColInfo)
2180 | Some(TokenType::TabName)
2181 | Some(TokenType::Offset)
2182 | Some(TokenType::ReturnValue) => {
2183 if self.remaining() < 3 {
2184 return Err(ProtocolError::UnexpectedEof);
2185 }
2186 let length = u16::from_le_bytes([
2187 self.data[self.position + 1],
2188 self.data[self.position + 2],
2189 ]) as usize;
2190 1 + 2 + length }
2192 Some(TokenType::SessionState) | Some(TokenType::FedAuthInfo) => {
2194 if self.remaining() < 5 {
2195 return Err(ProtocolError::UnexpectedEof);
2196 }
2197 let length = u32::from_le_bytes([
2198 self.data[self.position + 1],
2199 self.data[self.position + 2],
2200 self.data[self.position + 3],
2201 self.data[self.position + 4],
2202 ]) as usize;
2203 1 + 4 + length
2204 }
2205 Some(TokenType::FeatureExtAck) => {
2207 let mut buf = &self.data[self.position + 1..];
2209 let _ = FeatureExtAck::decode(&mut buf)?;
2210 self.data.len() - self.position - buf.remaining()
2211 }
2212 Some(TokenType::ColMetaData) | Some(TokenType::Row) | Some(TokenType::NbcRow) => {
2214 return Err(ProtocolError::InvalidTokenType(token_type_byte));
2215 }
2216 None => {
2217 return Err(ProtocolError::InvalidTokenType(token_type_byte));
2218 }
2219 };
2220
2221 if self.remaining() < skip_amount {
2222 return Err(ProtocolError::UnexpectedEof);
2223 }
2224
2225 self.position += skip_amount;
2226 Ok(())
2227 }
2228
2229 #[must_use]
2231 pub fn position(&self) -> usize {
2232 self.position
2233 }
2234
2235 pub fn reset(&mut self) {
2237 self.position = 0;
2238 }
2239}
2240
2241#[cfg(not(feature = "std"))]
2246use alloc::string::String;
2247#[cfg(not(feature = "std"))]
2248use alloc::vec::Vec;
2249
2250#[cfg(test)]
2255#[allow(clippy::unwrap_used, clippy::panic)]
2256mod tests {
2257 use super::*;
2258 use bytes::BytesMut;
2259
2260 #[test]
2261 fn test_done_roundtrip() {
2262 let done = Done {
2263 status: DoneStatus {
2264 more: false,
2265 error: false,
2266 in_xact: false,
2267 count: true,
2268 attn: false,
2269 srverror: false,
2270 },
2271 cur_cmd: 193, row_count: 42,
2273 };
2274
2275 let mut buf = BytesMut::new();
2276 done.encode(&mut buf);
2277
2278 let mut cursor = &buf[1..];
2280 let decoded = Done::decode(&mut cursor).unwrap();
2281
2282 assert_eq!(decoded.status.count, done.status.count);
2283 assert_eq!(decoded.cur_cmd, done.cur_cmd);
2284 assert_eq!(decoded.row_count, done.row_count);
2285 }
2286
2287 #[test]
2288 fn test_done_status_bits() {
2289 let status = DoneStatus {
2290 more: true,
2291 error: true,
2292 in_xact: true,
2293 count: true,
2294 attn: false,
2295 srverror: false,
2296 };
2297
2298 let bits = status.to_bits();
2299 let restored = DoneStatus::from_bits(bits);
2300
2301 assert_eq!(status.more, restored.more);
2302 assert_eq!(status.error, restored.error);
2303 assert_eq!(status.in_xact, restored.in_xact);
2304 assert_eq!(status.count, restored.count);
2305 }
2306
2307 #[test]
2308 fn test_token_parser_done() {
2309 let data = Bytes::from_static(&[
2311 0xFD, 0x10, 0x00, 0xC1, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ]);
2316
2317 let mut parser = TokenParser::new(data);
2318 let token = parser.next_token().unwrap().unwrap();
2319
2320 match token {
2321 Token::Done(done) => {
2322 assert!(done.status.count);
2323 assert!(!done.status.more);
2324 assert_eq!(done.cur_cmd, 193);
2325 assert_eq!(done.row_count, 5);
2326 }
2327 _ => panic!("Expected Done token"),
2328 }
2329
2330 assert!(parser.next_token().unwrap().is_none());
2332 }
2333
2334 #[test]
2335 fn test_env_change_type_from_u8() {
2336 assert_eq!(EnvChangeType::from_u8(1), Some(EnvChangeType::Database));
2337 assert_eq!(EnvChangeType::from_u8(20), Some(EnvChangeType::Routing));
2338 assert_eq!(EnvChangeType::from_u8(100), None);
2339 }
2340
2341 #[test]
2342 fn test_colmetadata_no_columns() {
2343 let data = Bytes::from_static(&[0xFF, 0xFF]);
2345 let mut cursor: &[u8] = &data;
2346 let meta = ColMetaData::decode(&mut cursor).unwrap();
2347 assert!(meta.is_empty());
2348 assert_eq!(meta.column_count(), 0);
2349 }
2350
2351 #[test]
2352 fn test_colmetadata_single_int_column() {
2353 let mut data = BytesMut::new();
2356 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;
2365 let meta = ColMetaData::decode(&mut cursor).unwrap();
2366
2367 assert_eq!(meta.column_count(), 1);
2368 assert_eq!(meta.columns[0].name, "id");
2369 assert_eq!(meta.columns[0].type_id, TypeId::Int4);
2370 assert!(meta.columns[0].is_nullable());
2371 }
2372
2373 #[test]
2374 fn test_colmetadata_nvarchar_column() {
2375 let mut data = BytesMut::new();
2377 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]);
2387
2388 let mut cursor: &[u8] = &data;
2389 let meta = ColMetaData::decode(&mut cursor).unwrap();
2390
2391 assert_eq!(meta.column_count(), 1);
2392 assert_eq!(meta.columns[0].name, "name");
2393 assert_eq!(meta.columns[0].type_id, TypeId::NVarChar);
2394 assert_eq!(meta.columns[0].type_info.max_length, Some(100));
2395 assert!(meta.columns[0].type_info.collation.is_some());
2396 }
2397
2398 #[test]
2399 fn test_raw_row_decode_int() {
2400 let metadata = ColMetaData {
2402 columns: vec![ColumnData {
2403 name: "id".to_string(),
2404 type_id: TypeId::Int4,
2405 col_type: 0x38,
2406 flags: 0,
2407 user_type: 0,
2408 type_info: TypeInfo::default(),
2409 }],
2410 };
2411
2412 let data = Bytes::from_static(&[0x2A, 0x00, 0x00, 0x00]); let mut cursor: &[u8] = &data;
2415 let row = RawRow::decode(&mut cursor, &metadata).unwrap();
2416
2417 assert_eq!(row.data.len(), 4);
2419 assert_eq!(&row.data[..], &[0x2A, 0x00, 0x00, 0x00]);
2420 }
2421
2422 #[test]
2423 fn test_raw_row_decode_nullable_int() {
2424 let metadata = ColMetaData {
2426 columns: vec![ColumnData {
2427 name: "id".to_string(),
2428 type_id: TypeId::IntN,
2429 col_type: 0x26,
2430 flags: 0x01, user_type: 0,
2432 type_info: TypeInfo {
2433 max_length: Some(4),
2434 ..Default::default()
2435 },
2436 }],
2437 };
2438
2439 let data = Bytes::from_static(&[0x04, 0x2A, 0x00, 0x00, 0x00]); let mut cursor: &[u8] = &data;
2442 let row = RawRow::decode(&mut cursor, &metadata).unwrap();
2443
2444 assert_eq!(row.data.len(), 5);
2445 assert_eq!(row.data[0], 4); assert_eq!(&row.data[1..], &[0x2A, 0x00, 0x00, 0x00]);
2447 }
2448
2449 #[test]
2450 fn test_raw_row_decode_null_value() {
2451 let metadata = ColMetaData {
2453 columns: vec![ColumnData {
2454 name: "id".to_string(),
2455 type_id: TypeId::IntN,
2456 col_type: 0x26,
2457 flags: 0x01, user_type: 0,
2459 type_info: TypeInfo {
2460 max_length: Some(4),
2461 ..Default::default()
2462 },
2463 }],
2464 };
2465
2466 let data = Bytes::from_static(&[0xFF]);
2468 let mut cursor: &[u8] = &data;
2469 let row = RawRow::decode(&mut cursor, &metadata).unwrap();
2470
2471 assert_eq!(row.data.len(), 1);
2472 assert_eq!(row.data[0], 0xFF); }
2474
2475 #[test]
2476 fn test_nbcrow_null_bitmap() {
2477 let row = NbcRow {
2478 null_bitmap: vec![0b00000101], data: Bytes::new(),
2480 };
2481
2482 assert!(row.is_null(0));
2483 assert!(!row.is_null(1));
2484 assert!(row.is_null(2));
2485 assert!(!row.is_null(3));
2486 }
2487
2488 #[test]
2489 fn test_token_parser_colmetadata() {
2490 let mut data = BytesMut::new();
2492 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());
2501 let token = parser.next_token().unwrap().unwrap();
2502
2503 match token {
2504 Token::ColMetaData(meta) => {
2505 assert_eq!(meta.column_count(), 1);
2506 assert_eq!(meta.columns[0].name, "id");
2507 assert_eq!(meta.columns[0].type_id, TypeId::Int4);
2508 }
2509 _ => panic!("Expected ColMetaData token"),
2510 }
2511 }
2512
2513 #[test]
2514 fn test_token_parser_row_with_metadata() {
2515 let metadata = ColMetaData {
2517 columns: vec![ColumnData {
2518 name: "id".to_string(),
2519 type_id: TypeId::Int4,
2520 col_type: 0x38,
2521 flags: 0,
2522 user_type: 0,
2523 type_info: TypeInfo::default(),
2524 }],
2525 };
2526
2527 let mut data = BytesMut::new();
2529 data.extend_from_slice(&[0xD1]); data.extend_from_slice(&[0x2A, 0x00, 0x00, 0x00]); let mut parser = TokenParser::new(data.freeze());
2533 let token = parser
2534 .next_token_with_metadata(Some(&metadata))
2535 .unwrap()
2536 .unwrap();
2537
2538 match token {
2539 Token::Row(row) => {
2540 assert_eq!(row.data.len(), 4);
2541 }
2542 _ => panic!("Expected Row token"),
2543 }
2544 }
2545
2546 #[test]
2547 fn test_token_parser_row_without_metadata_fails() {
2548 let mut data = BytesMut::new();
2550 data.extend_from_slice(&[0xD1]); data.extend_from_slice(&[0x2A, 0x00, 0x00, 0x00]); let mut parser = TokenParser::new(data.freeze());
2554 let result = parser.next_token(); assert!(result.is_err());
2557 }
2558
2559 #[test]
2560 fn test_token_parser_peek() {
2561 let data = Bytes::from_static(&[
2562 0xFD, 0x10, 0x00, 0xC1, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ]);
2567
2568 let parser = TokenParser::new(data);
2569 assert_eq!(parser.peek_token_type(), Some(TokenType::Done));
2570 }
2571
2572 #[test]
2573 fn test_column_data_fixed_size() {
2574 let col = ColumnData {
2575 name: String::new(),
2576 type_id: TypeId::Int4,
2577 col_type: 0x38,
2578 flags: 0,
2579 user_type: 0,
2580 type_info: TypeInfo::default(),
2581 };
2582 assert_eq!(col.fixed_size(), Some(4));
2583
2584 let col2 = ColumnData {
2585 name: String::new(),
2586 type_id: TypeId::NVarChar,
2587 col_type: 0xE7,
2588 flags: 0,
2589 user_type: 0,
2590 type_info: TypeInfo::default(),
2591 };
2592 assert_eq!(col2.fixed_size(), None);
2593 }
2594
2595 #[test]
2603 fn test_decode_nvarchar_then_intn_roundtrip() {
2604 let mut wire_data = BytesMut::new();
2609
2610 let word = "World";
2613 let utf16: Vec<u16> = word.encode_utf16().collect();
2614 wire_data.put_u16_le((utf16.len() * 2) as u16); for code_unit in &utf16 {
2616 wire_data.put_u16_le(*code_unit);
2617 }
2618
2619 wire_data.put_u8(4); wire_data.put_i32_le(42);
2622
2623 let metadata = ColMetaData {
2625 columns: vec![
2626 ColumnData {
2627 name: "greeting".to_string(),
2628 type_id: TypeId::NVarChar,
2629 col_type: 0xE7,
2630 flags: 0x01,
2631 user_type: 0,
2632 type_info: TypeInfo {
2633 max_length: Some(10), precision: None,
2635 scale: None,
2636 collation: None,
2637 },
2638 },
2639 ColumnData {
2640 name: "number".to_string(),
2641 type_id: TypeId::IntN,
2642 col_type: 0x26,
2643 flags: 0x01,
2644 user_type: 0,
2645 type_info: TypeInfo {
2646 max_length: Some(4),
2647 precision: None,
2648 scale: None,
2649 collation: None,
2650 },
2651 },
2652 ],
2653 };
2654
2655 let mut wire_cursor = wire_data.freeze();
2657 let raw_row = RawRow::decode(&mut wire_cursor, &metadata).unwrap();
2658
2659 assert_eq!(
2661 wire_cursor.remaining(),
2662 0,
2663 "wire data should be fully consumed"
2664 );
2665
2666 let mut stored_cursor: &[u8] = &raw_row.data;
2668
2669 assert!(
2672 stored_cursor.remaining() >= 2,
2673 "need at least 2 bytes for length"
2674 );
2675 let len0 = stored_cursor.get_u16_le() as usize;
2676 assert_eq!(len0, 10, "NVarChar length should be 10 bytes");
2677 assert!(
2678 stored_cursor.remaining() >= len0,
2679 "need {len0} bytes for data"
2680 );
2681
2682 let mut utf16_read = Vec::new();
2684 for _ in 0..(len0 / 2) {
2685 utf16_read.push(stored_cursor.get_u16_le());
2686 }
2687 let string0 = String::from_utf16(&utf16_read).unwrap();
2688 assert_eq!(string0, "World", "column 0 should be 'World'");
2689
2690 assert!(
2693 stored_cursor.remaining() >= 1,
2694 "need at least 1 byte for length"
2695 );
2696 let len1 = stored_cursor.get_u8();
2697 assert_eq!(len1, 4, "IntN length should be 4");
2698 assert!(stored_cursor.remaining() >= 4, "need 4 bytes for INT data");
2699 let int1 = stored_cursor.get_i32_le();
2700 assert_eq!(int1, 42, "column 1 should be 42");
2701
2702 assert_eq!(
2704 stored_cursor.remaining(),
2705 0,
2706 "stored data should be fully consumed"
2707 );
2708 }
2709
2710 #[test]
2711 fn test_decode_nvarchar_max_then_intn_roundtrip() {
2712 let mut wire_data = BytesMut::new();
2716
2717 let word = "Hello";
2720 let utf16: Vec<u16> = word.encode_utf16().collect();
2721 let byte_len = (utf16.len() * 2) as u64;
2722
2723 wire_data.put_u64_le(byte_len); wire_data.put_u32_le(byte_len as u32); for code_unit in &utf16 {
2726 wire_data.put_u16_le(*code_unit);
2727 }
2728 wire_data.put_u32_le(0); wire_data.put_u8(4);
2732 wire_data.put_i32_le(99);
2733
2734 let metadata = ColMetaData {
2736 columns: vec![
2737 ColumnData {
2738 name: "text".to_string(),
2739 type_id: TypeId::NVarChar,
2740 col_type: 0xE7,
2741 flags: 0x01,
2742 user_type: 0,
2743 type_info: TypeInfo {
2744 max_length: Some(0xFFFF), precision: None,
2746 scale: None,
2747 collation: None,
2748 },
2749 },
2750 ColumnData {
2751 name: "num".to_string(),
2752 type_id: TypeId::IntN,
2753 col_type: 0x26,
2754 flags: 0x01,
2755 user_type: 0,
2756 type_info: TypeInfo {
2757 max_length: Some(4),
2758 precision: None,
2759 scale: None,
2760 collation: None,
2761 },
2762 },
2763 ],
2764 };
2765
2766 let mut wire_cursor = wire_data.freeze();
2768 let raw_row = RawRow::decode(&mut wire_cursor, &metadata).unwrap();
2769
2770 assert_eq!(
2772 wire_cursor.remaining(),
2773 0,
2774 "wire data should be fully consumed"
2775 );
2776
2777 let mut stored_cursor: &[u8] = &raw_row.data;
2779
2780 let total_len = stored_cursor.get_u64_le();
2782 assert_eq!(total_len, 10, "PLP total length should be 10");
2783
2784 let chunk_len = stored_cursor.get_u32_le();
2785 assert_eq!(chunk_len, 10, "PLP chunk length should be 10");
2786
2787 let mut utf16_read = Vec::new();
2788 for _ in 0..(chunk_len / 2) {
2789 utf16_read.push(stored_cursor.get_u16_le());
2790 }
2791 let string0 = String::from_utf16(&utf16_read).unwrap();
2792 assert_eq!(string0, "Hello", "column 0 should be 'Hello'");
2793
2794 let terminator = stored_cursor.get_u32_le();
2795 assert_eq!(terminator, 0, "PLP should end with 0");
2796
2797 let len1 = stored_cursor.get_u8();
2799 assert_eq!(len1, 4);
2800 let int1 = stored_cursor.get_i32_le();
2801 assert_eq!(int1, 99, "column 1 should be 99");
2802
2803 assert_eq!(
2805 stored_cursor.remaining(),
2806 0,
2807 "stored data should be fully consumed"
2808 );
2809 }
2810}