wedb_embed 0.1.0

Embedded Kvrocks-compatible storage engine for WeDb
Documentation
/// 哈希字段状态码与返回值常量(对标 Redis 7.4 / Apache Kvrocks)
pub const HASH_FIELD_NOT_FOUND: i64 = -2;
pub const HASH_FIELD_PERSISTENT: i64 = -1;
pub const HASH_EXPIRE_COND_FAILED: i64 = 0;
pub const HASH_EXPIRE_SET_OK: i64 = 1;
pub const HASH_EXPIRE_DELETED: i64 = 2;

/// 错误提示常量(对标 Redis 7.4 / Apache Kvrocks)
pub const ERR_HASH_FIELD_EXPIRATION_LEGACY_ENCODING: &str =
    "ERR hash field expiration is not supported by legacy hash encoding";
pub const ERR_HASH_VALUE_NOT_INTEGER: &str = "ERR hash value is not an integer";
pub const ERR_HASH_VALUE_NOT_FLOAT: &str = "ERR hash value is not a valid float";
pub const ERR_INCREMENT_OVERFLOW: &str = "ERR increment or decrement would overflow";
pub const ERR_INCREMENT_NAN_OR_INFINITY: &str = "ERR increment would produce NaN or Infinity";

/// HEXPIRE / HPEXPIRE 条件选项(对标 Apache Kvrocks HashFieldExpireCondition)
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum HExpire {
    #[default]
    None,
    Nx,
    Xx,
    Gt,
    Lt,
}

pub type HashFieldExpireCondition = HExpire;

/// 字段设置条件(对标 Apache Kvrocks HashFieldSetCondition)
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum HashFieldSetCondition {
    #[default]
    None,
    Fnx,
    Fxx,
}

/// TTL 动作类型(对标 Apache Kvrocks HashSetExOptions::TTLAction / HashGetExOptions::TTLAction)
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum TTLAction {
    #[default]
    Discard,
    Keep,
    Set,
    Persist,
}

/// HSETEX 选项(对标 Apache Kvrocks HashSetExOptions)
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub struct HashSetExOptions {
    pub condition: HashFieldSetCondition,
    pub ttl_action: TTLAction,
    pub expire_at_ms: u64,
}

impl HashSetExOptions {
    #[inline]
    pub const fn new(
        condition: HashFieldSetCondition,
        ttl_action: TTLAction,
        expire_at_ms: u64,
    ) -> Self {
        Self {
            condition,
            ttl_action,
            expire_at_ms,
        }
    }

    /// 从便捷标志数组构造 HashSetExOptions
    pub fn from_flags(flags: &[HSetEx], now_ms: u64) -> Self {
        let mut opts = Self::default();
        for flag in flags {
            match *flag {
                HSetEx::Ex(sec) => {
                    opts.ttl_action = TTLAction::Set;
                    opts.expire_at_ms = now_ms.saturating_add(sec.saturating_mul(1000));
                }
                HSetEx::Px(ms) => {
                    opts.ttl_action = TTLAction::Set;
                    opts.expire_at_ms = now_ms.saturating_add(ms);
                }
                HSetEx::ExAt(sec) => {
                    opts.ttl_action = TTLAction::Set;
                    opts.expire_at_ms = sec.saturating_mul(1000);
                }
                HSetEx::PxAt(ms) => {
                    opts.ttl_action = TTLAction::Set;
                    opts.expire_at_ms = ms;
                }
                HSetEx::KeepTtl => {
                    opts.ttl_action = TTLAction::Keep;
                }
                HSetEx::Fnx => {
                    opts.condition = HashFieldSetCondition::Fnx;
                }
                HSetEx::Fxx => {
                    opts.condition = HashFieldSetCondition::Fxx;
                }
            }
        }
        opts
    }
}

/// HGETEX 选项(对标 Apache Kvrocks HashGetExOptions)
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub struct HashGetExOptions {
    pub ttl_action: TTLAction,
    pub expire_at_ms: u64,
}

impl HashGetExOptions {
    #[inline]
    pub const fn new(ttl_action: TTLAction, expire_at_ms: u64) -> Self {
        Self {
            ttl_action,
            expire_at_ms,
        }
    }

    #[inline]
    pub const fn persist() -> Self {
        Self {
            ttl_action: TTLAction::Persist,
            expire_at_ms: 0,
        }
    }

    /// 从单个便捷标志构造 HashGetExOptions
    pub fn from_flag(flag: HGetEx, now_ms: u64) -> Self {
        match flag {
            HGetEx::Ex(sec) => Self::new(
                TTLAction::Set,
                now_ms.saturating_add(sec.saturating_mul(1000)),
            ),
            HGetEx::Px(ms) => Self::new(TTLAction::Set, now_ms.saturating_add(ms)),
            HGetEx::ExAt(sec) => Self::new(TTLAction::Set, sec.saturating_mul(1000)),
            HGetEx::PxAt(ms) => Self::new(TTLAction::Set, ms),
            HGetEx::Persist => Self::persist(),
        }
    }
}

/// HSETEX 便捷选项枚举
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum HSetEx {
    Ex(u64),
    Px(u64),
    ExAt(u64),
    PxAt(u64),
    KeepTtl,
    Fnx,
    Fxx,
}

/// HGETEX 便捷选项枚举
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum HGetEx {
    Ex(u64),
    Px(u64),
    ExAt(u64),
    PxAt(u64),
    Persist,
}

/// 哈希长度计算模式(对标 Apache Kvrocks HashLengthMode)
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum HashLengthMode {
    #[default]
    Accurate = 0,
    Approximate = 1,
}

/// 哈希获取类型(对标 Apache Kvrocks HashFetchType)
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum HashFetchType {
    #[default]
    All = 0,
    OnlyKey = 1,
    OnlyValue = 2,
}

/// 字典序范围规格(对标 Apache Kvrocks RangeLexSpec)
#[derive(Debug, Clone, PartialEq, Eq, Default)]
pub struct RangeLexSpec {
    pub min: Vec<u8>,
    pub max: Vec<u8>,
    pub minex: bool,
    pub maxex: bool,
    pub max_infinite: bool,
    pub min_infinite: bool,
    pub offset: usize,
    pub count: Option<usize>,
    pub reversed: bool,
}

/// 字段与值结构对(对标 Apache Kvrocks FieldValue)
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct FieldValue<F = Vec<u8>, V = Vec<u8>> {
    pub field: F,
    pub value: V,
}

impl<F, V> FieldValue<F, V> {
    #[inline]
    pub const fn new(field: F, value: V) -> Self {
        Self { field, value }
    }
}