vortex-array 0.88.0

Vortex in memory columnar data format
Documentation
// SPDX-License-Identifier: Apache-2.0
// SPDX-FileCopyrightText: Copyright the Vortex contributors

use super::*;

#[rstest::rstest]
// Just past the inline boundary, typical, and large values.
#[case(13, 7, 42)]
#[case(20, 7, 42)]
#[case(255, 7, 42)]
#[case(4096, 7, 42)]
// Zero and `u32::MAX` buffer index/offset, so field assembly cannot overflow unnoticed.
#[case(13, 0, 0)]
#[case(13, u32::MAX, u32::MAX)]
fn new_ref_matches_make_view(#[case] len: u32, #[case] buffer_index: u32, #[case] offset: u32) {
    let value: Vec<u8> = (0..len)
        .map(|i| u8::try_from(i % 251).vortex_expect("i % 251 fits in u8"))
        .collect();
    let prefix = [value[0], value[1], value[2], value[3]];
    let made = BinaryView::make_view(&value, buffer_index, offset);
    let built = BinaryView::new_ref(len, prefix, buffer_index, offset);
    assert_eq!(made.as_u128(), built.as_u128(), "mismatch at len {len}");
    assert!(!built.is_inlined());
    let r = built.as_view();
    assert_eq!(r.size, len);
    assert_eq!(r.prefix, prefix);
    assert_eq!(r.buffer_index, buffer_index);
    assert_eq!(r.offset, offset);
}

/// Byte strings over `{\x00, a, b}` up to `max_len`; `\x00` collides with zero padding.
fn values(max_len: usize) -> Vec<Vec<u8>> {
    let mut values = vec![Vec::new()];
    let mut frontier = vec![Vec::new()];
    for _ in 0..max_len {
        frontier = frontier
            .iter()
            .flat_map(|value| {
                b"\x00a\xff".iter().map(|&byte| {
                    let mut next = value.clone();
                    next.push(byte);
                    next
                })
            })
            .collect();
        values.extend(frontier.iter().cloned());
    }
    values
}

/// A view holding `value`, inlined when it fits and otherwise referencing buffer 0 at offset 0.
fn view_of(value: &[u8]) -> BinaryView {
    BinaryView::make_view(value, 0, 0)
}

#[test]
fn words_match_between_view_and_value() {
    for value in values(5).iter().chain(&[vec![b'z'; 40]]) {
        let view = view_of(value);
        assert_eq!(view.prefix(), BinaryView::prefix_of(value), "{value:?}");
        assert_eq!(view.head(), BinaryView::head_of(value), "{value:?}");
        assert_eq!(
            view.order_prefix(),
            BinaryView::order_prefix_of(value),
            "{value:?}"
        );
        if view.is_inlined() {
            assert_eq!(
                view.order_tail(),
                BinaryView::order_tail_of(value),
                "{value:?}"
            );
        }
    }
}

/// A lower order prefix proves a lower value; an equal one decides nothing.
#[test]
fn order_prefix_refines_value_order() {
    let values = values(6);
    for a in &values {
        for b in &values {
            let (a_prefix, b_prefix) = (
                BinaryView::order_prefix_of(a),
                BinaryView::order_prefix_of(b),
            );
            if a_prefix < b_prefix {
                assert!(a < b, "prefix ordered {a:?} below {b:?}");
            }
            if a == b {
                assert_eq!(a_prefix, b_prefix, "{a:?} disagreed with itself");
            }
        }
    }
}

/// Inlined values are fully ordered by order prefix, then order tail, then length.
#[test]
fn order_words_fully_order_inlined_values() {
    let values = values(4)
        .into_iter()
        .filter(|value| value.len() <= BinaryView::MAX_INLINED_SIZE)
        .collect::<Vec<_>>();
    for a in &values {
        let a_view = view_of(a);
        for b in &values {
            let b_view = view_of(b);
            let by_words = (a_view.order_prefix(), a_view.order_tail(), a_view.len()).cmp(&(
                b_view.order_prefix(),
                b_view.order_tail(),
                b_view.len(),
            ));
            assert_eq!(by_words, a.cmp(b), "words misordered {a:?} against {b:?}");
        }
    }
}

/// The head rules equality out but never in.
#[test]
fn head_rules_out_inequality() {
    let values = values(6);
    for a in &values {
        for b in &values {
            if a == b {
                assert_eq!(BinaryView::head_of(a), BinaryView::head_of(b));
            } else if BinaryView::head_of(a) == BinaryView::head_of(b) {
                assert_eq!(a.len(), b.len(), "head collided across lengths");
                assert_eq!(a[..4.min(a.len())], b[..4.min(b.len())]);
            }
        }
    }
}