1use std::sync::Arc;
7
8use arrow::{
9 array::RecordBatch,
10 datatypes::{Schema, SchemaRef},
11};
12use unicode_width::UnicodeWidthStr;
13
14use super::{error::TuiResult, format::format_array_value};
15use crate::{dataset::ArrowDataset, Dataset};
16
17const STREAMING_THRESHOLD: usize = 100_000;
19
20#[derive(Debug, Clone)]
43pub enum DatasetAdapter {
44 InMemory(InMemoryAdapter),
46 Streaming(StreamingAdapter),
48}
49
50#[derive(Debug, Clone)]
52pub struct InMemoryAdapter {
53 batches: Vec<RecordBatch>,
55 schema: SchemaRef,
57 total_rows: usize,
59 column_count: usize,
61 batch_offsets: Vec<usize>,
63}
64
65#[derive(Debug, Clone)]
70pub struct StreamingAdapter {
71 schema: SchemaRef,
73 total_rows: usize,
75 column_count: usize,
77 loaded_batches: Vec<RecordBatch>,
79 batch_offsets: Vec<usize>,
81}
82
83impl DatasetAdapter {
84 pub fn from_dataset(dataset: &ArrowDataset) -> TuiResult<Self> {
94 let schema = dataset.schema();
95 let batches: Vec<_> = dataset.iter().collect();
96 let total_rows: usize = batches.iter().map(|b| b.num_rows()).sum();
97
98 if total_rows > STREAMING_THRESHOLD {
100 Self::streaming_from_batches(batches, schema)
101 } else {
102 Self::in_memory_from_batches(batches, schema)
103 }
104 }
105
106 pub fn from_batches(batches: Vec<RecordBatch>, schema: SchemaRef) -> TuiResult<Self> {
108 Self::in_memory_from_batches(batches, schema)
109 }
110
111 pub fn in_memory_from_batches(batches: Vec<RecordBatch>, schema: SchemaRef) -> TuiResult<Self> {
113 Ok(Self::InMemory(InMemoryAdapter::new(batches, schema)?))
114 }
115
116 pub fn streaming_from_batches(batches: Vec<RecordBatch>, schema: SchemaRef) -> TuiResult<Self> {
118 Ok(Self::Streaming(StreamingAdapter::new(batches, schema)?))
119 }
120
121 pub fn empty() -> Self {
123 Self::InMemory(InMemoryAdapter::empty())
124 }
125
126 #[inline]
128 pub fn schema(&self) -> &SchemaRef {
129 match self {
130 Self::InMemory(a) => a.schema(),
131 Self::Streaming(a) => a.schema(),
132 }
133 }
134
135 #[inline]
137 pub fn row_count(&self) -> usize {
138 match self {
139 Self::InMemory(a) => a.row_count(),
140 Self::Streaming(a) => a.row_count(),
141 }
142 }
143
144 #[inline]
146 pub fn column_count(&self) -> usize {
147 match self {
148 Self::InMemory(a) => a.column_count(),
149 Self::Streaming(a) => a.column_count(),
150 }
151 }
152
153 #[inline]
155 pub fn is_empty(&self) -> bool {
156 self.row_count() == 0
157 }
158
159 #[inline]
161 pub fn is_streaming(&self) -> bool {
162 matches!(self, Self::Streaming(_))
163 }
164
165 pub fn get_cell(&self, row: usize, col: usize) -> TuiResult<Option<String>> {
167 match self {
168 Self::InMemory(a) => a.get_cell(row, col),
169 Self::Streaming(a) => a.get_cell(row, col),
170 }
171 }
172
173 pub fn field_name(&self, col: usize) -> Option<&str> {
175 match self {
176 Self::InMemory(a) => a.field_name(col),
177 Self::Streaming(a) => a.field_name(col),
178 }
179 }
180
181 pub fn field_type(&self, col: usize) -> Option<String> {
183 match self {
184 Self::InMemory(a) => a.field_type(col),
185 Self::Streaming(a) => a.field_type(col),
186 }
187 }
188
189 pub fn field_nullable(&self, col: usize) -> Option<bool> {
191 match self {
192 Self::InMemory(a) => a.field_nullable(col),
193 Self::Streaming(a) => a.field_nullable(col),
194 }
195 }
196
197 pub fn calculate_column_widths(&self, max_width: u16, sample_rows: usize) -> Vec<u16> {
201 match self {
202 Self::InMemory(a) => a.calculate_column_widths(max_width, sample_rows),
203 Self::Streaming(a) => a.calculate_column_widths(max_width, sample_rows),
204 }
205 }
206
207 pub fn field_names(&self) -> Vec<&str> {
209 match self {
210 Self::InMemory(a) => a.field_names(),
211 Self::Streaming(a) => a.field_names(),
212 }
213 }
214
215 pub fn locate_row(&self, global_row: usize) -> Option<(usize, usize)> {
217 match self {
218 Self::InMemory(a) => a.locate_row(global_row),
219 Self::Streaming(a) => a.locate_row(global_row),
220 }
221 }
222
223 pub fn search(&self, query: &str) -> Option<usize> {
227 if query.is_empty() {
228 return None;
229 }
230 let query_lower = query.to_lowercase();
231
232 for row in 0..self.row_count() {
233 for col in 0..self.column_count() {
234 if let Ok(Some(value)) = self.get_cell(row, col) {
235 if value.to_lowercase().contains(&query_lower) {
236 return Some(row);
237 }
238 }
239 }
240 }
241 None
242 }
243
244 pub fn search_from(&self, query: &str, start_row: usize) -> Option<usize> {
246 if query.is_empty() {
247 return None;
248 }
249 let query_lower = query.to_lowercase();
250
251 (start_row..self.row_count())
252 .find(|&row| self.row_contains(row, &query_lower))
253 .or_else(|| (0..start_row).find(|&row| self.row_contains(row, &query_lower)))
255 }
256
257 fn row_contains(&self, row: usize, query_lower: &str) -> bool {
259 for col in 0..self.column_count() {
260 if let Ok(Some(value)) = self.get_cell(row, col) {
261 if value.to_lowercase().contains(query_lower) {
262 return true;
263 }
264 }
265 }
266 false
267 }
268}
269
270impl InMemoryAdapter {
271 #[allow(clippy::unnecessary_wraps)]
273 pub fn new(batches: Vec<RecordBatch>, schema: SchemaRef) -> TuiResult<Self> {
274 let total_rows = batches.iter().map(|b| b.num_rows()).sum();
275 let column_count = schema.fields().len();
276
277 let mut batch_offsets = Vec::with_capacity(batches.len() + 1);
279 batch_offsets.push(0);
280 let mut offset = 0;
281 for batch in &batches {
282 offset += batch.num_rows();
283 batch_offsets.push(offset);
284 }
285
286 Ok(Self {
287 batches,
288 schema,
289 total_rows,
290 column_count,
291 batch_offsets,
292 })
293 }
294
295 pub fn empty() -> Self {
297 Self {
298 batches: Vec::new(),
299 schema: Arc::new(Schema::empty()),
300 total_rows: 0,
301 column_count: 0,
302 batch_offsets: vec![0],
303 }
304 }
305
306 #[inline]
307 pub fn schema(&self) -> &SchemaRef {
308 &self.schema
309 }
310
311 #[inline]
312 pub fn row_count(&self) -> usize {
313 self.total_rows
314 }
315
316 #[inline]
317 pub fn column_count(&self) -> usize {
318 self.column_count
319 }
320
321 pub fn get_cell(&self, row: usize, col: usize) -> TuiResult<Option<String>> {
322 if row >= self.total_rows || col >= self.column_count {
323 return Ok(None);
324 }
325
326 let Some((batch_idx, local_row)) = self.locate_row(row) else {
327 return Ok(None);
328 };
329
330 let Some(batch) = self.batches.get(batch_idx) else {
331 return Ok(None);
332 };
333
334 let array = batch.column(col);
335 format_array_value(array.as_ref(), local_row)
336 }
337
338 pub fn field_name(&self, col: usize) -> Option<&str> {
339 self.schema.fields().get(col).map(|f| f.name().as_str())
340 }
341
342 pub fn field_type(&self, col: usize) -> Option<String> {
343 self.schema
344 .fields()
345 .get(col)
346 .map(|f| format!("{:?}", f.data_type()))
347 }
348
349 pub fn field_nullable(&self, col: usize) -> Option<bool> {
350 self.schema.fields().get(col).map(|f| f.is_nullable())
351 }
352
353 pub fn locate_row(&self, global_row: usize) -> Option<(usize, usize)> {
354 if global_row >= self.total_rows {
355 return None;
356 }
357
358 let batch_idx = match self.batch_offsets.binary_search(&global_row) {
359 Ok(idx) => {
360 if idx < self.batches.len() {
361 idx
362 } else {
363 idx.saturating_sub(1)
364 }
365 }
366 Err(idx) => idx.saturating_sub(1),
367 };
368
369 let batch_start = self.batch_offsets.get(batch_idx).copied().unwrap_or(0);
370 let local_row = global_row.saturating_sub(batch_start);
371
372 Some((batch_idx, local_row))
373 }
374
375 pub fn calculate_column_widths(&self, max_width: u16, sample_rows: usize) -> Vec<u16> {
377 if self.column_count == 0 {
378 return Vec::new();
379 }
380
381 let mut widths: Vec<u16> = self
383 .schema
384 .fields()
385 .iter()
386 .map(|f| {
387 let width = UnicodeWidthStr::width(f.name().as_str()).min(50);
388 u16::try_from(width).unwrap_or(u16::MAX)
389 })
390 .collect();
391
392 let sample_count = sample_rows.min(self.total_rows);
394 for row in 0..sample_count {
395 for col in 0..self.column_count {
396 if let Ok(Some(value)) = self.get_cell(row, col) {
397 let width = UnicodeWidthStr::width(value.as_str()).min(50);
399 let width_u16 = u16::try_from(width).unwrap_or(u16::MAX);
400 if let Some(w) = widths.get_mut(col) {
401 *w = (*w).max(width_u16);
402 }
403 }
404 }
405 }
406
407 for w in &mut widths {
409 *w = (*w).max(3);
410 }
411
412 let num_cols = u16::try_from(self.column_count).unwrap_or(u16::MAX);
414 let separators = num_cols.saturating_sub(1);
415 let available = max_width.saturating_sub(separators);
416
417 let total: u16 = widths.iter().sum();
419 if total > available && available > 0 {
420 let scale = f64::from(available) / f64::from(total);
421 for w in &mut widths {
422 #[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)]
423 let scaled = (f64::from(*w) * scale) as u16;
424 *w = scaled.max(3);
425 }
426 }
427
428 widths
429 }
430
431 pub fn field_names(&self) -> Vec<&str> {
432 self.schema
433 .fields()
434 .iter()
435 .map(|f| f.name().as_str())
436 .collect()
437 }
438}
439
440impl StreamingAdapter {
441 #[allow(clippy::unnecessary_wraps)]
446 pub fn new(batches: Vec<RecordBatch>, schema: SchemaRef) -> TuiResult<Self> {
447 let total_rows = batches.iter().map(|b| b.num_rows()).sum();
448 let column_count = schema.fields().len();
449
450 let mut batch_offsets = Vec::with_capacity(batches.len() + 1);
451 batch_offsets.push(0);
452 let mut offset = 0;
453 for batch in &batches {
454 offset += batch.num_rows();
455 batch_offsets.push(offset);
456 }
457
458 Ok(Self {
459 schema,
460 total_rows,
461 column_count,
462 loaded_batches: batches, batch_offsets,
464 })
465 }
466
467 #[inline]
468 pub fn schema(&self) -> &SchemaRef {
469 &self.schema
470 }
471
472 #[inline]
473 pub fn row_count(&self) -> usize {
474 self.total_rows
475 }
476
477 #[inline]
478 pub fn column_count(&self) -> usize {
479 self.column_count
480 }
481
482 pub fn get_cell(&self, row: usize, col: usize) -> TuiResult<Option<String>> {
483 if row >= self.total_rows || col >= self.column_count {
484 return Ok(None);
485 }
486
487 let Some((batch_idx, local_row)) = self.locate_row(row) else {
488 return Ok(None);
489 };
490
491 let Some(batch) = self.loaded_batches.get(batch_idx) else {
492 return Ok(None);
493 };
494
495 let array = batch.column(col);
496 format_array_value(array.as_ref(), local_row)
497 }
498
499 pub fn field_name(&self, col: usize) -> Option<&str> {
500 self.schema.fields().get(col).map(|f| f.name().as_str())
501 }
502
503 pub fn field_type(&self, col: usize) -> Option<String> {
504 self.schema
505 .fields()
506 .get(col)
507 .map(|f| format!("{:?}", f.data_type()))
508 }
509
510 pub fn field_nullable(&self, col: usize) -> Option<bool> {
511 self.schema.fields().get(col).map(|f| f.is_nullable())
512 }
513
514 pub fn locate_row(&self, global_row: usize) -> Option<(usize, usize)> {
515 if global_row >= self.total_rows {
516 return None;
517 }
518
519 let batch_idx = match self.batch_offsets.binary_search(&global_row) {
520 Ok(idx) => {
521 if idx < self.loaded_batches.len() {
522 idx
523 } else {
524 idx.saturating_sub(1)
525 }
526 }
527 Err(idx) => idx.saturating_sub(1),
528 };
529
530 let batch_start = self.batch_offsets.get(batch_idx).copied().unwrap_or(0);
531 let local_row = global_row.saturating_sub(batch_start);
532
533 Some((batch_idx, local_row))
534 }
535
536 pub fn calculate_column_widths(&self, max_width: u16, sample_rows: usize) -> Vec<u16> {
538 if self.column_count == 0 {
539 return Vec::new();
540 }
541
542 let mut widths: Vec<u16> = self
543 .schema
544 .fields()
545 .iter()
546 .map(|f| {
547 let width = UnicodeWidthStr::width(f.name().as_str()).min(50);
548 u16::try_from(width).unwrap_or(u16::MAX)
549 })
550 .collect();
551
552 let sample_count = sample_rows.min(self.total_rows);
553 for row in 0..sample_count {
554 for col in 0..self.column_count {
555 if let Ok(Some(value)) = self.get_cell(row, col) {
556 let width = UnicodeWidthStr::width(value.as_str()).min(50);
557 let width_u16 = u16::try_from(width).unwrap_or(u16::MAX);
558 if let Some(w) = widths.get_mut(col) {
559 *w = (*w).max(width_u16);
560 }
561 }
562 }
563 }
564
565 for w in &mut widths {
566 *w = (*w).max(3);
567 }
568
569 let num_cols = u16::try_from(self.column_count).unwrap_or(u16::MAX);
570 let separators = num_cols.saturating_sub(1);
571 let available = max_width.saturating_sub(separators);
572
573 let total: u16 = widths.iter().sum();
574 if total > available && available > 0 {
575 let scale = f64::from(available) / f64::from(total);
576 for w in &mut widths {
577 #[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss)]
578 let scaled = (f64::from(*w) * scale) as u16;
579 *w = scaled.max(3);
580 }
581 }
582
583 widths
584 }
585
586 pub fn field_names(&self) -> Vec<&str> {
587 self.schema
588 .fields()
589 .iter()
590 .map(|f| f.name().as_str())
591 .collect()
592 }
593}
594
595#[cfg(test)]
596mod tests {
597 use arrow::{
598 array::{Float32Array, Int32Array, StringArray},
599 datatypes::{DataType, Field},
600 };
601
602 use super::*;
603
604 fn create_test_schema() -> SchemaRef {
605 Arc::new(Schema::new(vec![
606 Field::new("id", DataType::Utf8, false),
607 Field::new("value", DataType::Int32, false),
608 Field::new("score", DataType::Float32, false),
609 ]))
610 }
611
612 fn create_test_batch(schema: &SchemaRef, start_id: i32, count: usize) -> RecordBatch {
613 let ids: Vec<String> = (0..count)
614 .map(|i| format!("id_{}", start_id + i as i32))
615 .collect();
616 let values: Vec<i32> = (0..count).map(|i| (start_id + i as i32) * 10).collect();
617 let scores: Vec<f32> = (0..count).map(|i| (i as f32) * 0.1).collect();
618
619 RecordBatch::try_new(
620 schema.clone(),
621 vec![
622 Arc::new(StringArray::from(ids)),
623 Arc::new(Int32Array::from(values)),
624 Arc::new(Float32Array::from(scores)),
625 ],
626 )
627 .unwrap()
628 }
629
630 fn create_test_adapter() -> DatasetAdapter {
631 let schema = create_test_schema();
632 let batch1 = create_test_batch(&schema, 0, 5);
633 let batch2 = create_test_batch(&schema, 5, 5);
634 DatasetAdapter::from_batches(vec![batch1, batch2], schema).unwrap()
635 }
636
637 #[test]
638 fn f001_adapter_row_count() {
639 let adapter = create_test_adapter();
640 assert_eq!(adapter.row_count(), 10, "FALSIFIED: Expected 10 rows");
641 }
642
643 #[test]
644 fn f002_adapter_column_count() {
645 let adapter = create_test_adapter();
646 assert_eq!(
647 adapter.column_count(),
648 3,
649 "FALSIFIED: Expected 3 columns (id, value, score)"
650 );
651 }
652
653 #[test]
654 fn f003_adapter_schema_o1() {
655 let adapter = create_test_adapter();
656 let schema = adapter.schema();
657 assert_eq!(schema.fields().len(), 3);
658 }
659
660 #[test]
661 fn f004_adapter_get_cell_first_batch() {
662 let adapter = create_test_adapter();
663 let cell = adapter.get_cell(0, 0).unwrap();
664 assert!(cell.is_some(), "FALSIFIED: Cell should exist");
665 assert_eq!(cell.unwrap(), "id_0");
666 }
667
668 #[test]
669 fn f005_adapter_get_cell_second_batch() {
670 let adapter = create_test_adapter();
671 let cell = adapter.get_cell(5, 0).unwrap();
672 assert!(cell.is_some(), "FALSIFIED: Cell should exist");
673 assert_eq!(cell.unwrap(), "id_5");
674 }
675
676 #[test]
677 fn f006_adapter_get_cell_row_out_of_bounds() {
678 let adapter = create_test_adapter();
679 let cell = adapter.get_cell(100, 0).unwrap();
680 assert!(
681 cell.is_none(),
682 "FALSIFIED: Out of bounds row should return None"
683 );
684 }
685
686 #[test]
687 fn f007_adapter_get_cell_col_out_of_bounds() {
688 let adapter = create_test_adapter();
689 let cell = adapter.get_cell(0, 100).unwrap();
690 assert!(
691 cell.is_none(),
692 "FALSIFIED: Out of bounds column should return None"
693 );
694 }
695
696 #[test]
697 fn f008_adapter_empty() {
698 let adapter = DatasetAdapter::empty();
699 assert_eq!(adapter.row_count(), 0);
700 assert_eq!(adapter.column_count(), 0);
701 assert!(adapter.is_empty());
702 }
703
704 #[test]
705 fn f009_adapter_empty_get_cell() {
706 let adapter = DatasetAdapter::empty();
707 let cell = adapter.get_cell(0, 0).unwrap();
708 assert!(
709 cell.is_none(),
710 "FALSIFIED: Empty adapter should return None"
711 );
712 }
713
714 #[test]
715 fn f010_adapter_field_name() {
716 let adapter = create_test_adapter();
717 assert_eq!(adapter.field_name(0), Some("id"));
718 assert_eq!(adapter.field_name(1), Some("value"));
719 assert_eq!(adapter.field_name(100), None);
720 }
721
722 #[test]
723 fn f011_adapter_field_type() {
724 let adapter = create_test_adapter();
725 let type_str = adapter.field_type(0).unwrap();
726 assert!(type_str.contains("Utf8"), "FALSIFIED: id should be Utf8");
727 }
728
729 #[test]
730 fn f012_adapter_field_nullable() {
731 let adapter = create_test_adapter();
732 assert_eq!(
733 adapter.field_nullable(0),
734 Some(false),
735 "FALSIFIED: id should not be nullable"
736 );
737 }
738
739 #[test]
740 fn f013_adapter_column_widths() {
741 let adapter = create_test_adapter();
742 let widths = adapter.calculate_column_widths(80, 5);
743 assert_eq!(
744 widths.len(),
745 3,
746 "FALSIFIED: Should have width for each column"
747 );
748 for (i, w) in widths.iter().enumerate() {
749 assert!(*w >= 3, "FALSIFIED: Column {} width {} below minimum", i, w);
750 }
751 }
752
753 #[test]
754 fn f014_adapter_column_widths_constrained() {
755 let adapter = create_test_adapter();
756 let widths = adapter.calculate_column_widths(15, 5);
757 let total: u16 = widths.iter().sum();
758 let separators = (widths.len() as u16).saturating_sub(1);
759 assert!(
760 total + separators <= 15,
761 "FALSIFIED: Total width {} exceeds constraint 15",
762 total + separators
763 );
764 }
765
766 #[test]
767 fn f015_adapter_locate_row_first_batch() {
768 let adapter = create_test_adapter();
769 let loc = adapter.locate_row(0);
770 assert_eq!(loc, Some((0, 0)), "FALSIFIED: Row 0 should be in batch 0");
771 }
772
773 #[test]
774 fn f016_adapter_locate_row_second_batch() {
775 let adapter = create_test_adapter();
776 let loc = adapter.locate_row(5);
777 assert_eq!(
778 loc,
779 Some((1, 0)),
780 "FALSIFIED: Row 5 should be first row of batch 1"
781 );
782 }
783
784 #[test]
785 fn f017_adapter_locate_row_last() {
786 let adapter = create_test_adapter();
787 let loc = adapter.locate_row(9);
788 assert_eq!(
789 loc,
790 Some((1, 4)),
791 "FALSIFIED: Row 9 should be last row of batch 1"
792 );
793 }
794
795 #[test]
796 fn f018_adapter_locate_row_out_of_bounds() {
797 let adapter = create_test_adapter();
798 let loc = adapter.locate_row(100);
799 assert_eq!(loc, None, "FALSIFIED: Out of bounds should return None");
800 }
801
802 #[test]
803 fn f019_adapter_is_clone() {
804 let adapter = create_test_adapter();
805 let cloned = adapter.clone();
806 assert_eq!(adapter.row_count(), cloned.row_count());
807 assert_eq!(adapter.column_count(), cloned.column_count());
808 }
809
810 #[test]
811 fn f020_adapter_schema_o1() {
812 let adapter = create_test_adapter();
813 for _ in 0..10000 {
814 let _ = adapter.schema();
815 }
816 }
817
818 #[test]
819 fn f021_adapter_row_count_o1() {
820 let adapter = create_test_adapter();
821 for _ in 0..10000 {
822 let _ = adapter.row_count();
823 }
824 }
825
826 #[test]
827 fn f022_adapter_int_formatting() {
828 let adapter = create_test_adapter();
829 let cell = adapter.get_cell(0, 1).unwrap().unwrap();
830 assert_eq!(cell, "0", "FALSIFIED: First value should be 0");
831 }
832
833 #[test]
834 fn f023_adapter_float_formatting() {
835 let adapter = create_test_adapter();
836 let cell = adapter.get_cell(1, 2).unwrap().unwrap();
837 assert!(cell.contains("0.1"), "FALSIFIED: Score should be ~0.1");
838 }
839
840 #[test]
841 fn f024_adapter_large_row_index() {
842 let adapter = create_test_adapter();
843 let cell = adapter.get_cell(usize::MAX, 0).unwrap();
844 assert!(cell.is_none(), "FALSIFIED: usize::MAX should not panic");
845 }
846
847 #[test]
848 fn f025_adapter_large_col_index() {
849 let adapter = create_test_adapter();
850 let cell = adapter.get_cell(0, usize::MAX).unwrap();
851 assert!(
852 cell.is_none(),
853 "FALSIFIED: usize::MAX column should not panic"
854 );
855 }
856
857 #[test]
858 fn f026_adapter_from_dataset() {
859 let schema = create_test_schema();
860 let batch = create_test_batch(&schema, 0, 5);
861 let dataset = ArrowDataset::from_batch(batch).unwrap();
862
863 let adapter = DatasetAdapter::from_dataset(&dataset).unwrap();
864 assert_eq!(adapter.row_count(), 5);
865 assert_eq!(adapter.column_count(), 3);
866 assert_eq!(adapter.field_name(0), Some("id"));
867 }
868
869 #[test]
870 fn f027_adapter_single_batch() {
871 let schema = create_test_schema();
872 let batch = create_test_batch(&schema, 0, 10);
873 let adapter = DatasetAdapter::from_batches(vec![batch], schema).unwrap();
874
875 assert_eq!(adapter.row_count(), 10);
876 assert_eq!(adapter.get_cell(0, 0).unwrap(), Some("id_0".to_string()));
877 assert_eq!(adapter.get_cell(9, 0).unwrap(), Some("id_9".to_string()));
878 }
879
880 #[test]
881 fn f028_adapter_multi_batch_boundaries() {
882 let schema = create_test_schema();
883 let batch1 = create_test_batch(&schema, 0, 3);
884 let batch2 = create_test_batch(&schema, 3, 3);
885 let batch3 = create_test_batch(&schema, 6, 3);
886 let adapter =
887 DatasetAdapter::from_batches(vec![batch1, batch2, batch3], schema.clone()).unwrap();
888
889 assert_eq!(adapter.row_count(), 9);
890 assert_eq!(adapter.get_cell(2, 0).unwrap(), Some("id_2".to_string()));
891 assert_eq!(adapter.get_cell(3, 0).unwrap(), Some("id_3".to_string()));
892 assert_eq!(adapter.get_cell(8, 0).unwrap(), Some("id_8".to_string()));
893 }
894
895 #[test]
896 fn f029_adapter_empty_schema_columns() {
897 let schema = create_test_schema();
898 let batch1 = create_test_batch(&schema, 0, 5);
899 let batch2 = create_test_batch(&schema, 5, 5);
900 let adapter = DatasetAdapter::from_batches(vec![batch1, batch2], schema.clone()).unwrap();
901
902 let widths = adapter.calculate_column_widths(100, 10);
903 assert_eq!(widths.len(), 3);
904 }
905
906 #[test]
907 fn f030_adapter_empty_batches() {
908 let schema = create_test_schema();
909 let adapter = DatasetAdapter::from_batches(vec![], schema).unwrap();
910 assert!(adapter.is_empty());
911 assert_eq!(adapter.row_count(), 0);
912 assert_eq!(adapter.get_cell(0, 0).unwrap(), None);
913 }
914
915 #[test]
916 fn f031_adapter_empty_schema_field_names() {
917 let schema = create_test_schema();
918 let adapter = DatasetAdapter::from_batches(vec![], schema).unwrap();
919 let names = adapter.field_names();
920 assert_eq!(names, vec!["id", "value", "score"]);
921 }
922
923 #[test]
926 fn f032_adapter_is_streaming() {
927 let adapter = create_test_adapter();
928 assert!(
929 !adapter.is_streaming(),
930 "FALSIFIED: Small dataset should be InMemory"
931 );
932 }
933
934 #[test]
935 fn f033_adapter_streaming_mode() {
936 let schema = create_test_schema();
937 let batch = create_test_batch(&schema, 0, 5);
938 let adapter = DatasetAdapter::streaming_from_batches(vec![batch], schema).unwrap();
939 assert!(
940 adapter.is_streaming(),
941 "FALSIFIED: Should be Streaming mode"
942 );
943 assert_eq!(adapter.row_count(), 5);
944 }
945
946 #[test]
947 fn f034_adapter_search_finds_match() {
948 let adapter = create_test_adapter();
949 let result = adapter.search("id_5");
950 assert_eq!(
951 result,
952 Some(5),
953 "FALSIFIED: Search should find 'id_5' at row 5"
954 );
955 }
956
957 #[test]
958 fn f035_adapter_search_no_match() {
959 let adapter = create_test_adapter();
960 let result = adapter.search("nonexistent_value");
961 assert_eq!(result, None, "FALSIFIED: Search should return None");
962 }
963
964 #[test]
965 fn f036_adapter_search_empty_query() {
966 let adapter = create_test_adapter();
967 let result = adapter.search("");
968 assert_eq!(result, None, "FALSIFIED: Empty query should return None");
969 }
970
971 #[test]
972 fn f037_adapter_search_case_insensitive() {
973 let adapter = create_test_adapter();
974 let result = adapter.search("ID_3");
975 assert_eq!(
976 result,
977 Some(3),
978 "FALSIFIED: Search should be case insensitive"
979 );
980 }
981
982 #[test]
983 fn f038_adapter_search_from_wraps() {
984 let adapter = create_test_adapter();
985 let result = adapter.search_from("id_0", 8);
987 assert_eq!(result, Some(0), "FALSIFIED: Search should wrap around");
988 }
989
990 #[test]
991 fn f039_adapter_unicode_width() {
992 let schema = Arc::new(Schema::new(vec![Field::new(
994 "emoji",
995 DataType::Utf8,
996 false,
997 )]));
998
999 let batch = RecordBatch::try_new(
1000 schema.clone(),
1001 vec![Arc::new(StringArray::from(vec!["👨👩👧👦", "hello"]))],
1002 )
1003 .unwrap();
1004
1005 let adapter = DatasetAdapter::from_batches(vec![batch], schema).unwrap();
1006 let widths = adapter.calculate_column_widths(80, 10);
1007
1008 assert!(
1011 widths[0] >= 3,
1012 "FALSIFIED: Column width should be at least minimum"
1013 );
1014 }
1015
1016 #[test]
1019 fn f040_streaming_adapter_get_cell() {
1020 let schema = create_test_schema();
1021 let batch = create_test_batch(&schema, 0, 5);
1022 let adapter = DatasetAdapter::streaming_from_batches(vec![batch], schema).unwrap();
1023
1024 let cell = adapter.get_cell(0, 0).unwrap();
1025 assert_eq!(cell, Some("id_0".to_string()));
1026 }
1027
1028 #[test]
1029 fn f041_streaming_adapter_field_name() {
1030 let schema = create_test_schema();
1031 let batch = create_test_batch(&schema, 0, 5);
1032 let adapter = DatasetAdapter::streaming_from_batches(vec![batch], schema).unwrap();
1033
1034 assert_eq!(adapter.field_name(0), Some("id"));
1035 assert_eq!(adapter.field_name(1), Some("value"));
1036 assert_eq!(adapter.field_name(100), None);
1037 }
1038
1039 #[test]
1040 fn f042_streaming_adapter_field_type() {
1041 let schema = create_test_schema();
1042 let batch = create_test_batch(&schema, 0, 5);
1043 let adapter = DatasetAdapter::streaming_from_batches(vec![batch], schema).unwrap();
1044
1045 let type_str = adapter.field_type(0).unwrap();
1046 assert!(type_str.contains("Utf8"));
1047 assert!(adapter.field_type(100).is_none());
1048 }
1049
1050 #[test]
1051 fn f043_streaming_adapter_field_nullable() {
1052 let schema = create_test_schema();
1053 let batch = create_test_batch(&schema, 0, 5);
1054 let adapter = DatasetAdapter::streaming_from_batches(vec![batch], schema).unwrap();
1055
1056 assert_eq!(adapter.field_nullable(0), Some(false));
1057 assert!(adapter.field_nullable(100).is_none());
1058 }
1059
1060 #[test]
1061 fn f044_streaming_adapter_locate_row() {
1062 let schema = create_test_schema();
1063 let batch1 = create_test_batch(&schema, 0, 5);
1064 let batch2 = create_test_batch(&schema, 5, 5);
1065 let adapter = DatasetAdapter::streaming_from_batches(vec![batch1, batch2], schema).unwrap();
1066
1067 assert_eq!(adapter.locate_row(0), Some((0, 0)));
1068 assert_eq!(adapter.locate_row(4), Some((0, 4)));
1069 assert_eq!(adapter.locate_row(5), Some((1, 0)));
1070 assert_eq!(adapter.locate_row(9), Some((1, 4)));
1071 assert_eq!(adapter.locate_row(100), None);
1072 }
1073
1074 #[test]
1075 fn f045_streaming_adapter_column_widths() {
1076 let schema = create_test_schema();
1077 let batch = create_test_batch(&schema, 0, 5);
1078 let adapter = DatasetAdapter::streaming_from_batches(vec![batch], schema).unwrap();
1079
1080 let widths = adapter.calculate_column_widths(80, 5);
1081 assert_eq!(widths.len(), 3);
1082 for w in &widths {
1083 assert!(*w >= 3);
1084 }
1085 }
1086
1087 #[test]
1088 fn f046_streaming_adapter_field_names() {
1089 let schema = create_test_schema();
1090 let batch = create_test_batch(&schema, 0, 5);
1091 let adapter = DatasetAdapter::streaming_from_batches(vec![batch], schema).unwrap();
1092
1093 let names = adapter.field_names();
1094 assert_eq!(names, vec!["id", "value", "score"]);
1095 }
1096
1097 #[test]
1098 fn f047_streaming_adapter_out_of_bounds() {
1099 let schema = create_test_schema();
1100 let batch = create_test_batch(&schema, 0, 5);
1101 let adapter = DatasetAdapter::streaming_from_batches(vec![batch], schema).unwrap();
1102
1103 assert_eq!(adapter.get_cell(100, 0).unwrap(), None);
1105 assert_eq!(adapter.get_cell(0, 100).unwrap(), None);
1107 }
1108
1109 #[test]
1110 fn f048_streaming_adapter_schema() {
1111 let schema = create_test_schema();
1112 let batch = create_test_batch(&schema, 0, 5);
1113 let adapter = DatasetAdapter::streaming_from_batches(vec![batch], schema).unwrap();
1114
1115 assert_eq!(adapter.schema().fields().len(), 3);
1116 }
1117
1118 #[test]
1119 fn f049_search_from_empty_query() {
1120 let adapter = create_test_adapter();
1121 let result = adapter.search_from("", 0);
1122 assert_eq!(result, None);
1123 }
1124
1125 #[test]
1126 fn f050_search_from_no_wrap_needed() {
1127 let adapter = create_test_adapter();
1128 let result = adapter.search_from("id_5", 0);
1130 assert_eq!(result, Some(5));
1131 }
1132
1133 #[test]
1134 fn f051_search_from_no_match() {
1135 let adapter = create_test_adapter();
1136 let result = adapter.search_from("nonexistent", 0);
1137 assert_eq!(result, None);
1138 }
1139
1140 #[test]
1141 fn f052_streaming_adapter_empty_batches() {
1142 let schema = create_test_schema();
1143 let adapter = DatasetAdapter::streaming_from_batches(vec![], schema).unwrap();
1144
1145 assert_eq!(adapter.row_count(), 0);
1146 assert_eq!(adapter.column_count(), 3);
1147 assert!(adapter.is_streaming());
1148 }
1149
1150 #[test]
1151 fn f053_streaming_adapter_column_widths_empty() {
1152 let schema = Arc::new(Schema::empty());
1153 let adapter = DatasetAdapter::streaming_from_batches(vec![], schema).unwrap();
1154
1155 let widths = adapter.calculate_column_widths(80, 10);
1156 assert!(widths.is_empty());
1157 }
1158
1159 #[test]
1160 fn f054_streaming_adapter_column_widths_constrained() {
1161 let schema = create_test_schema();
1162 let batch = create_test_batch(&schema, 0, 5);
1163 let adapter = DatasetAdapter::streaming_from_batches(vec![batch], schema).unwrap();
1164
1165 let widths = adapter.calculate_column_widths(15, 5);
1167 let total: u16 = widths.iter().sum();
1168 let separators = (widths.len() as u16).saturating_sub(1);
1169 assert!(total + separators <= 15);
1170 }
1171
1172 #[test]
1173 fn f055_in_memory_adapter_empty_row_count() {
1174 let schema = create_test_schema();
1175 let adapter = DatasetAdapter::in_memory_from_batches(vec![], schema.clone()).unwrap();
1176
1177 assert_eq!(adapter.row_count(), 0);
1178 assert!(!adapter.is_streaming());
1179 }
1180
1181 #[test]
1182 fn f056_in_memory_adapter_locate_row_boundary() {
1183 let schema = create_test_schema();
1184 let batch1 = create_test_batch(&schema, 0, 3);
1185 let batch2 = create_test_batch(&schema, 3, 3);
1186 let batch3 = create_test_batch(&schema, 6, 4);
1187 let adapter =
1188 DatasetAdapter::in_memory_from_batches(vec![batch1, batch2, batch3], schema).unwrap();
1189
1190 assert_eq!(adapter.locate_row(2), Some((0, 2))); assert_eq!(adapter.locate_row(3), Some((1, 0))); assert_eq!(adapter.locate_row(5), Some((1, 2))); assert_eq!(adapter.locate_row(6), Some((2, 0))); assert_eq!(adapter.locate_row(9), Some((2, 3))); }
1197
1198 #[test]
1199 fn f057_search_on_streaming_adapter() {
1200 let schema = create_test_schema();
1201 let batch = create_test_batch(&schema, 0, 10);
1202 let adapter = DatasetAdapter::streaming_from_batches(vec![batch], schema).unwrap();
1203
1204 let result = adapter.search("id_7");
1205 assert_eq!(result, Some(7));
1206 }
1207
1208 #[test]
1209 fn f058_search_from_on_streaming_adapter() {
1210 let schema = create_test_schema();
1211 let batch = create_test_batch(&schema, 0, 10);
1212 let adapter = DatasetAdapter::streaming_from_batches(vec![batch], schema).unwrap();
1213
1214 let result = adapter.search_from("id_3", 8);
1216 assert_eq!(result, Some(3));
1217 }
1218
1219 #[test]
1220 fn f059_search_partial_match() {
1221 let adapter = create_test_adapter();
1222 let result = adapter.search("id_");
1224 assert_eq!(result, Some(0));
1225 }
1226
1227 #[test]
1228 fn f060_search_numeric_value() {
1229 let adapter = create_test_adapter();
1230 let result = adapter.search("10");
1232 assert!(result.is_some());
1233 }
1234
1235 #[test]
1236 fn f061_empty_adapter_search() {
1237 let adapter = DatasetAdapter::empty();
1238 assert_eq!(adapter.search("anything"), None);
1239 assert_eq!(adapter.search_from("anything", 0), None);
1240 }
1241
1242 #[test]
1243 fn f062_column_widths_zero_sample() {
1244 let adapter = create_test_adapter();
1245 let widths = adapter.calculate_column_widths(80, 0);
1246 assert_eq!(widths.len(), 3);
1248 }
1249
1250 #[test]
1251 fn f063_column_widths_large_sample() {
1252 let adapter = create_test_adapter();
1253 let widths = adapter.calculate_column_widths(80, 1000);
1255 assert_eq!(widths.len(), 3);
1256 }
1257
1258 #[test]
1259 fn f064_streaming_locate_row_exact_boundary() {
1260 let schema = create_test_schema();
1261 let batch1 = create_test_batch(&schema, 0, 5);
1262 let batch2 = create_test_batch(&schema, 5, 5);
1263 let adapter = DatasetAdapter::streaming_from_batches(vec![batch1, batch2], schema).unwrap();
1264
1265 let loc = adapter.locate_row(0);
1267 assert_eq!(loc, Some((0, 0)));
1268
1269 let loc = adapter.locate_row(5);
1270 assert_eq!(loc, Some((1, 0)));
1271 }
1272
1273 #[test]
1274 fn f065_in_memory_adapter_debug() {
1275 let adapter = create_test_adapter();
1276 let debug = format!("{:?}", adapter);
1277 assert!(debug.contains("InMemory"));
1278 }
1279
1280 #[test]
1281 fn f066_streaming_adapter_debug() {
1282 let schema = create_test_schema();
1283 let batch = create_test_batch(&schema, 0, 5);
1284 let adapter = DatasetAdapter::streaming_from_batches(vec![batch], schema).unwrap();
1285 let debug = format!("{:?}", adapter);
1286 assert!(debug.contains("Streaming"));
1287 }
1288
1289 #[test]
1290 fn f067_in_memory_empty_direct() {
1291 let adapter = InMemoryAdapter::empty();
1292 assert_eq!(adapter.row_count(), 0);
1293 assert_eq!(adapter.column_count(), 0);
1294 assert!(adapter.schema().fields().is_empty());
1295 }
1296
1297 #[test]
1298 fn f068_adapter_from_dataset_small() {
1299 let schema = create_test_schema();
1300 let batch = create_test_batch(&schema, 0, 50);
1301 let dataset = ArrowDataset::from_batch(batch).unwrap();
1302
1303 let adapter = DatasetAdapter::from_dataset(&dataset).unwrap();
1304 assert!(!adapter.is_streaming());
1306 assert_eq!(adapter.row_count(), 50);
1307 }
1308
1309 #[test]
1314 fn f069_in_memory_adapter_get_cell_batch_not_found() {
1315 let schema = create_test_schema();
1317 let adapter = InMemoryAdapter::new(vec![], schema).unwrap();
1318 let result = adapter.get_cell(0, 0).unwrap();
1319 assert!(result.is_none());
1320 }
1321
1322 #[test]
1323 fn f070_streaming_adapter_get_cell_batch_not_found() {
1324 let schema = create_test_schema();
1326 let adapter = StreamingAdapter::new(vec![], schema).unwrap();
1327 let result = adapter.get_cell(0, 0).unwrap();
1328 assert!(result.is_none());
1329 }
1330
1331 #[test]
1332 fn f071_in_memory_adapter_locate_row_at_batch_boundary() {
1333 let schema = create_test_schema();
1334 let batch1 = create_test_batch(&schema, 0, 5);
1335 let batch2 = create_test_batch(&schema, 5, 5);
1336 let adapter = InMemoryAdapter::new(vec![batch1, batch2], schema).unwrap();
1337
1338 let loc = adapter.locate_row(5);
1340 assert_eq!(loc, Some((1, 0)));
1341
1342 let loc = adapter.locate_row(4);
1344 assert_eq!(loc, Some((0, 4)));
1345 }
1346
1347 #[test]
1348 fn f072_streaming_adapter_locate_row_at_batch_boundary() {
1349 let schema = create_test_schema();
1350 let batch1 = create_test_batch(&schema, 0, 5);
1351 let batch2 = create_test_batch(&schema, 5, 5);
1352 let adapter = StreamingAdapter::new(vec![batch1, batch2], schema).unwrap();
1353
1354 let loc = adapter.locate_row(5);
1356 assert_eq!(loc, Some((1, 0)));
1357 }
1358
1359 #[test]
1360 fn f073_in_memory_adapter_schema_access() {
1361 let schema = create_test_schema();
1362 let adapter = InMemoryAdapter::new(vec![], schema.clone()).unwrap();
1363 assert_eq!(adapter.schema().fields().len(), 3);
1364 }
1365
1366 #[test]
1367 fn f074_streaming_adapter_schema_access() {
1368 let schema = create_test_schema();
1369 let adapter = StreamingAdapter::new(vec![], schema.clone()).unwrap();
1370 assert_eq!(adapter.schema().fields().len(), 3);
1371 }
1372
1373 #[test]
1374 fn f075_in_memory_adapter_row_count() {
1375 let schema = create_test_schema();
1376 let batch = create_test_batch(&schema, 0, 7);
1377 let adapter = InMemoryAdapter::new(vec![batch], schema).unwrap();
1378 assert_eq!(adapter.row_count(), 7);
1379 }
1380
1381 #[test]
1382 fn f076_streaming_adapter_row_count() {
1383 let schema = create_test_schema();
1384 let batch = create_test_batch(&schema, 0, 7);
1385 let adapter = StreamingAdapter::new(vec![batch], schema).unwrap();
1386 assert_eq!(adapter.row_count(), 7);
1387 }
1388
1389 #[test]
1390 fn f077_in_memory_adapter_column_count() {
1391 let schema = create_test_schema();
1392 let adapter = InMemoryAdapter::new(vec![], schema).unwrap();
1393 assert_eq!(adapter.column_count(), 3);
1394 }
1395
1396 #[test]
1397 fn f078_streaming_adapter_column_count() {
1398 let schema = create_test_schema();
1399 let adapter = StreamingAdapter::new(vec![], schema).unwrap();
1400 assert_eq!(adapter.column_count(), 3);
1401 }
1402
1403 #[test]
1404 fn f079_in_memory_adapter_field_names() {
1405 let schema = create_test_schema();
1406 let adapter = InMemoryAdapter::new(vec![], schema).unwrap();
1407 let names = adapter.field_names();
1408 assert_eq!(names, vec!["id", "value", "score"]);
1409 }
1410
1411 #[test]
1412 fn f080_in_memory_adapter_field_name_out_of_bounds() {
1413 let schema = create_test_schema();
1414 let adapter = InMemoryAdapter::new(vec![], schema).unwrap();
1415 assert!(adapter.field_name(100).is_none());
1416 }
1417
1418 #[test]
1419 fn f081_in_memory_adapter_field_type_out_of_bounds() {
1420 let schema = create_test_schema();
1421 let adapter = InMemoryAdapter::new(vec![], schema).unwrap();
1422 assert!(adapter.field_type(100).is_none());
1423 }
1424
1425 #[test]
1426 fn f082_in_memory_adapter_field_nullable_out_of_bounds() {
1427 let schema = create_test_schema();
1428 let adapter = InMemoryAdapter::new(vec![], schema).unwrap();
1429 assert!(adapter.field_nullable(100).is_none());
1430 }
1431
1432 #[test]
1433 fn f083_streaming_adapter_field_name_out_of_bounds() {
1434 let schema = create_test_schema();
1435 let adapter = StreamingAdapter::new(vec![], schema).unwrap();
1436 assert!(adapter.field_name(100).is_none());
1437 }
1438
1439 #[test]
1440 fn f084_streaming_adapter_field_type_out_of_bounds() {
1441 let schema = create_test_schema();
1442 let adapter = StreamingAdapter::new(vec![], schema).unwrap();
1443 assert!(adapter.field_type(100).is_none());
1444 }
1445
1446 #[test]
1447 fn f085_streaming_adapter_field_nullable_out_of_bounds() {
1448 let schema = create_test_schema();
1449 let adapter = StreamingAdapter::new(vec![], schema).unwrap();
1450 assert!(adapter.field_nullable(100).is_none());
1451 }
1452
1453 #[test]
1454 fn f086_in_memory_calculate_column_widths_empty_schema() {
1455 let schema = Arc::new(Schema::empty());
1456 let adapter = InMemoryAdapter::new(vec![], schema).unwrap();
1457 let widths = adapter.calculate_column_widths(80, 10);
1458 assert!(widths.is_empty());
1459 }
1460
1461 #[test]
1462 fn f087_in_memory_calculate_column_widths_scaling() {
1463 let schema = create_test_schema();
1464 let batch = create_test_batch(&schema, 0, 5);
1465 let adapter = InMemoryAdapter::new(vec![batch], schema).unwrap();
1466
1467 let widths = adapter.calculate_column_widths(12, 5);
1469 let total: u16 = widths.iter().sum();
1470 let separators = (widths.len() as u16).saturating_sub(1);
1471 assert!(total + separators <= 12);
1472 }
1473
1474 #[test]
1475 fn f088_streaming_calculate_column_widths_scaling() {
1476 let schema = create_test_schema();
1477 let batch = create_test_batch(&schema, 0, 5);
1478 let adapter = StreamingAdapter::new(vec![batch], schema).unwrap();
1479
1480 let widths = adapter.calculate_column_widths(12, 5);
1482 let total: u16 = widths.iter().sum();
1483 let separators = (widths.len() as u16).saturating_sub(1);
1484 assert!(total + separators <= 12);
1485 }
1486
1487 #[test]
1488 fn f089_adapter_search_empty_dataset() {
1489 let adapter = DatasetAdapter::empty();
1490 assert!(adapter.search("anything").is_none());
1491 }
1492
1493 #[test]
1494 fn f090_adapter_search_from_start_row_beyond_total() {
1495 let adapter = create_test_adapter();
1496 let result = adapter.search_from("id_0", 100);
1498 assert_eq!(result, Some(0));
1500 }
1501
1502 #[test]
1503 fn f091_in_memory_locate_row_binary_search_ok_branch() {
1504 let schema = create_test_schema();
1506 let batch1 = create_test_batch(&schema, 0, 3);
1507 let batch2 = create_test_batch(&schema, 3, 3);
1508 let adapter = InMemoryAdapter::new(vec![batch1, batch2], schema).unwrap();
1509
1510 let loc = adapter.locate_row(3);
1512 assert_eq!(loc, Some((1, 0)));
1513
1514 let loc = adapter.locate_row(0);
1516 assert_eq!(loc, Some((0, 0)));
1517 }
1518
1519 #[test]
1520 fn f092_streaming_locate_row_binary_search_ok_branch() {
1521 let schema = create_test_schema();
1522 let batch1 = create_test_batch(&schema, 0, 3);
1523 let batch2 = create_test_batch(&schema, 3, 3);
1524 let adapter = StreamingAdapter::new(vec![batch1, batch2], schema).unwrap();
1525
1526 let loc = adapter.locate_row(3);
1527 assert_eq!(loc, Some((1, 0)));
1528
1529 let loc = adapter.locate_row(0);
1530 assert_eq!(loc, Some((0, 0)));
1531 }
1532
1533 #[test]
1534 fn f093_adapter_field_type_streaming_mode() {
1535 let schema = create_test_schema();
1536 let batch = create_test_batch(&schema, 0, 5);
1537 let adapter = DatasetAdapter::streaming_from_batches(vec![batch], schema).unwrap();
1538
1539 let type_str = adapter.field_type(0);
1540 assert!(type_str.is_some());
1541 assert!(type_str.unwrap().contains("Utf8"));
1542 }
1543
1544 #[test]
1545 fn f094_adapter_field_nullable_streaming_mode() {
1546 let schema = create_test_schema();
1547 let batch = create_test_batch(&schema, 0, 5);
1548 let adapter = DatasetAdapter::streaming_from_batches(vec![batch], schema).unwrap();
1549
1550 let nullable = adapter.field_nullable(0);
1551 assert_eq!(nullable, Some(false));
1552 }
1553
1554 #[test]
1555 fn f095_adapter_locate_row_streaming_mode() {
1556 let schema = create_test_schema();
1557 let batch = create_test_batch(&schema, 0, 5);
1558 let adapter = DatasetAdapter::streaming_from_batches(vec![batch], schema).unwrap();
1559
1560 let loc = adapter.locate_row(2);
1561 assert_eq!(loc, Some((0, 2)));
1562
1563 let loc_oob = adapter.locate_row(100);
1564 assert!(loc_oob.is_none());
1565 }
1566
1567 #[test]
1568 fn f096_in_memory_adapter_with_many_batches() {
1569 let schema = create_test_schema();
1570 let batches: Vec<_> = (0..10)
1571 .map(|i| create_test_batch(&schema, i * 5, 5))
1572 .collect();
1573 let adapter = InMemoryAdapter::new(batches, schema).unwrap();
1574
1575 assert_eq!(adapter.row_count(), 50);
1576
1577 assert_eq!(adapter.locate_row(0), Some((0, 0)));
1579 assert_eq!(adapter.locate_row(7), Some((1, 2)));
1580 assert_eq!(adapter.locate_row(49), Some((9, 4)));
1581 }
1582
1583 #[test]
1584 fn f097_streaming_adapter_with_many_batches() {
1585 let schema = create_test_schema();
1586 let batches: Vec<_> = (0..10)
1587 .map(|i| create_test_batch(&schema, i * 5, 5))
1588 .collect();
1589 let adapter = StreamingAdapter::new(batches, schema).unwrap();
1590
1591 assert_eq!(adapter.row_count(), 50);
1592 assert_eq!(adapter.locate_row(7), Some((1, 2)));
1593 }
1594
1595 #[test]
1596 fn f098_adapter_search_in_numeric_column() {
1597 let adapter = create_test_adapter();
1598 let result = adapter.search("30");
1600 assert!(result.is_some());
1601 }
1602
1603 #[test]
1604 fn f099_adapter_search_partial_match() {
1605 let adapter = create_test_adapter();
1606 let result = adapter.search("d_3");
1608 assert_eq!(result, Some(3));
1609 }
1610
1611 #[test]
1612 fn f100_adapter_is_empty_with_batches() {
1613 let schema = create_test_schema();
1614 let batch = create_test_batch(&schema, 0, 5);
1615 let adapter = DatasetAdapter::from_batches(vec![batch], schema).unwrap();
1616 assert!(!adapter.is_empty());
1617 }
1618
1619 #[test]
1620 fn f101_streaming_adapter_search() {
1621 let schema = create_test_schema();
1622 let batch = create_test_batch(&schema, 0, 10);
1623 let adapter = DatasetAdapter::streaming_from_batches(vec![batch], schema).unwrap();
1624
1625 let result = adapter.search("id_5");
1626 assert_eq!(result, Some(5));
1627 }
1628
1629 #[test]
1630 fn f102_streaming_adapter_search_from() {
1631 let schema = create_test_schema();
1632 let batch = create_test_batch(&schema, 0, 10);
1633 let adapter = DatasetAdapter::streaming_from_batches(vec![batch], schema).unwrap();
1634
1635 let result = adapter.search_from("id_2", 7);
1637 assert_eq!(result, Some(2));
1638 }
1639
1640 #[test]
1641 fn f103_calculate_column_widths_with_unicode() {
1642 let schema = Arc::new(Schema::new(vec![Field::new("name", DataType::Utf8, false)]));
1644
1645 let batch = RecordBatch::try_new(
1646 schema.clone(),
1647 vec![Arc::new(StringArray::from(vec!["Hello", "World"]))],
1648 )
1649 .unwrap();
1650
1651 let adapter = DatasetAdapter::from_batches(vec![batch], schema).unwrap();
1652 let widths = adapter.calculate_column_widths(80, 10);
1653 assert!(!widths.is_empty());
1654 assert!(widths[0] >= 4); }
1656
1657 #[test]
1658 fn f104_in_memory_empty_direct_methods() {
1659 let adapter = InMemoryAdapter::empty();
1660 assert_eq!(adapter.row_count(), 0);
1661 assert_eq!(adapter.column_count(), 0);
1662 assert!(adapter.field_name(0).is_none());
1663 assert!(adapter.field_type(0).is_none());
1664 assert!(adapter.field_nullable(0).is_none());
1665 assert!(adapter.locate_row(0).is_none());
1666 }
1667}