use crate::store::*;
use self::constants::*;
pub(super) mod constants {
pub(in crate::store::kv) const META_TO_VALUE: u8 = 0;
pub(in crate::store::kv) const TERM_TO_IIDS: u8 = 1;
pub(in crate::store::kv) const OID_TO_IID: u8 = 2;
pub(in crate::store::kv) const IID_TO_OID: u8 = 3;
pub(in crate::store::kv) const IID_TO_TERMS: u8 = 4;
}
#[derive(Clone, Copy, PartialEq, Eq)]
#[repr(transparent)]
pub(super) struct KvStoreKey([u8; 9]);
impl KvStoreKey {
pub(super) fn meta_to_value(bucket: &StoreItemPart, meta: &StoreMetaKey) -> KvStoreKey {
Self::make(META_TO_VALUE, bucket, meta.as_u32())
}
pub(super) fn term_to_iids(bucket: &StoreItemPart, term_hash: StoreTermHash) -> KvStoreKey {
Self::make(TERM_TO_IIDS, bucket, term_hash.into())
}
pub(super) fn oid_to_iid(bucket: &StoreItemPart, oid: StoreObjectOid) -> KvStoreKey {
Self::make(OID_TO_IID, bucket, oid.into_compact())
}
pub(super) fn iid_to_oid(bucket: &StoreItemPart, iid: StoreObjectIid) -> KvStoreKey {
Self::make(IID_TO_OID, bucket, iid.into())
}
pub(super) fn iid_to_terms(bucket: &StoreItemPart, iid: StoreObjectIid) -> KvStoreKey {
Self::make(IID_TO_TERMS, bucket, iid.into())
}
fn make(idx: u8, bucket: &StoreItemPart, route: u32) -> KvStoreKey {
let [b0, b1, b2, b3] = bucket.into_compact().to_le_bytes();
let [r0, r1, r2, r3] = route.to_le_bytes();
KvStoreKey::from([
idx, b0, b1, b2, b3, r0, r1, r2, r3, ])
}
pub(super) fn into_prefix(self) -> [u8; 5] {
[self.0[0], self.0[1], self.0[2], self.0[3], self.0[4]]
}
}
impl From<[u8; 9]> for KvStoreKey {
fn from(value: [u8; 9]) -> Self {
Self(value)
}
}
impl AsRef<[u8]> for KvStoreKey {
fn as_ref(&self) -> &[u8] {
&self.0
}
}
impl std::fmt::Display for KvStoreKey {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
let Self(bytes @ [key_idx, b1, b2, b3, b4, b5, b6, b7, b8]) = self;
let key_bucket = u32::from_le_bytes([*b1, *b2, *b3, *b4]);
let key_route = u32::from_le_bytes([*b5, *b6, *b7, *b8]);
write!(f, "'{key_idx}:{key_bucket:x}:{key_route:x}' {bytes:?}")
}
}
impl std::fmt::Debug for KvStoreKey {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Debug::fmt(&self.0, f)
}
}
pub enum StoreMetaKey {
IIDIncr,
ObjectCount,
}
impl StoreMetaKey {
pub const fn as_u32(&self) -> u32 {
match self {
StoreMetaKey::IIDIncr => 0,
StoreMetaKey::ObjectCount => 1,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn it_keys_meta_to_value() {
assert_eq!(
KvStoreKey::meta_to_value(&"bucket:1".into(), &StoreMetaKey::IIDIncr).0,
[0, 108, 244, 29, 93, 0, 0, 0, 0]
);
}
#[test]
fn it_keys_term_to_iids() {
assert_eq!(
KvStoreKey::term_to_iids(&"bucket:2".into(), 772137347.into()).0,
[1, 50, 220, 166, 65, 131, 225, 5, 46]
);
assert_eq!(
KvStoreKey::term_to_iids(&"bucket:2".into(), 3582484684.into()).0,
[1, 50, 220, 166, 65, 204, 96, 136, 213]
);
}
#[test]
fn it_keys_oid_to_iid() {
assert_eq!(
KvStoreKey::oid_to_iid(&"bucket:3".into(), "conversation:6501e83a".into()).0,
[2, 171, 194, 213, 57, 31, 156, 118, 213]
);
}
#[test]
fn it_keys_iid_to_oid() {
assert_eq!(
KvStoreKey::iid_to_oid(&"bucket:4".into(), 10292198.into()).0,
[3, 105, 12, 54, 147, 230, 11, 157, 0]
);
}
#[test]
fn it_keys_iid_to_terms() {
assert_eq!(
KvStoreKey::iid_to_terms(&"bucket:5".into(), 1.into()).0,
[4, 137, 142, 73, 67, 1, 0, 0, 0]
);
assert_eq!(
KvStoreKey::iid_to_terms(&"bucket:5".into(), 20.into()).0,
[4, 137, 142, 73, 67, 20, 0, 0, 0]
);
}
#[test]
fn it_hashes_compact() {
assert_eq!(StoreObjectOid::from("key:1").into_compact(), 3370353088);
assert_eq!(StoreObjectOid::from("key:2").into_compact(), 1042559698);
}
#[test]
fn it_formats_key() {
assert_eq!(
&format!(
"{}",
KvStoreKey::term_to_iids(&"bucket:6".into(), 72137347.into())
),
"'1:71198b49:44cba83' [1, 73, 139, 25, 113, 131, 186, 76, 4]"
);
assert_eq!(
&format!(
"{}",
KvStoreKey::meta_to_value(&"bucket:6".into(), &StoreMetaKey::IIDIncr)
),
"'0:71198b49:0' [0, 73, 139, 25, 113, 0, 0, 0, 0]"
);
}
}
#[cfg(all(feature = "benchmark", test))]
mod benches {
extern crate test;
use super::*;
use test::Bencher;
#[bench]
fn bench_hash_compact_short(b: &mut Bencher) {
b.iter(|| StoreKeyerHasher::to_compact("key:bench:1"));
}
#[bench]
fn bench_hash_compact_long(b: &mut Bencher) {
b.iter(|| {
StoreKeyerHasher::to_compact(
"key:bench:2:long:long:long:long:long:long:long:long:long:long:long:long:long:long",
)
});
}
#[bench]
fn bench_key_meta_to_value(b: &mut Bencher) {
b.iter(|| KvStoreKey::meta_to_value("bucket:bench:1", &StoreMetaKey::IIDIncr));
}
#[bench]
fn bench_key_term_to_iids(b: &mut Bencher) {
b.iter(|| KvStoreKey::term_to_iids("bucket:bench:2", 772137347));
}
#[bench]
fn bench_key_oid_to_iid(b: &mut Bencher) {
let key = "conversation:6501e83a".to_string();
b.iter(|| KvStoreKey::oid_to_iid("bucket:bench:3", &key));
}
#[bench]
fn bench_key_iid_to_oid(b: &mut Bencher) {
b.iter(|| KvStoreKey::iid_to_oid("bucket:bench:4", 10292198));
}
#[bench]
fn bench_key_iid_to_terms(b: &mut Bencher) {
b.iter(|| KvStoreKey::iid_to_terms("bucket:bench:5", 1));
}
}