tiberius/tds/codec/token/
token_alt_row.rs1use crate::{
2 tds::codec::{ColumnData, TokenAltMetaData},
3 SqlReadBytes,
4};
5
6#[derive(Debug, Clone)]
15pub struct TokenAltRow<'a> {
16 pub id: u16,
19 data: Vec<ColumnData<'a>>,
20}
21
22impl<'a> TokenAltRow<'a> {
23 pub fn id(&self) -> u16 {
25 self.id
26 }
27
28 pub fn len(&self) -> usize {
30 self.data.len()
31 }
32
33 pub fn is_empty(&self) -> bool {
35 self.data.is_empty()
36 }
37
38 pub fn iter(&self) -> std::slice::Iter<'_, ColumnData<'a>> {
40 self.data.iter()
41 }
42
43 pub fn get(&self, index: usize) -> Option<&ColumnData<'a>> {
45 self.data.get(index)
46 }
47}
48
49impl TokenAltRow<'static> {
50 pub(crate) async fn decode<R>(
56 src: &mut R,
57 id: u16,
58 meta: &TokenAltMetaData<'static>,
59 ) -> crate::Result<Self>
60 where
61 R: SqlReadBytes + Unpin,
62 {
63 let mut data = Vec::with_capacity(meta.columns.len());
64
65 for column in meta.columns.iter() {
66 data.push(ColumnData::decode(src, &column.base.ty).await?);
67 }
68
69 Ok(TokenAltRow { id, data })
70 }
71}
72
73#[cfg(test)]
74mod tests {
75 use std::borrow::Cow;
76
77 use super::*;
78 use crate::{
79 sql_read_bytes::test_utils::IntoSqlReadBytes, AltMetaDataColumn, BaseMetaDataColumn,
80 ColumnFlag, FixedLenType, TypeInfo,
81 };
82 use bytes::{BufMut, BytesMut};
83
84 fn int_alt_meta() -> TokenAltMetaData<'static> {
85 TokenAltMetaData {
86 id: 1,
87 by_columns: vec![],
88 columns: vec![AltMetaDataColumn {
89 op: 0x4f, operand: 1,
91 base: BaseMetaDataColumn {
92 flags: ColumnFlag::Nullable.into(),
93 ty: TypeInfo::FixedLen(FixedLenType::Int4),
94 },
95 col_name: Cow::from("sum"),
96 }],
97 }
98 }
99
100 #[tokio::test]
101 async fn decode_alt_row_reads_values() {
102 let meta = int_alt_meta();
103
104 let mut buf = BytesMut::new();
105 buf.put_i32_le(42); let mut reader = buf.into_sql_read_bytes();
108 let row = TokenAltRow::decode(&mut reader, meta.id, &meta)
109 .await
110 .unwrap();
111
112 assert_eq!(1, row.id());
113 assert_eq!(1, row.len());
114 assert!(matches!(row.get(0), Some(ColumnData::I32(Some(42)))));
115 }
116
117 #[test]
118 fn accessors_reflect_id_and_columns() {
119 let empty = TokenAltRow {
122 id: 5,
123 data: vec![],
124 };
125 assert_eq!(empty.id(), 5);
126 assert_eq!(empty.len(), 0);
127 assert!(empty.is_empty());
128
129 let filled = TokenAltRow {
132 id: 9,
133 data: vec![ColumnData::I32(Some(10)), ColumnData::I32(Some(20))],
134 };
135 assert_eq!(filled.id(), 9);
136 assert_eq!(filled.len(), 2);
137 assert!(!filled.is_empty());
138 }
139}