wedb_embed 0.1.0

Embedded Kvrocks-compatible storage engine for WeDb
Documentation
use crate::error::{Error, Result};
use serde::{Deserialize, Serialize};

/// 64 位无符号整数十六进制定长字节数(16 字符)
pub const HEX_LEN: usize = 16;

/// 十六进制小写字符查找表
pub const HEX_CHARS: &[u8; 16] = b"0123456789abcdef";

/// 编译期预计算十六进制 ASCII 解码查找表(支持 0-9, a-f, A-F,非法字符为 -1)
const HEX_DECODE_LUT: [i8; 256] = {
    let mut table = [-1i8; 256];
    let mut i = 0;
    while i < 10 {
        table[(b'0' + i) as usize] = i as i8;
        i += 1;
    }
    let mut i = 0;
    while i < 6 {
        table[(b'a' + i) as usize] = (10 + i) as i8;
        table[(b'A' + i) as usize] = (10 + i) as i8;
        i += 1;
    }
    table
};

/// 64 位有序整型集合范围查询规则(对标 Apache Kvrocks SortedintRangeSpec)
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct SortedintRangeSpec {
    pub min: u64,
    pub max: u64,
    pub minex: bool,
    pub maxex: bool,
    pub offset: usize,
    pub count: Option<usize>,
    pub reversed: bool,
}

impl Default for SortedintRangeSpec {
    #[inline]
    fn default() -> Self {
        Self {
            min: u64::MIN,
            max: u64::MAX,
            minex: false,
            maxex: false,
            offset: 0,
            count: None,
            reversed: false,
        }
    }
}

impl SortedintRangeSpec {
    /// 创建全区间范围规则 [0, u64::MAX]
    #[inline]
    pub const fn all() -> Self {
        Self {
            min: u64::MIN,
            max: u64::MAX,
            minex: false,
            maxex: false,
            offset: 0,
            count: None,
            reversed: false,
        }
    }

    /// 设置分页偏移量
    #[inline]
    pub const fn with_offset(mut self, offset: usize) -> Self {
        self.offset = offset;
        self
    }

    /// 设置最大返回数量
    #[inline]
    pub const fn with_count(mut self, count: usize) -> Self {
        self.count = Some(count);
        self
    }

    /// 设置是否逆序
    #[inline]
    pub const fn with_reversed(mut self, reversed: bool) -> Self {
        self.reversed = reversed;
        self
    }

    /// 检查范围区间是否为空(如 min > max,或 min == max 且存在开区间)
    #[inline]
    pub const fn is_empty_range(&self) -> bool {
        if self.min > self.max {
            return true;
        }
        if self.min == self.max && (self.minex || self.maxex) {
            return true;
        }
        false
    }
}

/// 解析单侧边界值(支持 '(' 开区间、'[' 闭区间及无前缀数字)
#[inline]
fn parse_bound(s: &str, is_min: bool) -> Result<(u64, bool)> {
    let (num_str, ex) = if let Some(stripped) = s.strip_prefix('(') {
        (stripped, true)
    } else if let Some(stripped) = s.strip_prefix('[') {
        (stripped, false)
    } else {
        (s, false)
    };
    let val = num_str.parse::<u64>().map_err(|_| {
        let label = if is_min { "min" } else { "max" };
        Error::invalid_data(format!("ERR the {label} isn't integer"))
    })?;
    Ok((val, ex))
}

/// 解析 64 位无符号整型范围规则(对标 Apache Kvrocks Sortedint::ParseRangeSpec)
/// 支持 -inf, +inf, (val, [val, val
pub fn parse_range_spec(min_str: &str, max_str: &str) -> Result<SortedintRangeSpec> {
    let min_str = min_str.trim();
    let max_str = max_str.trim();

    if min_str == "+inf" || max_str == "-inf" {
        return Err(Error::invalid_data("ERR min > max"));
    }

    let (min, minex) = if min_str == "-inf" {
        (u64::MIN, false)
    } else {
        parse_bound(min_str, true)?
    };

    let (max, maxex) = if max_str == "+inf" {
        (u64::MAX, false)
    } else {
        parse_bound(max_str, false)?
    };

    Ok(SortedintRangeSpec {
        min,
        max,
        minex,
        maxex,
        offset: 0,
        count: None,
        reversed: false,
    })
}

/// 快速解码 16 字节十六进制为 64 位无符号整数(编译期 LUT 表驱动,零堆分配、零分支预测失败)
#[inline(always)]
pub const fn decode_hex_u64(hex: &[u8]) -> Option<u64> {
    if hex.len() != HEX_LEN {
        return None;
    }
    let mut val = 0u64;
    let mut i = 0;
    while i < HEX_LEN {
        let d = HEX_DECODE_LUT[hex[i] as usize];
        if d < 0 {
            return None;
        }
        val = (val << 4) | (d as u64);
        i += 1;
    }
    Some(val)
}

/// 64 位无符号整数编码为 16 字符大端序十六进制字节数组(编译期常量函数,零堆分配)
#[inline(always)]
pub const fn encode_hex_u64(val: u64) -> [u8; HEX_LEN] {
    let mut buf = [0u8; HEX_LEN];
    let mut i = 0;
    while i < HEX_LEN {
        let shift = (15 - i) * 4;
        buf[i] = HEX_CHARS[((val >> shift) & 0xF) as usize];
        i += 1;
    }
    buf
}

/// 64 位无符号整数编码为 8 字节大端序原生二进制数组
#[inline(always)]
pub const fn encode_be_u64(val: u64) -> [u8; 8] {
    val.to_be_bytes()
}

/// 8 字节大端序原生二进制解码为 64 位无符号整数
#[inline(always)]
pub const fn decode_be_u64(bytes: &[u8]) -> Option<u64> {
    if bytes.len() != 8 {
        return None;
    }
    let mut buf = [0u8; 8];
    let mut i = 0;
    while i < 8 {
        buf[i] = bytes[i];
        i += 1;
    }
    Some(u64::from_be_bytes(buf))
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_parse_range_spec_cases() {
        let spec1 = parse_range_spec("-inf", "+inf").unwrap();
        assert_eq!(spec1.min, u64::MIN);
        assert_eq!(spec1.max, u64::MAX);
        assert!(!spec1.minex);
        assert!(!spec1.maxex);
        assert!(!spec1.is_empty_range());

        let spec2 = parse_range_spec("(10", "[200").unwrap();
        assert_eq!(spec2.min, 10);
        assert_eq!(spec2.max, 200);
        assert!(spec2.minex);
        assert!(!spec2.maxex);
        assert!(!spec2.is_empty_range());

        let spec3 = parse_range_spec("20", "(300").unwrap();
        assert_eq!(spec3.min, 20);
        assert_eq!(spec3.max, 300);
        assert!(!spec3.minex);
        assert!(spec3.maxex);
        assert!(!spec3.is_empty_range());

        let empty_spec1 = parse_range_spec("300", "200").unwrap();
        assert!(empty_spec1.is_empty_range());

        let empty_spec2 = parse_range_spec("(200", "200").unwrap();
        assert!(empty_spec2.is_empty_range());

        let empty_spec3 = parse_range_spec("200", "(200").unwrap();
        assert!(empty_spec3.is_empty_range());

        assert!(parse_range_spec("+inf", "100").is_err());
        assert!(parse_range_spec("100", "-inf").is_err());
        assert!(parse_range_spec("abc", "100").is_err());
        assert!(parse_range_spec("100", "xyz").is_err());
    }

    #[test]
    fn test_builder_methods() {
        let spec = SortedintRangeSpec::all()
            .with_offset(5)
            .with_count(10)
            .with_reversed(true);
        assert_eq!(spec.offset, 5);
        assert_eq!(spec.count, Some(10));
        assert!(spec.reversed);
        assert_eq!(spec.min, u64::MIN);
        assert_eq!(spec.max, u64::MAX);
    }

    #[test]
    fn test_hex_u64_codec() {
        let test_cases = [0u64, 1, 15, 16, 255, 1000, 1234567890123456789, u64::MAX];
        for &val in &test_cases {
            let encoded = encode_hex_u64(val);
            let decoded = decode_hex_u64(&encoded).expect("Decode should succeed");
            assert_eq!(val, decoded);

            let expected_hex = format!("{val:016x}");
            assert_eq!(encoded, expected_hex.as_bytes());
        }

        assert_eq!(decode_hex_u64(b"invalid_length"), None);
        assert_eq!(decode_hex_u64(b"000000000000000g"), None);
        assert_eq!(decode_hex_u64(b"000000000000000A"), Some(10));
        assert_eq!(decode_hex_u64(b"000000000000000F"), Some(15));
    }

    #[test]
    fn test_be_u64_codec() {
        let test_cases = [0u64, 1, 42, 1024, 0x123456789ABCDEF0, u64::MAX];
        for &val in &test_cases {
            let encoded = encode_be_u64(val);
            assert_eq!(encoded, val.to_be_bytes());
            let decoded = decode_be_u64(&encoded).expect("Decode BE u64 should succeed");
            assert_eq!(val, decoded);
        }
        assert_eq!(decode_be_u64(b"short"), None);
    }
}