pub(super) fn table_key(tenant_id: u32, collection: &str) -> u64 {
super::hash_helpers::fxhash_multi(&[&tenant_id.to_le_bytes(), b":", collection.as_bytes()])
}
pub(super) fn expiry_key(tenant_id: u32, collection: &str, key: &[u8]) -> Vec<u8> {
let prefix = format!("{tenant_id}:{collection}\0");
let mut composite = prefix.into_bytes();
composite.extend_from_slice(key);
composite
}
pub(super) fn parse_expiry_key(composite: &[u8]) -> Option<(u32, String, Vec<u8>)> {
let null_pos = composite.iter().position(|&b| b == 0)?;
let prefix = std::str::from_utf8(&composite[..null_pos]).ok()?;
let colon_pos = prefix.find(':')?;
let tenant_id: u32 = prefix[..colon_pos].parse().ok()?;
let collection = prefix[colon_pos + 1..].to_string();
let key = composite[null_pos + 1..].to_vec();
Some((tenant_id, collection, key))
}
pub(super) fn extract_all_field_values_from_msgpack(data: &[u8]) -> Vec<(String, Vec<u8>)> {
let Ok(value) = rmp_serde::from_slice::<serde_json::Value>(data) else {
return Vec::new();
};
let Some(obj) = value.as_object() else {
return Vec::new();
};
obj.iter()
.map(|(k, v)| {
let bytes = json_value_to_index_bytes(v);
(k.clone(), bytes)
})
.collect()
}
pub(super) fn extract_field_values_from_msgpack(data: &[u8], field: &str) -> Vec<Vec<u8>> {
let Ok(value) = rmp_serde::from_slice::<serde_json::Value>(data) else {
return Vec::new();
};
let Some(obj) = value.as_object() else {
return Vec::new();
};
match obj.get(field) {
Some(v) => vec![json_value_to_index_bytes(v)],
None => Vec::new(),
}
}
fn json_value_to_index_bytes(v: &serde_json::Value) -> Vec<u8> {
match v {
serde_json::Value::String(s) => s.as_bytes().to_vec(),
serde_json::Value::Number(n) => {
if let Some(i) = n.as_i64() {
let sortable = (i as u64) ^ (1u64 << 63);
sortable.to_be_bytes().to_vec()
} else if let Some(f) = n.as_f64() {
let bits = f.to_bits();
let sortable = if bits >> 63 == 1 {
!bits } else {
bits | (1u64 << 63) };
sortable.to_be_bytes().to_vec()
} else {
Vec::new()
}
}
serde_json::Value::Bool(b) => vec![*b as u8],
serde_json::Value::Null => Vec::new(),
other => other.to_string().into_bytes(),
}
}