taos_query/common/raw/views/
var_char_view.rs1use std::{ffi::c_void, fmt::Debug};
2
3use super::{IsColumnView, Offsets};
4use crate::{
5 common::{BorrowedValue, Ty},
6 prelude::InlinableWrite,
7 util::InlineStr,
8};
9
10use bytes::Bytes;
11use itertools::Itertools;
12
13#[derive(Debug, Clone)]
14pub struct VarCharView {
15 pub(crate) offsets: Offsets,
17 pub(crate) data: Bytes,
18}
19
20impl IsColumnView for VarCharView {
21 fn ty(&self) -> Ty {
22 Ty::VarChar
23 }
24 fn from_borrowed_value_iter<'b>(iter: impl Iterator<Item = BorrowedValue<'b>>) -> Self {
25 Self::from_iter::<String, _, _, _>(
26 iter.map(|v| v.to_str().map(|v| v.into_owned()))
27 .collect_vec(),
28 )
29 }
30}
31
32impl VarCharView {
33 pub fn len(&self) -> usize {
34 self.offsets.len()
35 }
36
37 pub fn is_null_iter(&self) -> VarCharNullsIter {
39 VarCharNullsIter { view: self, row: 0 }
40 }
41
42 pub fn to_nulls_vec(&self) -> Vec<bool> {
44 self.is_null_iter().collect()
45 }
46
47 pub fn is_null(&self, row: usize) -> bool {
51 if row < self.len() {
52 unsafe { self.is_null_unchecked(row) }
53 } else {
54 false
55 }
56 }
57
58 pub(crate) unsafe fn is_null_unchecked(&self, row: usize) -> bool {
60 self.offsets.get_unchecked(row) < 0
61 }
62
63 pub(crate) unsafe fn get_unchecked(&self, row: usize) -> Option<&InlineStr> {
64 let offset = self.offsets.get_unchecked(row);
65 if offset >= 0 {
66 Some(InlineStr::<u16>::from_ptr(
67 self.data.as_ptr().offset(offset as isize),
68 ))
69 } else {
70 None
71 }
72 }
73
74 pub(crate) unsafe fn get_value_unchecked(&self, row: usize) -> BorrowedValue {
75 self.get_unchecked(row)
76 .map(|s| BorrowedValue::VarChar(s.as_str()))
77 .unwrap_or(BorrowedValue::Null(Ty::VarChar))
78 }
79
80 pub(crate) unsafe fn get_raw_value_unchecked(&self, row: usize) -> (Ty, u32, *const c_void) {
81 match self.get_unchecked(row) {
82 Some(s) => (Ty::VarChar, s.len() as _, s.as_ptr() as _),
83 None => (Ty::VarChar, 0, std::ptr::null()),
84 }
85 }
86
87 #[inline]
88 pub unsafe fn get_length_unchecked(&self, row: usize) -> Option<usize> {
89 let offset = self.offsets.get_unchecked(row);
90 if offset >= 0 {
91 Some(InlineStr::<u16>::from_ptr(self.data.as_ptr().offset(offset as isize)).len())
92 } else {
93 None
94 }
95 }
96
97 #[inline]
98 pub fn lengths(&self) -> Vec<Option<usize>> {
99 (0..self.len())
100 .map(|i| unsafe { self.get_length_unchecked(i) })
101 .collect()
102 }
103
104 #[inline]
105 pub fn max_length(&self) -> usize {
106 (0..self.len())
107 .filter_map(|i| unsafe { self.get_length_unchecked(i) })
108 .min()
109 .unwrap_or(0)
110 }
111
112 pub fn slice(&self, mut range: std::ops::Range<usize>) -> Option<Self> {
113 if range.start >= self.len() {
114 return None;
115 }
116 if range.end > self.len() {
117 range.end = self.len();
118 }
119 if range.is_empty() {
120 return None;
121 }
122 let (offsets, range) = unsafe { self.offsets.slice_unchecked(range.clone()) };
123 if let Some(range) = range {
124 let range = range.0 as usize..range.1.map(|v| v as usize).unwrap_or(self.data.len());
125 let data = self.data.slice(range);
126 Some(Self { offsets, data })
127 } else {
128 let data = self.data.slice(0..0);
129 Some(Self { offsets, data })
130 }
131 }
132
133 pub fn iter(&self) -> VarCharIter {
134 VarCharIter { view: self, row: 0 }
135 }
136
137 pub fn to_vec(&self) -> Vec<Option<String>> {
138 (0..self.len())
139 .map(|row| unsafe { self.get_unchecked(row) }.map(|s| s.to_string()))
140 .collect()
141 }
142 pub fn iter_as_bytes(&self) -> impl Iterator<Item = Option<&[u8]>> {
143 (0..self.len()).map(|row| unsafe { self.get_unchecked(row) }.map(|s| s.as_bytes()))
144 }
145
146 pub fn to_bytes_vec(&self) -> Vec<Option<&[u8]>> {
147 self.iter_as_bytes().collect_vec()
148 }
149
150 pub(crate) fn write_raw_into<W: std::io::Write>(&self, mut wtr: W) -> std::io::Result<usize> {
152 let mut offsets = Vec::with_capacity(self.len());
153 let mut bytes: Vec<u8> = Vec::new();
154 for v in self.iter() {
155 if let Some(v) = v {
156 offsets.push(bytes.len() as i32);
157 bytes.write_inlined_str::<2>(v.as_str()).unwrap();
158 } else {
159 offsets.push(-1);
160 }
161 }
162 unsafe {
163 let offsets_bytes = std::slice::from_raw_parts(
164 offsets.as_ptr() as *const u8,
165 offsets.len() * std::mem::size_of::<i32>(),
166 );
167 wtr.write_all(offsets_bytes)?;
168 wtr.write_all(&bytes)?;
169 Ok(offsets_bytes.len() + bytes.len())
170 }
171 }
177
178 pub fn from_iter<
179 S: AsRef<str>,
180 T: Into<Option<S>>,
181 I: ExactSizeIterator<Item = T>,
182 V: IntoIterator<Item = T, IntoIter = I>,
183 >(
184 iter: V,
185 ) -> Self {
186 let iter = iter.into_iter();
187 let mut offsets = Vec::with_capacity(iter.len());
188 let mut data = Vec::new();
189
190 for i in iter.map(|v| v.into()) {
191 if let Some(s) = i {
192 let s: &str = s.as_ref();
193 offsets.push(data.len() as i32);
194 data.write_inlined_str::<2>(s).unwrap();
195 } else {
196 offsets.push(-1);
197 }
198 }
199 let offsets_bytes = unsafe {
201 Vec::from_raw_parts(
202 offsets.as_mut_ptr() as *mut u8,
203 offsets.len() * 4,
204 offsets.capacity() * 4,
205 )
206 };
207 std::mem::forget(offsets);
208 VarCharView {
209 offsets: Offsets(offsets_bytes.into()),
210 data: data.into(),
211 }
212 }
213
214 pub fn concat(&self, rhs: &Self) -> Self {
215 Self::from_iter::<&InlineStr, _, _, _>(self.iter().chain(rhs.iter()).collect_vec())
216 }
217}
218
219pub struct VarCharIter<'a> {
220 view: &'a VarCharView,
221 row: usize,
222}
223
224impl<'a> Iterator for VarCharIter<'a> {
225 type Item = Option<&'a InlineStr>;
226
227 fn next(&mut self) -> Option<Self::Item> {
228 if self.row < self.view.len() {
229 let row = self.row;
230 self.row += 1;
231 Some(unsafe { self.view.get_unchecked(row) })
232 } else {
233 None
234 }
235 }
236
237 fn size_hint(&self) -> (usize, Option<usize>) {
238 let len = self.view.len() - self.row;
239 (len, Some(len))
240 }
241}
242
243impl<'a> ExactSizeIterator for VarCharIter<'a> {}
244
245pub struct VarCharNullsIter<'a> {
246 view: &'a VarCharView,
247 row: usize,
248}
249
250impl<'a> Iterator for VarCharNullsIter<'a> {
251 type Item = bool;
252
253 fn next(&mut self) -> Option<Self::Item> {
254 if self.row < self.view.len() {
255 let row = self.row;
256 self.row += 1;
257 Some(unsafe { self.view.is_null_unchecked(row) })
258 } else {
259 None
260 }
261 }
262}
263
264impl<'a> ExactSizeIterator for VarCharNullsIter<'a> {
265 fn len(&self) -> usize {
266 self.view.len() - self.row
267 }
268}
269
270#[test]
271fn test_slice() {
272 let data = [None, Some(""), Some("abc"), Some("中文"), None, None, Some("a loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooog string")];
273 let view = VarCharView::from_iter::<&str, _, _, _>(data);
274 let slice = view.slice(0..0);
275 assert!(slice.is_none());
276 let slice = view.slice(100..1000);
277 assert!(slice.is_none());
278
279 for start in 0..data.len() {
280 let end = start + 1;
281 for end in end..data.len() {
282 let slice = view.slice(start..end).unwrap();
283 assert_eq!(
284 slice.to_vec().as_slice(),
285 &data[start..end]
286 .iter()
287 .map(|s| s.map(ToString::to_string))
288 .collect_vec()
289 );
290 }
291 }
292}