// Copyright 2024 PingCAP, Inc.

mod builder;
mod cache;
mod columnar;
mod columnar_meta_cache;
pub mod filter;
mod reader;

pub use builder::*;
pub use cache::*;
pub use columnar::*;
pub use columnar_meta_cache::*;
pub use reader::*;

/// Columnar readers treat int-handle range ends as exclusive.
///
/// A bare `encode_row_key(table_id, i64::MAX)` still means `< i64::MAX`.
/// Only keys that sort strictly after that row key, such as `MAX + b"\0"`,
/// should be treated as unbounded and include the real `INT64_MAX` row.
pub(crate) fn decode_exclusive_end_int_handle(end_key: &[u8]) -> Option<i64> {
    use tidb_query_datatype::codec::table::{RECORD_ROW_KEY_LEN, decode_int_handle};

    let end_handle = decode_int_handle(end_key).ok()?;
    if end_handle == i64::MAX && end_key.len() > RECORD_ROW_KEY_LEN {
        None
    } else {
        Some(end_handle)
    }
}

#[cfg(test)]
mod decode_tests {
    use tidb_query_datatype::codec::table::encode_row_key;

    use super::decode_exclusive_end_int_handle;

    #[test]
    fn test_decode_exclusive_end_int_handle() {
        let table_id = 100;
        let normal = encode_row_key(table_id, 123);
        let max = encode_row_key(table_id, i64::MAX);
        let mut max_inclusive_end = max.clone();
        max_inclusive_end.push(0);

        assert_eq!(decode_exclusive_end_int_handle(&normal), Some(123));
        assert_eq!(decode_exclusive_end_int_handle(&max), Some(i64::MAX));
        assert_eq!(decode_exclusive_end_int_handle(&max_inclusive_end), None);
    }
}
