1use crate::null_sentinel;
19use arrow_array::types::ByteArrayType;
20use arrow_array::*;
21use arrow_buffer::bit_util::ceil;
22use arrow_buffer::{
23 ArrowNativeType, BooleanBuffer, MutableBuffer, NullBuffer, OffsetBuffer, ScalarBuffer,
24};
25use arrow_data::MAX_INLINE_VIEW_LEN;
26use arrow_schema::{ArrowError, SortOptions};
27use builder::make_view;
28
29pub const BLOCK_SIZE: usize = 32;
31
32pub const MINI_BLOCK_COUNT: usize = 4;
36
37pub const MINI_BLOCK_SIZE: usize = BLOCK_SIZE / MINI_BLOCK_COUNT;
39
40pub const BLOCK_CONTINUATION: u8 = 0xFF;
42
43pub const EMPTY_SENTINEL: u8 = 1;
45
46pub const NON_EMPTY_SENTINEL: u8 = 2;
48
49pub const NULL_VALUE_SENTINEL: u8 = 3;
51
52#[inline]
54pub fn padded_length(a: Option<usize>) -> usize {
55 match a {
56 Some(a) => non_null_padded_length(a),
57 None => 1,
58 }
59}
60
61#[inline]
63pub(crate) fn non_null_padded_length(len: usize) -> usize {
64 if len <= BLOCK_SIZE {
65 1 + ceil(len, MINI_BLOCK_SIZE) * (MINI_BLOCK_SIZE + 1)
66 } else {
67 MINI_BLOCK_COUNT + ceil(len, BLOCK_SIZE) * (BLOCK_SIZE + 1)
70 }
71}
72
73pub(crate) fn decode_nulls_sentinel(rows: &[&[u8]], options: SortOptions) -> Option<NullBuffer> {
76 let null_sentinel = null_sentinel(options);
77 let nulls = BooleanBuffer::collect_bool(rows.len(), |x| rows[x][0] != null_sentinel);
78 let nulls = NullBuffer::new(nulls);
79 (nulls.null_count() > 0).then_some(nulls)
80}
81
82pub fn encode<'a, I: Iterator<Item = Option<&'a [u8]>>>(
94 data: &mut [u8],
95 offsets: &mut [usize],
96 i: I,
97 opts: SortOptions,
98) {
99 for (offset, maybe_val) in offsets.iter_mut().skip(1).zip(i) {
100 *offset += encode_one(&mut data[*offset..], maybe_val, opts);
101 }
102}
103
104pub(crate) fn encode_generic_byte_array<T: ByteArrayType>(
106 data: &mut [u8],
107 offsets: &mut [usize],
108 input_array: &GenericByteArray<T>,
109 opts: SortOptions,
110) {
111 let input_offsets = input_array.value_offsets();
112 let bytes = input_array.values().as_slice();
113
114 if let Some(null_buffer) = input_array.nulls().filter(|x| x.null_count() > 0) {
115 let input_iter =
116 input_offsets
117 .windows(2)
118 .zip(null_buffer.iter())
119 .map(|(start_end, is_valid)| {
120 if is_valid {
121 let item_range = start_end[0].as_usize()..start_end[1].as_usize();
122 let item = unsafe { bytes.get_unchecked(item_range) };
125 Some(item)
126 } else {
127 None
128 }
129 });
130
131 encode(data, offsets, input_iter, opts);
132 } else {
133 let input_iter = input_offsets.windows(2).map(|start_end| {
135 let item_range = start_end[0].as_usize()..start_end[1].as_usize();
136 let item = unsafe { bytes.get_unchecked(item_range) };
139 Some(item)
140 });
141
142 encode(data, offsets, input_iter, opts);
143 }
144}
145
146pub fn encode_null(out: &mut [u8], opts: SortOptions) -> usize {
147 out[0] = null_sentinel(opts);
148 1
149}
150
151pub fn encode_empty(out: &mut [u8], opts: SortOptions) -> usize {
152 out[0] = match opts.descending {
153 true => !EMPTY_SENTINEL,
154 false => EMPTY_SENTINEL,
155 };
156 1
157}
158
159pub fn encode_null_value(out: &mut [u8], opts: SortOptions) -> usize {
161 out[0] = match opts.descending {
162 true => !NON_EMPTY_SENTINEL,
163 false => NON_EMPTY_SENTINEL,
164 };
165 out[1] = match opts.descending {
166 true => !NULL_VALUE_SENTINEL,
167 false => NULL_VALUE_SENTINEL,
168 };
169 2
170}
171
172#[inline]
173pub fn encode_one(out: &mut [u8], val: Option<&[u8]>, opts: SortOptions) -> usize {
174 match val {
175 None => encode_null(out, opts),
176 Some([]) => encode_empty(out, opts),
177 Some(val) => {
178 out[0] = NON_EMPTY_SENTINEL;
180
181 let len = if val.len() <= BLOCK_SIZE {
182 1 + encode_blocks::<MINI_BLOCK_SIZE>(&mut out[1..], val)
183 } else {
184 let (initial, rem) = val.split_at(BLOCK_SIZE);
185 let offset = encode_blocks::<MINI_BLOCK_SIZE>(&mut out[1..], initial);
186 out[offset] = BLOCK_CONTINUATION;
187 1 + offset + encode_blocks::<BLOCK_SIZE>(&mut out[1 + offset..], rem)
188 };
189
190 if opts.descending {
191 out[..len].iter_mut().for_each(|v| *v = !*v)
193 }
194 len
195 }
196 }
197}
198
199#[inline]
201fn encode_blocks<const SIZE: usize>(out: &mut [u8], val: &[u8]) -> usize {
202 let block_count = ceil(val.len(), SIZE);
203 let end_offset = block_count * (SIZE + 1);
204 let to_write = &mut out[..end_offset];
205
206 let (chunks, remainder) = val.as_chunks::<SIZE>();
207 let to_write_chunks = to_write.chunks_exact_mut(SIZE + 1);
208 for (input, output) in chunks.iter().zip(to_write_chunks) {
209 let out_block: &mut [u8; SIZE] = (&mut output[..SIZE]).try_into().unwrap();
210
211 *out_block = *input;
212
213 output[SIZE] = BLOCK_CONTINUATION;
215 }
216
217 if !remainder.is_empty() {
218 let start_offset = (block_count - 1) * (SIZE + 1);
219 to_write[start_offset..start_offset + remainder.len()].copy_from_slice(remainder);
220 *to_write.last_mut().unwrap() = remainder.len() as u8;
221 } else {
222 *to_write.last_mut().unwrap() = SIZE as u8;
224 }
225 end_offset
226}
227
228pub fn decode_blocks(row: &[u8], options: SortOptions, mut f: impl FnMut(&[u8])) -> usize {
231 let (non_empty_sentinel, continuation) = match options.descending {
232 true => (!NON_EMPTY_SENTINEL, !BLOCK_CONTINUATION),
233 false => (NON_EMPTY_SENTINEL, BLOCK_CONTINUATION),
234 };
235
236 if row[0] != non_empty_sentinel {
237 return 1;
239 }
240
241 let block_len = |sentinel: u8| match options.descending {
243 true => !sentinel as usize,
244 false => sentinel as usize,
245 };
246
247 let mut idx = 1;
248 for _ in 0..MINI_BLOCK_COUNT {
249 let sentinel = row[idx + MINI_BLOCK_SIZE];
250 if sentinel != continuation {
251 f(&row[idx..idx + block_len(sentinel)]);
252 return idx + MINI_BLOCK_SIZE + 1;
253 }
254 f(&row[idx..idx + MINI_BLOCK_SIZE]);
255 idx += MINI_BLOCK_SIZE + 1;
256 }
257
258 loop {
259 let sentinel = row[idx + BLOCK_SIZE];
260 if sentinel != continuation {
261 f(&row[idx..idx + block_len(sentinel)]);
262 return idx + BLOCK_SIZE + 1;
263 }
264 f(&row[idx..idx + BLOCK_SIZE]);
265 idx += BLOCK_SIZE + 1;
266 }
267}
268
269fn decoded_len(row: &[u8], options: SortOptions) -> usize {
271 let mut len = 0;
272 decode_blocks(row, options, |block| len += block.len());
273 len
274}
275
276pub fn decode_binary<I: OffsetSizeTrait>(
278 rows: &mut [&[u8]],
279 options: SortOptions,
280) -> GenericBinaryArray<I> {
281 let len = rows.len();
282 let nulls = decode_nulls_sentinel(rows, options);
283
284 let values_capacity = rows.iter().map(|row| decoded_len(row, options)).sum();
285 let mut offsets = Vec::<I>::with_capacity(len + 1);
286 offsets.push(I::zero());
287 let mut values = MutableBuffer::new(values_capacity);
288
289 for row in rows {
290 let offset = decode_blocks(row, options, |b| values.extend_from_slice(b));
291 *row = &row[offset..];
292 offsets.push(I::from_usize(values.len()).expect("offset overflow"))
293 }
294
295 if options.descending {
296 values.as_slice_mut().iter_mut().for_each(|o| *o = !*o)
297 }
298
299 unsafe {
302 GenericBinaryArray::new_unchecked(
303 OffsetBuffer::new(ScalarBuffer::from(offsets)),
304 values.into(),
305 nulls,
306 )
307 }
308}
309
310fn decode_binary_view_inner<const VALIDATE_UTF8: bool>(
311 rows: &mut [&[u8]],
312 options: SortOptions,
313) -> Result<BinaryViewArray, ArrowError> {
314 let len = rows.len();
315 let inline_str_max_len = MAX_INLINE_VIEW_LEN as usize;
316
317 let nulls = decode_nulls_sentinel(rows, options);
318
319 let mut values_capacity = inline_str_max_len;
321 let mut inline_capacity = 0;
322 for row in rows.iter() {
323 let len = decoded_len(row, options);
324 if len > inline_str_max_len {
325 values_capacity += len;
326 } else if VALIDATE_UTF8 {
327 inline_capacity += len;
328 }
329 }
330 let long_values_len = values_capacity - inline_str_max_len;
334 if long_values_len > i32::MAX as usize {
335 return Err(ArrowError::InvalidArgumentError(format!(
336 "{long_values_len} bytes of non-inlined values too long to decode into a view array with a single data buffer"
337 )));
338 }
339 let mut values = MutableBuffer::new(values_capacity);
340 let mut view_utf8_validation_buffer = if VALIDATE_UTF8 {
341 Vec::with_capacity(inline_capacity)
342 } else {
343 Vec::new()
344 };
345
346 let null_sentinel = null_sentinel(options);
347 let mut views = vec![0_u128; len];
348 for (i, row) in rows.iter_mut().enumerate() {
349 let start_offset = values.len();
350 let offset = decode_blocks(row, options, |b| values.extend_from_slice(b));
351 let decoded_len = values.len() - start_offset;
355 if row[0] == null_sentinel {
356 debug_assert_eq!(offset, 1);
357 debug_assert_eq!(start_offset, values.len());
358 } else {
359 let val = unsafe { values.get_unchecked_mut(start_offset..) };
361
362 if options.descending {
363 val.iter_mut().for_each(|o| *o = !*o);
364 }
365
366 views[i] = make_view(val, 0, start_offset as u32);
367
368 if decoded_len <= inline_str_max_len {
369 if VALIDATE_UTF8 {
370 view_utf8_validation_buffer.extend_from_slice(val);
371 }
372 values.truncate(start_offset);
373 }
374 }
375 *row = &row[offset..];
376 }
377
378 if VALIDATE_UTF8 {
379 std::str::from_utf8(&values).unwrap();
380 std::str::from_utf8(&view_utf8_validation_buffer).unwrap();
381 }
382
383 Ok(unsafe { BinaryViewArray::new_unchecked(views.into(), [values.into()].into(), nulls) })
386}
387
388pub fn decode_binary_view(
393 rows: &mut [&[u8]],
394 options: SortOptions,
395) -> Result<BinaryViewArray, ArrowError> {
396 decode_binary_view_inner::<false>(rows, options)
397}
398
399pub unsafe fn decode_string<I: OffsetSizeTrait>(
405 rows: &mut [&[u8]],
406 options: SortOptions,
407 validate_utf8: bool,
408) -> GenericStringArray<I> {
409 let decoded = decode_binary::<I>(rows, options);
410
411 if validate_utf8 {
412 return GenericStringArray::from(decoded);
413 }
414
415 let (offsets, values, nulls) = decoded.into_parts();
416
417 unsafe { GenericStringArray::new_unchecked(offsets, values, nulls) }
420}
421
422pub unsafe fn decode_string_view(
431 rows: &mut [&[u8]],
432 options: SortOptions,
433 validate_utf8: bool,
434) -> Result<StringViewArray, ArrowError> {
435 let view = if validate_utf8 {
436 decode_binary_view_inner::<true>(rows, options)?
437 } else {
438 decode_binary_view_inner::<false>(rows, options)?
439 };
440 Ok(unsafe { view.to_string_view_unchecked() })
441}
442
443pub fn decode_null_value(rows: &mut [&[u8]], options: SortOptions) {
444 for row in rows.iter_mut() {
445 let (sentinel1, sentinel2) = match options.descending {
446 true => (!NON_EMPTY_SENTINEL, !NULL_VALUE_SENTINEL),
447 false => (NON_EMPTY_SENTINEL, NULL_VALUE_SENTINEL),
448 };
449 debug_assert_eq!(row[0], sentinel1, "Expected NULL_VALUE_SENTINEL at byte 0");
450 debug_assert_eq!(row[1], sentinel2, "Expected NULL_VALUE_SENTINEL at byte 1");
451 *row = &row[2..];
452 }
453}