1use std::any::Any;
5use std::collections::VecDeque;
6use std::fmt::Debug;
7use std::ops::Range;
8use std::sync::Arc;
9use std::vec;
10
11use arrow_buffer::ScalarBuffer;
12use bytes::Bytes;
13use futures::FutureExt;
14use futures::future::BoxFuture;
15use lance_core::Result;
16use lance_core::cache::{Context, DeepSizeOf};
17use lance_core::error::Error;
18
19use crate::EncodingsIo;
20use crate::buffer::LanceBuffer;
21use crate::compression::{BlockDecompressor, DecompressionStrategy, create_rle_decompressor};
22use crate::data::{AllNullDataBlock, DataBlock};
23use crate::decoder::{DecodePageTask, DecodedPage, StructuralPageDecoder};
24use crate::encodings::physical::rle::{RleDecompressor, RleRuns};
25use crate::format::metadata::CompressiveEncoding;
26use crate::format::metadata::compressive_encoding::Compression;
27use crate::repdef::{DefinitionInterpretation, RepDefUnraveler, max_visible_level};
28
29use super::{
30 CachedPageData, NoCachedPageData, PageInitialization, PageInitializationBuffers, PageLoadTask,
31 StructuralPageScheduler,
32};
33
34#[derive(Debug, Clone)]
38pub enum LevelCodec {
39 Uncompressed,
41 Rle(Arc<RleDecompressor>),
43 Block(Arc<dyn BlockDecompressor>),
46}
47
48impl LevelCodec {
49 pub(super) fn try_new(
50 encoding: Option<&CompressiveEncoding>,
51 decompression_strategy: &dyn DecompressionStrategy,
52 ) -> Result<Self> {
53 match encoding {
54 None => Ok(Self::Uncompressed),
55 Some(encoding) => match encoding.compression.as_ref() {
56 Some(Compression::Rle(rle)) => Ok(Self::Rle(Arc::new(create_rle_decompressor(
57 rle,
58 decompression_strategy,
59 )?))),
60 _ => Ok(Self::Block(Arc::from(
61 decompression_strategy.create_block_decompressor(encoding)?,
62 ))),
63 },
64 }
65 }
66}
67
68#[derive(Debug)]
69enum RunEnds {
70 U16(Box<[u16]>),
71 U32(Box<[u32]>),
72 U64(Box<[u64]>),
73}
74
75impl RunEnds {
76 fn width_for(num_values: usize) -> usize {
77 if u16::try_from(num_values).is_ok() {
78 std::mem::size_of::<u16>()
79 } else if u32::try_from(num_values).is_ok() {
80 std::mem::size_of::<u32>()
81 } else {
82 std::mem::size_of::<u64>()
83 }
84 }
85
86 fn len(&self) -> usize {
87 match self {
88 Self::U16(ends) => ends.len(),
89 Self::U32(ends) => ends.len(),
90 Self::U64(ends) => ends.len(),
91 }
92 }
93
94 fn get(&self, run: usize) -> usize {
95 match self {
96 Self::U16(ends) => ends[run] as usize,
97 Self::U32(ends) => ends[run] as usize,
98 Self::U64(ends) => ends[run] as usize,
99 }
100 }
101
102 fn partition_point(&self, logical_index: usize) -> usize {
103 match self {
104 Self::U16(ends) => ends.partition_point(|&end| end as usize <= logical_index),
105 Self::U32(ends) => ends.partition_point(|&end| end as usize <= logical_index),
106 Self::U64(ends) => ends.partition_point(|&end| end as usize <= logical_index),
107 }
108 }
109
110 fn deep_size(&self) -> usize {
111 match self {
112 Self::U16(ends) => std::mem::size_of_val(ends.as_ref()),
113 Self::U32(ends) => std::mem::size_of_val(ends.as_ref()),
114 Self::U64(ends) => std::mem::size_of_val(ends.as_ref()),
115 }
116 }
117}
118
119enum RunEndsBuilder {
120 U16(Vec<u16>),
121 U32(Vec<u32>),
122 U64(Vec<u64>),
123}
124
125impl RunEndsBuilder {
126 fn with_capacity(num_values: usize, capacity: usize) -> Self {
127 if u16::try_from(num_values).is_ok() {
128 Self::U16(Vec::with_capacity(capacity))
129 } else if u32::try_from(num_values).is_ok() {
130 Self::U32(Vec::with_capacity(capacity))
131 } else {
132 Self::U64(Vec::with_capacity(capacity))
133 }
134 }
135
136 fn push(&mut self, end: usize) -> Result<()> {
137 match self {
138 Self::U16(ends) => ends.push(
139 u16::try_from(end)
140 .map_err(|_| Error::internal(format!("Run end {end} does not fit in u16")))?,
141 ),
142 Self::U32(ends) => ends.push(
143 u32::try_from(end)
144 .map_err(|_| Error::internal(format!("Run end {end} does not fit in u32")))?,
145 ),
146 Self::U64(ends) => ends.push(end as u64),
147 }
148 Ok(())
149 }
150
151 fn set_last(&mut self, end: usize) -> Result<()> {
152 match self {
153 Self::U16(ends) => {
154 let last = ends.last_mut().ok_or_else(|| {
155 Error::internal("Cannot extend an empty coalesced run buffer")
156 })?;
157 *last = u16::try_from(end)
158 .map_err(|_| Error::internal(format!("Run end {end} does not fit in u16")))?;
159 }
160 Self::U32(ends) => {
161 let last = ends.last_mut().ok_or_else(|| {
162 Error::internal("Cannot extend an empty coalesced run buffer")
163 })?;
164 *last = u32::try_from(end)
165 .map_err(|_| Error::internal(format!("Run end {end} does not fit in u32")))?;
166 }
167 Self::U64(ends) => {
168 let last = ends.last_mut().ok_or_else(|| {
169 Error::internal("Cannot extend an empty coalesced run buffer")
170 })?;
171 *last = end as u64;
172 }
173 }
174 Ok(())
175 }
176
177 fn finish(self) -> RunEnds {
178 match self {
179 Self::U16(ends) => RunEnds::U16(ends.into_boxed_slice()),
180 Self::U32(ends) => RunEnds::U32(ends.into_boxed_slice()),
181 Self::U64(ends) => RunEnds::U64(ends.into_boxed_slice()),
182 }
183 }
184}
185
186#[derive(Debug)]
187enum RunStorage {
188 Physical(RleRuns),
189 Coalesced { values: Box<[u16]>, ends: RunEnds },
190}
191
192impl RunStorage {
193 fn len(&self) -> usize {
194 match self {
195 Self::Physical(runs) => runs.num_values(),
196 Self::Coalesced { ends, .. } => ends.get(ends.len() - 1),
197 }
198 }
199
200 fn num_runs(&self) -> usize {
201 match self {
202 Self::Physical(runs) => runs.num_runs(),
203 Self::Coalesced { values, .. } => values.len(),
204 }
205 }
206
207 fn value(&self, run: usize) -> u16 {
208 match self {
209 Self::Physical(runs) => runs.value(run),
210 Self::Coalesced { values, .. } => values[run],
211 }
212 }
213
214 fn first_value_above(&self, max: u16) -> Option<(usize, u16)> {
215 (0..self.num_runs()).find_map(|run| {
216 let value = self.value(run);
217 (value > max).then_some((run, value))
218 })
219 }
220
221 fn seek(&self, position: &mut RunPosition, logical_index: usize) {
222 if logical_index >= self.len() {
223 *position = RunPosition {
224 run: self.num_runs(),
225 start: self.len(),
226 end: self.len(),
227 };
228 return;
229 }
230
231 match self {
232 Self::Physical(runs) => {
233 if position.run >= runs.num_runs()
234 || position.end == 0
235 || logical_index < position.start
236 {
237 *position = RunPosition {
238 run: 0,
239 start: 0,
240 end: runs.length(0),
241 };
242 }
243 while position.end <= logical_index {
244 self.advance(position);
245 }
246 }
247 Self::Coalesced { ends, .. } => {
248 if logical_index < position.start || logical_index >= position.end {
249 let run = ends.partition_point(logical_index);
250 *position = RunPosition {
251 run,
252 start: if run == 0 { 0 } else { ends.get(run - 1) },
253 end: ends.get(run),
254 };
255 }
256 }
257 }
258 }
259
260 fn advance(&self, position: &mut RunPosition) {
261 let next_run = position.run + 1;
262 if next_run >= self.num_runs() {
263 *position = RunPosition {
264 run: self.num_runs(),
265 start: self.len(),
266 end: self.len(),
267 };
268 return;
269 }
270
271 let start = position.end;
272 position.run = next_run;
273 position.start = start;
274 position.end = match self {
275 Self::Physical(runs) => start + runs.length(next_run),
276 Self::Coalesced { ends, .. } => ends.get(next_run),
277 };
278 }
279
280 fn deep_size(&self) -> usize {
281 match self {
282 Self::Physical(runs) => runs.deep_size(),
283 Self::Coalesced { values, ends } => {
284 std::mem::size_of_val(values.as_ref()) + ends.deep_size()
285 }
286 }
287 }
288}
289
290#[derive(Debug, Clone)]
296enum LazyLevels {
297 Dense(ScalarBuffer<u16>),
298 Runs(Arc<RunStorage>),
299}
300
301#[derive(Debug, Clone, Copy, PartialEq, Eq)]
302enum LevelPlan {
303 Physical,
304 Coalesced,
305 Dense,
306}
307
308#[derive(Debug, Default, Clone, Copy)]
309struct RunPosition {
310 run: usize,
311 start: usize,
312 end: usize,
313}
314
315#[derive(Debug, Default, Clone, Copy)]
321struct LevelCursor {
322 level: usize,
324 row: u64,
326 run: RunPosition,
328}
329
330impl LazyLevels {
331 fn from_rle_runs(runs: RleRuns) -> Result<Self> {
332 let plan = Self::select_plan(&runs);
333 match plan {
334 LevelPlan::Physical => Ok(Self::Runs(Arc::new(RunStorage::Physical(
335 runs.into_owned(),
336 )))),
337 LevelPlan::Coalesced => Self::build_coalesced(runs),
338 LevelPlan::Dense => Self::build_dense(runs),
339 }
340 }
341
342 fn select_plan(runs: &RleRuns) -> LevelPlan {
345 if runs.num_values() == 0 {
346 return LevelPlan::Dense;
347 }
348
349 let run_storage_size = std::mem::size_of::<RunStorage>() as u128;
350 let physical_size = run_storage_size + runs.owned_size() as u128;
351 let coalesced_size = run_storage_size
352 + (runs.coalesced_runs() as u128)
353 * (std::mem::size_of::<u16>() + RunEnds::width_for(runs.num_values())) as u128;
354 let dense_size = (runs.num_values() as u128) * std::mem::size_of::<u16>() as u128;
355 [
356 (physical_size, runs.num_runs(), 0usize, LevelPlan::Physical),
357 (
358 coalesced_size,
359 runs.coalesced_runs(),
360 1usize,
361 LevelPlan::Coalesced,
362 ),
363 (dense_size, runs.num_values(), 2usize, LevelPlan::Dense),
364 ]
365 .into_iter()
366 .min_by_key(|(size, traversal, priority, _)| (*size, *traversal, *priority))
367 .map(|(_, _, _, plan)| plan)
368 .unwrap_or(LevelPlan::Dense)
369 }
370
371 fn build_coalesced(runs: RleRuns) -> Result<Self> {
372 let mut values = Vec::with_capacity(runs.coalesced_runs());
373 let mut ends = RunEndsBuilder::with_capacity(runs.num_values(), runs.coalesced_runs());
374 let mut logical_end = 0usize;
375 for (value, length) in runs.iter() {
376 logical_end = logical_end
377 .checked_add(length)
378 .ok_or_else(|| Error::internal("Validated RLE run length sum overflowed usize"))?;
379 if values.last().copied() == Some(value) {
380 ends.set_last(logical_end)?;
381 } else {
382 values.push(value);
383 ends.push(logical_end)?;
384 }
385 }
386 Ok(Self::Runs(Arc::new(RunStorage::Coalesced {
387 values: values.into_boxed_slice(),
388 ends: ends.finish(),
389 })))
390 }
391
392 fn build_dense(runs: RleRuns) -> Result<Self> {
393 let mut values = Vec::new();
394 values.try_reserve_exact(runs.num_values()).map_err(|_| {
395 Error::internal(format!(
396 "Cannot allocate {} dense repetition/definition levels",
397 runs.num_values()
398 ))
399 })?;
400 for (value, length) in runs.iter() {
401 values.resize(values.len() + length, value);
402 }
403 Ok(Self::Dense(ScalarBuffer::from(values)))
404 }
405
406 fn len(&self) -> usize {
407 match self {
408 Self::Dense(buf) => buf.len(),
409 Self::Runs(runs) => runs.len(),
410 }
411 }
412
413 fn validate_max(&self, level_type: &str, max: u16) -> Result<()> {
414 let invalid = match self {
415 Self::Dense(levels) => levels
416 .iter()
417 .enumerate()
418 .find_map(|(index, &value)| (value > max).then_some(("index", index, value))),
419 Self::Runs(runs) => runs
420 .first_value_above(max)
421 .map(|(run, value)| ("run", run, value)),
422 };
423 if let Some((position_type, position, value)) = invalid {
424 return Err(Error::invalid_input_source(
425 format!(
426 "Invalid {level_type} level {value} at {position_type} {position}: maximum is {max}"
427 )
428 .into(),
429 ));
430 }
431 Ok(())
432 }
433
434 fn seek_row_start(
441 &self,
442 cursor: &mut LevelCursor,
443 target_row: u64,
444 max_rep: u16,
445 ) -> Result<usize> {
446 let mut need = target_row.checked_sub(cursor.row).ok_or_else(|| {
447 Error::internal(format!(
448 "Complex all-null row ranges are not sorted: target row {target_row} follows {}",
449 cursor.row
450 ))
451 })?;
452 if need == 0 {
453 return Ok(cursor.level);
454 }
455 match self {
456 Self::Dense(buf) => {
457 let mut level = cursor.level;
458 while need > 0 {
459 if level >= buf.len() {
460 return Err(Error::internal(
461 "Invalid complex all-null layout: repetition buffer too short",
462 ));
463 }
464 if buf[level] != max_rep {
465 return Err(Error::internal(
466 "Invalid complex all-null layout: row did not start at max repetition level",
467 ));
468 }
469 level += 1;
470 while level < buf.len() && buf[level] != max_rep {
471 level += 1;
472 }
473 need -= 1;
474 }
475 cursor.level = level;
476 cursor.row = target_row;
477 Ok(level)
478 }
479 Self::Runs(runs) => {
480 let mut level = cursor.level;
481 let mut run = cursor.run;
482 runs.seek(&mut run, level);
483 while need > 0 {
484 if run.run >= runs.num_runs() {
485 return Err(Error::internal(
486 "Invalid complex all-null layout: repetition buffer too short",
487 ));
488 }
489 if runs.value(run.run) != max_rep {
490 return Err(Error::internal(
491 "Invalid complex all-null layout: row did not start at max repetition level",
492 ));
493 }
494 let avail = (run.end - level) as u64;
495 if need < avail {
496 level += need as usize;
498 need = 0;
499 } else {
500 need -= avail;
503 runs.advance(&mut run);
504 while run.run < runs.num_runs() && runs.value(run.run) != max_rep {
505 runs.advance(&mut run);
506 }
507 level = if run.run < runs.num_runs() {
508 run.start
509 } else {
510 self.len()
511 };
512 }
513 }
514 cursor.level = level;
515 cursor.row = target_row;
516 cursor.run = run;
517 Ok(level)
518 }
519 }
520 }
521
522 fn count_le_cursor(
528 &self,
529 run_cursor: &mut RunPosition,
530 range: Range<usize>,
531 max: u16,
532 ) -> (u64, RunPosition) {
533 if range.is_empty() {
534 return (0, *run_cursor);
535 }
536 match self {
537 Self::Dense(buf) => (
538 buf[range].iter().filter(|&&d| d <= max).count() as u64,
539 RunPosition::default(),
540 ),
541 Self::Runs(runs) => {
542 runs.seek(run_cursor, range.start);
544 let start = *run_cursor;
545 let mut count = 0u64;
546 let mut current = *run_cursor;
547 while current.run < runs.num_runs() && current.start < range.end {
548 if runs.value(current.run) <= max {
549 let lo = current.start.max(range.start);
550 let hi = current.end.min(range.end);
551 count += (hi - lo) as u64;
552 }
553 if current.end >= range.end {
554 break;
555 }
556 runs.advance(&mut current);
557 }
558 *run_cursor = current;
561 (count, start)
562 }
563 }
564 }
565
566 fn extend_into(&self, range: Range<usize>, run: RunPosition, out: &mut Vec<u16>) {
567 if range.is_empty() {
568 return;
569 }
570 match self {
571 Self::Dense(buf) => out.extend_from_slice(&buf[range]),
572 Self::Runs(runs) => {
573 let mut current = run;
574 runs.seek(&mut current, range.start);
575 while current.run < runs.num_runs() && current.start < range.end {
576 let lo = current.start.max(range.start);
577 let hi = current.end.min(range.end);
578 if hi > lo {
579 out.resize(out.len() + (hi - lo), runs.value(current.run));
580 }
581 runs.advance(&mut current);
582 }
583 }
584 }
585 }
586
587 #[cfg(test)]
588 fn deep_size(&self) -> usize {
589 self.deep_size_of_children(&mut Context::new())
590 }
591}
592
593impl DeepSizeOf for LazyLevels {
594 fn deep_size_of_children(&self, ctx: &mut Context) -> usize {
595 match self {
596 Self::Dense(buf) => buf.deep_size_of_children(ctx),
597 Self::Runs(runs) => {
598 let pointer = Arc::as_ptr(runs) as *const () as usize;
599 if ctx.mark_seen(pointer) {
600 std::mem::size_of_val(runs.as_ref()) + runs.deep_size()
601 } else {
602 0
603 }
604 }
605 }
606 }
607}
608
609fn validate_complex_all_null_levels(
610 rep: &Option<LazyLevels>,
611 def: &Option<LazyLevels>,
612 max_rep: u16,
613 max_def: u16,
614) -> Result<()> {
615 if let Some(rep) = rep {
616 rep.validate_max("repetition", max_rep)?;
617 }
618 if let Some(def) = def {
619 def.validate_max("definition", max_def)?;
620 }
621 if let (Some(rep), Some(def)) = (rep, def)
622 && rep.len() != def.len()
623 {
624 return Err(Error::invalid_input_source(
625 format!(
626 "Mismatched complex all-null level counts: repetition has {}, definition has {}",
627 rep.len(),
628 def.len()
629 )
630 .into(),
631 ));
632 }
633 Ok(())
634}
635
636fn expected_level_bytes(num_values: u64, level_type: &str) -> Result<usize> {
637 usize::try_from(num_values)
638 .ok()
639 .and_then(|num_values| num_values.checked_mul(std::mem::size_of::<u16>()))
640 .ok_or_else(|| {
641 Error::invalid_input_source(
642 format!("{level_type} level count {num_values} does not fit in memory").into(),
643 )
644 })
645}
646
647fn dense_levels_from_block(
648 decompressed: DataBlock,
649 num_values: u64,
650 level_type: &str,
651) -> Result<LazyLevels> {
652 let DataBlock::FixedWidth(block) = decompressed else {
653 return Err(Error::invalid_input_source(
654 format!("Expected fixed-width data block for {level_type} levels").into(),
655 ));
656 };
657 if block.num_values != num_values {
658 return Err(Error::invalid_input_source(
659 format!(
660 "Unexpected {level_type} level count after decompression: expected {num_values}, got {}",
661 block.num_values
662 )
663 .into(),
664 ));
665 }
666 if block.bits_per_value != 16 {
667 return Err(Error::invalid_input_source(
668 format!(
669 "Unexpected {level_type} level bit width after decompression: expected 16, got {}",
670 block.bits_per_value
671 )
672 .into(),
673 ));
674 }
675 let expected_bytes = expected_level_bytes(num_values, level_type)?;
676 if block.data.len() != expected_bytes {
677 return Err(Error::invalid_input_source(
678 format!(
679 "Unexpected decompressed {level_type} level size: expected {expected_bytes} bytes for {num_values} values, got {}",
680 block.data.len()
681 )
682 .into(),
683 ));
684 }
685 Ok(LazyLevels::Dense(block.data.borrow_to_typed_slice::<u16>()))
686}
687
688#[derive(Debug)]
689struct CachedComplexAllNullState {
690 rep: Option<LazyLevels>,
691 def: Option<LazyLevels>,
692}
693
694impl DeepSizeOf for CachedComplexAllNullState {
695 fn deep_size_of_children(&self, ctx: &mut Context) -> usize {
696 self.rep.deep_size_of_children(ctx) + self.def.deep_size_of_children(ctx)
697 }
698}
699
700impl CachedPageData for CachedComplexAllNullState {
701 fn as_arc_any(self: Arc<Self>) -> Arc<dyn Any + Send + Sync + 'static> {
702 self
703 }
704}
705
706#[derive(Debug)]
715pub struct ComplexAllNullScheduler {
716 buffer_offsets_and_sizes: Arc<[(u64, u64)]>,
718 def_meaning: Arc<[DefinitionInterpretation]>,
719 repdef: Option<Arc<CachedComplexAllNullState>>,
720 max_rep: u16,
721 max_def: u16,
722 max_visible_level: u16,
723 rep_codec: LevelCodec,
724 def_codec: LevelCodec,
725 num_rep_values: u64,
726 num_def_values: u64,
727}
728
729impl ComplexAllNullScheduler {
730 pub(crate) fn new(
731 buffer_offsets_and_sizes: Arc<[(u64, u64)]>,
732 def_meaning: Arc<[DefinitionInterpretation]>,
733 rep_codec: LevelCodec,
734 def_codec: LevelCodec,
735 num_rep_values: u64,
736 num_def_values: u64,
737 ) -> Self {
738 let max_rep = def_meaning.iter().filter(|l| l.is_list()).count() as u16;
739 let max_def = def_meaning
740 .iter()
741 .map(|meaning| meaning.num_def_levels())
742 .sum::<u16>();
743 let max_visible_level = max_visible_level(&def_meaning);
744 Self {
745 buffer_offsets_and_sizes,
746 def_meaning,
747 repdef: None,
748 max_rep,
749 max_def,
750 max_visible_level,
751 rep_codec,
752 def_codec,
753 num_rep_values,
754 num_def_values,
755 }
756 }
757}
758
759impl StructuralPageScheduler for ComplexAllNullScheduler {
760 fn init_layout(&self) -> Result<PageInitialization> {
761 let (rep_pos, rep_size) = self.buffer_offsets_and_sizes[0];
763 let (def_pos, def_size) = self.buffer_offsets_and_sizes[1];
764
765 Ok(PageInitialization::new([
766 (rep_size > 0).then_some(rep_pos..rep_pos + rep_size),
767 (def_size > 0).then_some(def_pos..def_pos + def_size),
768 ]))
769 }
770
771 fn init_from_buffers<'a>(
772 &'a mut self,
773 buffers: PageInitializationBuffers,
774 _io: &Arc<dyn EncodingsIo>,
775 ) -> BoxFuture<'a, Result<Arc<dyn CachedPageData>>> {
776 let rep_codec = self.rep_codec.clone();
777 let def_codec = self.def_codec.clone();
778 let num_rep_values = self.num_rep_values;
779 let num_def_values = self.num_def_values;
780 let max_rep = self.max_rep;
781 let max_def = self.max_def;
782
783 async move {
784 let [rep_bytes, def_bytes] = buffers.try_into_array("complex all-null")?;
785
786 let build_levels = |compressed_bytes: Bytes,
789 codec: &LevelCodec,
790 num_values: u64,
791 level_type: &str|
792 -> Result<LazyLevels> {
793 match codec {
794 LevelCodec::Uncompressed => {
795 if num_values == 0 {
796 if !compressed_bytes
797 .len()
798 .is_multiple_of(std::mem::size_of::<u16>())
799 {
800 return Err(Error::invalid_input_source(
801 format!(
802 "Unexpected uncompressed {level_type} level size: {} bytes is not divisible by {}",
803 compressed_bytes.len(),
804 std::mem::size_of::<u16>()
805 )
806 .into(),
807 ));
808 }
809 } else {
810 let expected_bytes = expected_level_bytes(num_values, level_type)?;
811 if compressed_bytes.len() != expected_bytes {
812 return Err(Error::invalid_input_source(
813 format!(
814 "Unexpected uncompressed {level_type} level size: expected {expected_bytes} bytes for {num_values} values, got {}",
815 compressed_bytes.len()
816 )
817 .into(),
818 ));
819 }
820 }
821 let buffer = LanceBuffer::from_bytes(compressed_bytes, 2);
822 Ok(LazyLevels::Dense(buffer.borrow_to_typed_slice::<u16>()))
823 }
824 LevelCodec::Rle(decompressor) => {
825 let frame = LanceBuffer::from_bytes(compressed_bytes, 1);
826 let runs = decompressor.decode_u16_runs(frame, num_values)?;
827 LazyLevels::from_rle_runs(runs)
828 }
829 LevelCodec::Block(decompressor) => {
830 let frame = LanceBuffer::from_bytes(compressed_bytes, 1);
831 let decompressed = decompressor.decompress(Some(frame), num_values)?;
832 dense_levels_from_block(decompressed, num_values, level_type)
833 }
834 }
835 };
836
837 let rep = if let Some(rep) = rep_bytes {
838 Some(build_levels(rep, &rep_codec, num_rep_values, "repetition")?)
839 } else {
840 None
841 };
842
843 let def = if let Some(def) = def_bytes {
844 Some(build_levels(def, &def_codec, num_def_values, "definition")?)
845 } else {
846 None
847 };
848
849 validate_complex_all_null_levels(&rep, &def, max_rep, max_def)?;
850 let repdef = Arc::new(CachedComplexAllNullState { rep, def });
851
852 Ok(repdef as Arc<dyn CachedPageData>)
853 }
854 .boxed()
855 }
856
857 fn try_load(&mut self, data: &Arc<dyn CachedPageData>) -> Result<()> {
858 self.repdef = Some(data.clone().as_arc_any().downcast().map_err(|_| {
859 Error::invalid_input_source(
860 "Cached complex all-null page data has an unexpected type".into(),
861 )
862 })?);
863 Ok(())
864 }
865
866 fn schedule_ranges(
867 &self,
868 ranges: &[Range<u64>],
869 _io: &Arc<dyn EncodingsIo>,
870 ) -> Result<Vec<PageLoadTask>> {
871 let ranges = VecDeque::from_iter(ranges.iter().cloned());
872 let num_rows = ranges.iter().map(|r| r.end - r.start).sum::<u64>();
873 let decoder = Box::new(ComplexAllNullPageDecoder {
874 ranges,
875 rep: self.repdef.as_ref().unwrap().rep.clone(),
876 def: self.repdef.as_ref().unwrap().def.clone(),
877 num_rows,
878 def_meaning: self.def_meaning.clone(),
879 max_rep: self.max_rep,
880 max_visible_level: self.max_visible_level,
881 rep_cursor: LevelCursor::default(),
882 def_run_cursor: RunPosition::default(),
883 }) as Box<dyn StructuralPageDecoder>;
884 let page_load_task = PageLoadTask {
885 decoder_fut: std::future::ready(Ok(decoder)).boxed(),
886 num_rows,
887 };
888 Ok(vec![page_load_task])
889 }
890}
891
892#[derive(Debug)]
893pub struct ComplexAllNullPageDecoder {
894 ranges: VecDeque<Range<u64>>,
895 rep: Option<LazyLevels>,
896 def: Option<LazyLevels>,
897 num_rows: u64,
898 def_meaning: Arc<[DefinitionInterpretation]>,
899 max_rep: u16,
900 max_visible_level: u16,
901 rep_cursor: LevelCursor,
903 def_run_cursor: RunPosition,
905}
906
907impl ComplexAllNullPageDecoder {
908 fn drain_ranges(&mut self, num_rows: u64) -> Vec<Range<u64>> {
909 let mut rows_desired = num_rows;
910 let mut ranges = Vec::with_capacity(self.ranges.len());
911 while rows_desired > 0 {
912 let front = self.ranges.front_mut().unwrap();
913 let avail = front.end - front.start;
914 if avail > rows_desired {
915 ranges.push(front.start..front.start + rows_desired);
916 front.start += rows_desired;
917 rows_desired = 0;
918 } else {
919 ranges.push(self.ranges.pop_front().unwrap());
920 rows_desired -= avail;
921 }
922 }
923 ranges
924 }
925
926 fn seek_row_start(&mut self, target_row: u64) -> Result<usize> {
929 match &self.rep {
930 Some(rep) => rep.seek_row_start(&mut self.rep_cursor, target_row, self.max_rep),
931 None => {
932 self.rep_cursor.row = target_row;
934 self.rep_cursor.level = target_row as usize;
935 Ok(target_row as usize)
936 }
937 }
938 }
939
940 fn count_visible(&mut self, levels: Range<usize>) -> Result<(u64, RunPosition)> {
943 match &self.def {
944 Some(def) => {
945 if levels.end > def.len() {
946 return Err(Error::internal(
947 "Invalid complex all-null layout: definition buffer too short",
948 ));
949 }
950 Ok(def.count_le_cursor(&mut self.def_run_cursor, levels, self.max_visible_level))
951 }
952 None => Ok(((levels.end - levels.start) as u64, RunPosition::default())),
953 }
954 }
955}
956
957impl StructuralPageDecoder for ComplexAllNullPageDecoder {
958 fn drain(&mut self, num_rows: u64) -> Result<Box<dyn DecodePageTask>> {
959 let drained_ranges = self.drain_ranges(num_rows);
960 let mut level_slices: Vec<LevelSlice> = Vec::with_capacity(drained_ranges.len());
961 let mut visible_items_total = 0;
962
963 for range in drained_ranges {
968 let level_start = self.seek_row_start(range.start)?;
969 let rep_run = self.rep_cursor.run;
970 let level_end = self.seek_row_start(range.end)?;
971 let (visible_items, def_run) = self.count_visible(level_start..level_end)?;
972 visible_items_total += visible_items;
973 if let Some(last) = level_slices.last_mut()
974 && last.range.end == level_start
975 {
976 last.range.end = level_end;
977 } else {
978 level_slices.push(LevelSlice {
979 range: level_start..level_end,
980 rep_run,
981 def_run,
982 });
983 }
984 }
985
986 Ok(Box::new(DecodeComplexAllNullTask {
987 level_slices,
988 visible_items_total,
989 rep: self.rep.clone(),
990 def: self.def.clone(),
991 def_meaning: self.def_meaning.clone(),
992 max_visible_level: self.max_visible_level,
993 }))
994 }
995
996 fn num_rows(&self) -> u64 {
997 self.num_rows
998 }
999}
1000
1001#[derive(Debug, Clone)]
1004struct LevelSlice {
1005 range: Range<usize>,
1006 rep_run: RunPosition,
1007 def_run: RunPosition,
1008}
1009
1010#[derive(Clone, Copy)]
1011enum LevelKind {
1012 Repetition,
1013 Definition,
1014}
1015
1016impl LevelSlice {
1017 fn run(&self, kind: LevelKind) -> RunPosition {
1018 match kind {
1019 LevelKind::Repetition => self.rep_run,
1020 LevelKind::Definition => self.def_run,
1021 }
1022 }
1023}
1024
1025#[derive(Debug)]
1026pub struct DecodeComplexAllNullTask {
1027 level_slices: Vec<LevelSlice>,
1028 visible_items_total: u64,
1029 rep: Option<LazyLevels>,
1030 def: Option<LazyLevels>,
1031 def_meaning: Arc<[DefinitionInterpretation]>,
1032 max_visible_level: u16,
1033}
1034
1035impl DecodeComplexAllNullTask {
1036 fn decode_level(&self, levels: &Option<LazyLevels>, kind: LevelKind) -> Option<Vec<u16>> {
1037 levels.as_ref().map(|levels| {
1038 let num_levels = self
1039 .level_slices
1040 .iter()
1041 .map(|slice| slice.range.end - slice.range.start)
1042 .sum();
1043 let mut referenced_levels = Vec::with_capacity(num_levels);
1044 for slice in &self.level_slices {
1045 levels.extend_into(slice.range.clone(), slice.run(kind), &mut referenced_levels);
1046 }
1047 referenced_levels
1048 })
1049 }
1050}
1051
1052impl DecodePageTask for DecodeComplexAllNullTask {
1053 fn decode(self: Box<Self>) -> Result<DecodedPage> {
1054 let rep = self.decode_level(&self.rep, LevelKind::Repetition);
1055 let def = self.decode_level(&self.def, LevelKind::Definition);
1056
1057 let num_values = if let Some(def) = &def {
1061 def.iter().filter(|&d| *d <= self.max_visible_level).count() as u64
1062 } else {
1063 self.visible_items_total
1064 };
1065
1066 let data = DataBlock::AllNull(AllNullDataBlock { num_values });
1067 let unraveler = RepDefUnraveler::new(rep, def, self.def_meaning, num_values);
1068 Ok(DecodedPage {
1069 data,
1070 repdef: unraveler,
1071 })
1072 }
1073}
1074
1075#[derive(Debug, Default)]
1080pub struct SimpleAllNullScheduler {}
1081
1082impl StructuralPageScheduler for SimpleAllNullScheduler {
1083 fn needs_initialization(&self) -> bool {
1084 false
1085 }
1086
1087 fn init_layout(&self) -> Result<PageInitialization> {
1088 Ok(PageInitialization::new([]))
1089 }
1090
1091 fn init_from_buffers<'a>(
1092 &'a mut self,
1093 _buffers: PageInitializationBuffers,
1094 _io: &Arc<dyn EncodingsIo>,
1095 ) -> BoxFuture<'a, Result<Arc<dyn CachedPageData>>> {
1096 std::future::ready(Ok(Arc::new(NoCachedPageData) as Arc<dyn CachedPageData>)).boxed()
1097 }
1098
1099 fn try_load(&mut self, _cache: &Arc<dyn CachedPageData>) -> Result<()> {
1100 Ok(())
1101 }
1102
1103 fn schedule_ranges(
1104 &self,
1105 ranges: &[Range<u64>],
1106 _io: &Arc<dyn EncodingsIo>,
1107 ) -> Result<Vec<PageLoadTask>> {
1108 let num_rows = ranges.iter().map(|r| r.end - r.start).sum::<u64>();
1109 let decoder =
1110 Box::new(SimpleAllNullPageDecoder { num_rows }) as Box<dyn StructuralPageDecoder>;
1111 let page_load_task = PageLoadTask {
1112 decoder_fut: std::future::ready(Ok(decoder)).boxed(),
1113 num_rows,
1114 };
1115 Ok(vec![page_load_task])
1116 }
1117}
1118
1119#[derive(Debug)]
1122struct SimpleAllNullDecodePageTask {
1123 num_values: u64,
1124}
1125impl DecodePageTask for SimpleAllNullDecodePageTask {
1126 fn decode(self: Box<Self>) -> Result<DecodedPage> {
1127 let unraveler = RepDefUnraveler::new(
1128 None,
1129 Some(vec![1; self.num_values as usize]),
1130 Arc::new([DefinitionInterpretation::NullableItem]),
1131 self.num_values,
1132 );
1133 Ok(DecodedPage {
1134 data: DataBlock::AllNull(AllNullDataBlock {
1135 num_values: self.num_values,
1136 }),
1137 repdef: unraveler,
1138 })
1139 }
1140}
1141
1142#[derive(Debug)]
1143pub struct SimpleAllNullPageDecoder {
1144 num_rows: u64,
1145}
1146
1147impl StructuralPageDecoder for SimpleAllNullPageDecoder {
1148 fn drain(&mut self, num_rows: u64) -> Result<Box<dyn DecodePageTask>> {
1149 Ok(Box::new(SimpleAllNullDecodePageTask {
1150 num_values: num_rows,
1151 }))
1152 }
1153
1154 fn num_rows(&self) -> u64 {
1155 self.num_rows
1156 }
1157}
1158
1159#[cfg(test)]
1160#[allow(clippy::single_range_in_vec_init)]
1161mod tests {
1162 use std::collections::HashMap;
1163 use std::sync::Arc;
1164
1165 use arrow_buffer::ScalarBuffer;
1166
1167 use crate::buffer::LanceBuffer;
1168 use crate::compression::DefaultDecompressionStrategy;
1169 use crate::data::{BlockInfo, DataBlock, FixedWidthDataBlock};
1170 use crate::encodings::logical::primitive::tests::encoded_u16_frame;
1171 use crate::encodings::physical::rle::{RleDecompressor, RleRuns, RunLengthWidth};
1172 use crate::format::metadata::compressive_encoding::Compression;
1173 use crate::format::{EncodingUtils, metadata};
1174 use crate::testing::{TestCases, check_round_trip_encoding_of_data};
1175
1176 use super::{
1177 LazyLevels, LevelCodec, LevelCursor, LevelPlan, RunEndsBuilder, RunPosition, RunStorage,
1178 dense_levels_from_block, validate_complex_all_null_levels,
1179 };
1180
1181 fn encoded_u16_runs(levels: &[u16], run_length_width: RunLengthWidth) -> RleRuns {
1182 let frame = encoded_u16_frame(levels, run_length_width);
1183 RleDecompressor::with_run_length_width(16, run_length_width)
1184 .decode_u16_runs(frame, levels.len() as u64)
1185 .unwrap()
1186 }
1187
1188 fn physical_levels(levels: &[u16]) -> LazyLevels {
1189 LazyLevels::Runs(Arc::new(RunStorage::Physical(
1190 encoded_u16_runs(levels, RunLengthWidth::U8).into_owned(),
1191 )))
1192 }
1193
1194 fn coalesced_levels(levels: &[u16]) -> LazyLevels {
1195 let mut values = Vec::new();
1196 let mut ends = RunEndsBuilder::with_capacity(levels.len(), levels.len());
1197 for (index, &value) in levels.iter().enumerate() {
1198 if values.last() == Some(&value) {
1199 ends.set_last(index + 1).unwrap();
1200 } else {
1201 values.push(value);
1202 ends.push(index + 1).unwrap();
1203 }
1204 }
1205 LazyLevels::Runs(Arc::new(RunStorage::Coalesced {
1206 values: values.into_boxed_slice(),
1207 ends: ends.finish(),
1208 }))
1209 }
1210
1211 #[test]
1212 fn lazy_levels_runs_match_dense() {
1213 let expanded: Vec<u16> = vec![3, 3, 1, 3, 3, 3, 0, 0];
1215 let coalesced = coalesced_levels(&expanded);
1216 let physical = physical_levels(&expanded);
1217 let dense = LazyLevels::Dense(ScalarBuffer::<u16>::from(expanded.clone()));
1218 let n = expanded.len();
1219
1220 assert_eq!(coalesced.len(), n);
1221 assert_eq!(physical.len(), n);
1222 assert_eq!(dense.len(), n);
1223
1224 let max_rep = 3u16;
1226 let row_starts: Vec<usize> = (0..n).filter(|&i| expanded[i] == max_rep).collect();
1227 for target in 0..=row_starts.len() as u64 {
1228 let want = row_starts.get(target as usize).copied().unwrap_or(n);
1229 for runs in [&coalesced, &physical] {
1230 let mut cursor = LevelCursor::default();
1231 assert_eq!(
1232 runs.seek_row_start(&mut cursor, target, max_rep).unwrap(),
1233 want,
1234 "seek_row_start({target})"
1235 );
1236 }
1237 let mut c_dense = LevelCursor::default();
1238 assert_eq!(
1239 dense.seek_row_start(&mut c_dense, target, max_rep).unwrap(),
1240 want
1241 );
1242 }
1243
1244 for start in 0..=n {
1247 for end in start..=n {
1248 for max in [0u16, 1, 2, 3] {
1249 let want = expanded[start..end].iter().filter(|&&d| d <= max).count() as u64;
1250 for runs in [&coalesced, &physical] {
1251 let mut cursor = RunPosition::default();
1252 assert_eq!(
1253 runs.count_le_cursor(&mut cursor, start..end, max).0,
1254 want,
1255 "count_le_cursor({start}..{end}, {max})"
1256 );
1257 }
1258 let mut d_cur = RunPosition::default();
1259 assert_eq!(dense.count_le_cursor(&mut d_cur, start..end, max).0, want);
1260 }
1261 for runs in [&coalesced, &physical] {
1262 let mut got = Vec::new();
1263 runs.extend_into(start..end, RunPosition::default(), &mut got);
1264 assert_eq!(
1265 got,
1266 expanded[start..end].to_vec(),
1267 "extend_into({start}..{end})"
1268 );
1269 }
1270 let mut got_dense = Vec::new();
1271 dense.extend_into(start..end, RunPosition::default(), &mut got_dense);
1272 assert_eq!(got_dense, expanded[start..end].to_vec());
1273 }
1274 }
1275 }
1276
1277 #[test]
1278 fn physical_run_hints_support_deferred_materialization() {
1279 let expanded: Vec<u16> = vec![3, 3, 1, 1, 2, 2, 0, 0];
1280 let physical = physical_levels(&expanded);
1281 let LazyLevels::Runs(runs) = &physical else {
1282 panic!("expected physical runs");
1283 };
1284 let mut first_hint = RunPosition::default();
1285 runs.seek(&mut first_hint, 2);
1286 let mut second_hint = RunPosition::default();
1287 runs.seek(&mut second_hint, 6);
1288
1289 let mut second = Vec::new();
1290 physical.extend_into(6..8, second_hint, &mut second);
1291 let mut first = Vec::new();
1292 physical.extend_into(2..4, first_hint, &mut first);
1293 assert_eq!(second, expanded[6..8]);
1294 assert_eq!(first, expanded[2..4]);
1295 }
1296
1297 mod complex_all_null_drain_parity {
1302 use std::ops::Range;
1303
1304 use arrow_buffer::ScalarBuffer;
1305 use proptest::prelude::*;
1306
1307 use super::super::{LazyLevels, LevelCursor, RunPosition};
1308 use super::{coalesced_levels, physical_levels};
1309 use crate::Result;
1310
1311 #[derive(Debug, Clone)]
1312 struct DrainInput {
1313 max_rep: u16,
1314 max_visible: u16,
1315 rep: Option<Vec<u16>>,
1316 def: Option<Vec<u16>>,
1317 ranges: Vec<Range<u64>>,
1318 }
1319
1320 fn dense_levels(levels: &[u16]) -> LazyLevels {
1321 LazyLevels::Dense(ScalarBuffer::from(levels.to_vec()))
1322 }
1323
1324 fn rle_levels(levels: &[u16]) -> LazyLevels {
1325 coalesced_levels(levels)
1326 }
1327
1328 fn seek(
1329 rep: Option<&LazyLevels>,
1330 cursor: &mut LevelCursor,
1331 row: u64,
1332 max_rep: u16,
1333 ) -> Result<usize> {
1334 match rep {
1335 Some(rep) => rep.seek_row_start(cursor, row, max_rep),
1336 None => {
1337 cursor.row = row;
1338 cursor.level = row as usize;
1339 Ok(row as usize)
1340 }
1341 }
1342 }
1343
1344 fn simulate_drain(
1347 rep: Option<&LazyLevels>,
1348 def: Option<&LazyLevels>,
1349 max_rep: u16,
1350 max_visible: u16,
1351 ranges: &[Range<u64>],
1352 ) -> Result<(Vec<Range<usize>>, u64)> {
1353 let mut rep_cursor = LevelCursor::default();
1354 let mut def_run_cursor = RunPosition::default();
1355 let mut slices: Vec<Range<usize>> = Vec::new();
1356 let mut visible = 0u64;
1357 for range in ranges {
1358 let level_start = seek(rep, &mut rep_cursor, range.start, max_rep)?;
1359 let level_end = seek(rep, &mut rep_cursor, range.end, max_rep)?;
1360 visible += match def {
1361 Some(def) => {
1362 def.count_le_cursor(
1363 &mut def_run_cursor,
1364 level_start..level_end,
1365 max_visible,
1366 )
1367 .0
1368 }
1369 None => (level_end - level_start) as u64,
1370 };
1371 match slices.last_mut() {
1372 Some(last) if last.end == level_start => last.end = level_end,
1373 _ => slices.push(level_start..level_end),
1374 }
1375 }
1376 Ok((slices, visible))
1377 }
1378
1379 fn reference_drain(
1381 rep: Option<&[u16]>,
1382 def: Option<&[u16]>,
1383 max_rep: u16,
1384 max_visible: u16,
1385 ranges: &[Range<u64>],
1386 ) -> (Vec<Range<usize>>, u64) {
1387 let total_levels = rep
1388 .map(|r| r.len())
1389 .or_else(|| def.map(|d| d.len()))
1390 .unwrap_or(0);
1391 let row_starts: Vec<usize> = match rep {
1393 Some(rep) => (0..rep.len()).filter(|&i| rep[i] == max_rep).collect(),
1394 None => (0..total_levels).collect(),
1395 };
1396 let level_of_row = |row: u64| {
1397 row_starts
1398 .get(row as usize)
1399 .copied()
1400 .unwrap_or(total_levels)
1401 };
1402
1403 let mut slices: Vec<Range<usize>> = Vec::new();
1404 let mut visible = 0u64;
1405 for range in ranges {
1406 let ls = level_of_row(range.start);
1407 let le = level_of_row(range.end);
1408 visible += match def {
1409 Some(def) => def[ls..le].iter().filter(|&&d| d <= max_visible).count() as u64,
1410 None => (le - ls) as u64,
1411 };
1412 match slices.last_mut() {
1413 Some(last) if last.end == ls => last.end = le,
1414 _ => slices.push(ls..le),
1415 }
1416 }
1417 (slices, visible)
1418 }
1419
1420 fn ranges_strategy(num_rows: u64) -> BoxedStrategy<Vec<Range<u64>>> {
1421 if num_rows == 0 {
1422 return Just(Vec::new()).boxed();
1423 }
1424 proptest::collection::vec((0u64..=3, 1u64..=4), 0..=8)
1427 .prop_map(move |pairs| {
1428 let mut ranges = Vec::new();
1429 let mut pos = 0u64;
1430 for (gap, len) in pairs {
1431 pos = pos.saturating_add(gap);
1432 if pos >= num_rows {
1433 break;
1434 }
1435 let end = (pos + len).min(num_rows);
1436 ranges.push(pos..end);
1437 pos = end;
1438 }
1439 ranges
1440 })
1441 .boxed()
1442 }
1443
1444 fn drain_input() -> impl Strategy<Value = DrainInput> {
1445 (
1446 1u16..=3,
1447 0u16..=3,
1448 any::<bool>(),
1449 any::<bool>(),
1450 1usize..=48,
1451 )
1452 .prop_flat_map(|(max_rep, max_visible, has_rep, has_def, len)| {
1453 let has_def = has_def || !has_rep;
1456 let rep = if has_rep {
1457 proptest::collection::vec(0u16..=max_rep, len)
1458 .prop_map(move |mut v| {
1459 v[0] = max_rep;
1461 Some(v)
1462 })
1463 .boxed()
1464 } else {
1465 Just(None).boxed()
1466 };
1467 let def = if has_def {
1468 proptest::collection::vec(0u16..=(max_visible + 2), len)
1469 .prop_map(Some)
1470 .boxed()
1471 } else {
1472 Just(None).boxed()
1473 };
1474 (Just(max_rep), Just(max_visible), rep, def)
1475 })
1476 .prop_flat_map(|(max_rep, max_visible, rep, def)| {
1477 let num_rows = match &rep {
1478 Some(rep) => rep.iter().filter(|&&v| v == max_rep).count() as u64,
1479 None => def.as_ref().map(|d| d.len() as u64).unwrap_or(0),
1480 };
1481 ranges_strategy(num_rows).prop_map(move |ranges| DrainInput {
1482 max_rep,
1483 max_visible,
1484 rep: rep.clone(),
1485 def: def.clone(),
1486 ranges,
1487 })
1488 })
1489 }
1490
1491 proptest! {
1492 #![proptest_config(ProptestConfig::with_cases(512))]
1493
1494 #[test]
1495 fn drain_matches_reference(input in drain_input()) {
1496 let DrainInput { max_rep, max_visible, rep, def, ranges } = input;
1497
1498 let reference =
1499 reference_drain(rep.as_deref(), def.as_deref(), max_rep, max_visible, &ranges);
1500
1501 let rep_dense = rep.as_deref().map(dense_levels);
1502 let def_dense = def.as_deref().map(dense_levels);
1503 let got_dense =
1504 simulate_drain(rep_dense.as_ref(), def_dense.as_ref(), max_rep, max_visible, &ranges)
1505 .unwrap();
1506 prop_assert_eq!(&got_dense, &reference, "dense form diverged from reference");
1507
1508 let rep_rle = rep.as_deref().map(rle_levels);
1509 let def_rle = def.as_deref().map(rle_levels);
1510 let got_rle =
1511 simulate_drain(rep_rle.as_ref(), def_rle.as_ref(), max_rep, max_visible, &ranges)
1512 .unwrap();
1513 prop_assert_eq!(&got_rle, &reference, "rle form diverged from reference");
1514
1515 let rep_physical = rep.as_deref().map(physical_levels);
1516 let def_physical = def.as_deref().map(physical_levels);
1517 let got_physical =
1518 simulate_drain(rep_physical.as_ref(), def_physical.as_ref(), max_rep, max_visible, &ranges)
1519 .unwrap();
1520 prop_assert_eq!(&got_physical, &reference, "physical form diverged from reference");
1521 }
1522 }
1523 }
1524
1525 #[test]
1526 fn lazy_levels_runs_are_compact() {
1527 let single_run = |n: usize| {
1528 let mut ends = RunEndsBuilder::with_capacity(n, 1);
1529 ends.push(n).unwrap();
1530 LazyLevels::Runs(Arc::new(RunStorage::Coalesced {
1531 values: vec![1u16].into_boxed_slice(),
1532 ends: ends.finish(),
1533 }))
1534 };
1535 assert_eq!(single_run(100).deep_size(), single_run(10_000).deep_size());
1537 assert!(single_run(10_000_000).deep_size() < 100);
1538 assert_eq!(single_run(10_000_000).len(), 10_000_000);
1539 assert_eq!(
1541 LazyLevels::Dense(ScalarBuffer::<u16>::from(vec![1u16; 1000])).deep_size(),
1542 2000
1543 );
1544 }
1545
1546 #[test]
1547 fn lazy_levels_selects_smallest_representation() {
1548 let runs = encoded_u16_runs(&[7u16; 10], RunLengthWidth::U8);
1549 assert_eq!(LazyLevels::select_plan(&runs), LevelPlan::Dense);
1550
1551 let equal_size: Vec<u16> = std::iter::repeat_n(0, 256)
1552 .chain(std::iter::repeat_n(1, 100))
1553 .chain(std::iter::repeat_n(2, 100))
1554 .collect();
1555 let runs = encoded_u16_runs(&equal_size, RunLengthWidth::U8);
1556 assert_eq!(LazyLevels::select_plan(&runs), LevelPlan::Coalesced);
1557
1558 let moderate_runs: Vec<u16> = (0..250)
1559 .flat_map(|run| std::iter::repeat_n((run % 2) as u16, 4))
1560 .collect();
1561 let runs = encoded_u16_runs(&moderate_runs, RunLengthWidth::U8);
1562 assert_eq!(LazyLevels::select_plan(&runs), LevelPlan::Physical);
1563
1564 let split_constant = vec![7u16; 5000];
1565 let runs = encoded_u16_runs(&split_constant, RunLengthWidth::U8);
1566 assert_eq!(LazyLevels::select_plan(&runs), LevelPlan::Coalesced);
1567
1568 let high_density: Vec<u16> = (0..70_000).map(|index| (index % 2) as u16).collect();
1569 let runs = encoded_u16_runs(&high_density, RunLengthWidth::U32);
1570 assert_eq!(LazyLevels::select_plan(&runs), LevelPlan::Dense);
1571 }
1572
1573 #[test]
1574 fn physical_runs_detach_from_large_encoded_frame() {
1575 let levels: Vec<u16> = (0..250)
1576 .flat_map(|run| std::iter::repeat_n((run % 2) as u16, 4))
1577 .collect();
1578 let frame = encoded_u16_frame(&levels, RunLengthWidth::U8);
1579 let frame_offset = 4096;
1580 let mut allocation = vec![0; frame_offset + frame.len() + 1_000_000];
1581 allocation[frame_offset..frame_offset + frame.len()].copy_from_slice(frame.as_ref());
1582 let frame = LanceBuffer::from(allocation).slice_with_length(frame_offset, frame.len());
1583 let runs = RleDecompressor::with_run_length_width(16, RunLengthWidth::U8)
1584 .decode_u16_runs(frame, levels.len() as u64)
1585 .unwrap();
1586
1587 assert_eq!(LazyLevels::select_plan(&runs), LevelPlan::Physical);
1588 let cached = LazyLevels::from_rle_runs(runs).unwrap();
1589 assert!(
1590 matches!(cached, LazyLevels::Runs(ref runs) if matches!(runs.as_ref(), RunStorage::Physical(_)))
1591 );
1592 assert_eq!(cached.len(), levels.len());
1593 assert!(cached.deep_size() < 4096);
1594 }
1595
1596 #[test]
1597 fn complex_all_null_levels_reject_invalid_values_and_lengths() {
1598 let invalid_levels = vec![0u16, 3];
1599 for levels in [
1600 LazyLevels::Dense(ScalarBuffer::from(invalid_levels.clone())),
1601 physical_levels(&invalid_levels),
1602 coalesced_levels(&invalid_levels),
1603 ] {
1604 let error = validate_complex_all_null_levels(&None, &Some(levels), 0, 2).unwrap_err();
1605 assert!(matches!(error, lance_core::Error::InvalidInput { .. }));
1606 assert!(error.to_string().contains("Invalid definition level 3"));
1607 }
1608
1609 let rep = Some(LazyLevels::Dense(ScalarBuffer::from(vec![0u16; 2])));
1610 let def = Some(LazyLevels::Dense(ScalarBuffer::from(vec![0u16])));
1611 let error = validate_complex_all_null_levels(&rep, &def, 0, 0).unwrap_err();
1612 assert!(matches!(error, lance_core::Error::InvalidInput { .. }));
1613 assert!(
1614 error
1615 .to_string()
1616 .contains("repetition has 2, definition has 1")
1617 );
1618 }
1619
1620 #[test]
1621 fn block_levels_reject_malformed_payload_size() {
1622 let block = DataBlock::FixedWidth(FixedWidthDataBlock {
1623 data: LanceBuffer::from(vec![0]),
1624 bits_per_value: 16,
1625 num_values: 1,
1626 block_info: BlockInfo::new(),
1627 });
1628 let error = dense_levels_from_block(block, 1, "definition").unwrap_err();
1629 assert!(matches!(error, lance_core::Error::InvalidInput { .. }));
1630 assert!(
1631 error
1632 .to_string()
1633 .contains("expected 2 bytes for 1 values, got 1")
1634 );
1635 }
1636
1637 #[test]
1638 fn complex_all_null_level_codec_validates_rle_metadata() {
1639 let encoding = metadata::CompressiveEncoding {
1640 compression: Some(Compression::Rle(Box::new(metadata::Rle {
1641 values: None,
1642 run_lengths: Some(Box::new(EncodingUtils::flat(8, None))),
1643 }))),
1644 };
1645
1646 let error = LevelCodec::try_new(Some(&encoding), &DefaultDecompressionStrategy::default())
1647 .unwrap_err();
1648 assert!(matches!(error, lance_core::Error::InvalidInput { .. }));
1649 assert!(
1650 error
1651 .to_string()
1652 .contains("RLE compression missing values encoding")
1653 );
1654 }
1655
1656 #[tokio::test]
1658 async fn test_sparse_boolean_list_roundtrip() {
1659 use arrow_array::builder::{BooleanBuilder, ListBuilder};
1660
1661 let mut list_builder = ListBuilder::new(BooleanBuilder::new());
1662 for i in 0..1000i32 {
1663 if i % 64 == 0 {
1664 list_builder.values().append_value(i % 128 == 0);
1666 list_builder.append(true);
1667 } else {
1668 list_builder.append(false);
1669 }
1670 }
1671 let list_array = Arc::new(list_builder.finish());
1672
1673 let test_cases = TestCases::default().with_structural_encodings();
1674 check_round_trip_encoding_of_data(vec![list_array], &test_cases, HashMap::new()).await;
1675 }
1676}