tiberius/tds/codec/token/
token_row.rs1mod bytes_mut_with_data_columns;
2mod into_row;
3use crate::tds::codec::encode::Encode;
4use crate::{tds::codec::ColumnData, BytesMutWithTypeInfo, SqlReadBytes, TokenType};
5use bytes::BufMut;
6pub(crate) use bytes_mut_with_data_columns::BytesMutWithDataColumns;
7use futures_util::io::AsyncReadExt;
8pub use into_row::IntoRow;
9
10#[derive(Debug, Default, Clone)]
12pub struct TokenRow<'a> {
13 data: Vec<ColumnData<'a>>,
14}
15
16impl<'a> IntoIterator for TokenRow<'a> {
17 type Item = ColumnData<'a>;
18 type IntoIter = std::vec::IntoIter<Self::Item>;
19
20 fn into_iter(self) -> Self::IntoIter {
21 self.data.into_iter()
22 }
23}
24
25impl<'a> Encode<BytesMutWithDataColumns<'a>> for TokenRow<'a> {
26 fn encode(self, dst: &mut BytesMutWithDataColumns<'a>) -> crate::Result<()> {
27 dst.put_u8(TokenType::Row as u8);
28
29 if self.data.len() != dst.data_columns().len() {
30 return Err(crate::Error::BulkInput(
31 format!(
32 "Expecting {} columns but {} were given",
33 dst.data_columns().len(),
34 self.data.len()
35 )
36 .into(),
37 ));
38 }
39
40 for (value, column) in self.data.into_iter().zip(dst.data_columns()) {
41 let mut dst_ti = BytesMutWithTypeInfo::new(dst).with_type_info(&column.base.ty);
42 value.encode(&mut dst_ti)?
43 }
44
45 Ok(())
46 }
47}
48
49impl<'a> TokenRow<'a> {
50 pub const fn new() -> Self {
52 Self { data: Vec::new() }
53 }
54
55 pub fn with_capacity(capacity: usize) -> Self {
57 Self {
58 data: Vec::with_capacity(capacity),
59 }
60 }
61
62 pub fn clear(&mut self) {
66 self.data.clear();
67 }
68
69 pub fn len(&self) -> usize {
71 self.data.len()
72 }
73
74 pub fn iter(&self) -> std::slice::Iter<'_, ColumnData<'a>> {
76 self.data.iter()
77 }
78
79 pub fn is_empty(&self) -> bool {
81 self.data.is_empty()
82 }
83
84 pub fn get(&self, index: usize) -> Option<&ColumnData<'a>> {
87 self.data.get(index)
88 }
89
90 pub fn push(&mut self, value: ColumnData<'a>) {
92 self.data.push(value);
93 }
94}
95
96impl TokenRow<'static> {
97 pub(crate) async fn decode<R>(src: &mut R) -> crate::Result<Self>
100 where
101 R: SqlReadBytes + Unpin,
102 {
103 let col_meta = src.context().last_meta().unwrap();
104
105 let mut row = Self {
106 data: Vec::with_capacity(col_meta.columns.len()),
107 };
108
109 for column in col_meta.columns.iter() {
110 let data = ColumnData::decode(src, &column.base.ty).await?;
111 row.data.push(data);
112 }
113
114 Ok(row)
115 }
116
117 pub(crate) async fn decode_nbc<R>(src: &mut R) -> crate::Result<Self>
120 where
121 R: SqlReadBytes + Unpin,
122 {
123 let col_meta = src.context().last_meta().unwrap();
124 let row_bitmap = RowBitmap::decode(src, col_meta.columns.len()).await?;
125
126 let mut row = Self {
127 data: Vec::with_capacity(col_meta.columns.len()),
128 };
129
130 for (i, column) in col_meta.columns.iter().enumerate() {
131 let data = if row_bitmap.is_null(i) {
132 column.base.null_value()
133 } else {
134 ColumnData::decode(src, &column.base.ty).await?
135 };
136
137 row.data.push(data);
138 }
139
140 Ok(row)
141 }
142}
143
144struct RowBitmap {
161 data: Vec<u8>,
162}
163
164impl RowBitmap {
165 #[inline]
167 fn is_null(&self, i: usize) -> bool {
168 let index = i / 8;
169 let bit = i % 8;
170
171 self.data[index] & (1 << bit) > 0
172 }
173
174 async fn decode<R>(src: &mut R, columns: usize) -> crate::Result<Self>
177 where
178 R: SqlReadBytes + Unpin,
179 {
180 let size = (columns + 8 - 1) / 8;
181 let mut data = vec![0; size];
182 src.read_exact(&mut data[0..size]).await?;
183
184 Ok(Self { data })
185 }
186}
187
188#[cfg(test)]
189mod tests {
190 use super::*;
191 use crate::{BaseMetaDataColumn, ColumnFlag, FixedLenType, MetaDataColumn, TypeInfo};
192 use bytes::BytesMut;
193
194 #[tokio::test]
195 async fn wrong_number_of_columns_will_fail() {
196 let row = (true, 5).into_row();
197 let columns = vec![MetaDataColumn {
198 base: BaseMetaDataColumn {
199 flags: ColumnFlag::Nullable.into(),
200 ty: TypeInfo::FixedLen(FixedLenType::Bit),
201 },
202 col_name: Default::default(),
203 }];
204 let mut buf = BytesMut::new();
205 let mut buf_with_columns = BytesMutWithDataColumns::new(&mut buf, &columns);
206
207 row.encode(&mut buf_with_columns)
208 .expect_err("wrong number of columns");
209 }
210}