use plugmem_arena::{BlobId, ListHandle, Slot, TermId, key};
use crate::id::{EntityId, FactId, NONE_U32};
pub const VALID_TO_OPEN: u64 = u64::MAX;
pub mod fact_flags {
pub const TOMBSTONE: u16 = 1;
pub const CLOSED: u16 = 1 << 1;
pub const HAS_VECTOR: u16 = 1 << 2;
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct FactRecord {
pub id: FactId,
pub entity: EntityId,
pub flags: u16,
pub kind: u16,
pub text: BlobId,
pub vector: u32,
pub revises: FactId,
pub recorded_at: u64,
pub valid_from: u64,
pub valid_to: u64,
}
impl FactRecord {
pub fn is_tombstone(&self) -> bool {
self.flags & fact_flags::TOMBSTONE != 0
}
pub fn is_closed(&self) -> bool {
self.flags & fact_flags::CLOSED != 0
}
pub fn has_vector(&self) -> bool {
self.flags & fact_flags::HAS_VECTOR != 0
}
pub fn is_live_at(&self, t: u64) -> bool {
!self.is_tombstone() && self.recorded_at <= t && self.valid_from <= t && t < self.valid_to
}
}
impl Slot for FactRecord {
const SIZE: usize = 48;
const KEY_LEN: usize = 4;
fn write(&self, out: &mut [u8]) {
key::write_u32(out, self.id.0);
key::write_u32(&mut out[4..], self.entity.0);
out[8..10].copy_from_slice(&self.flags.to_be_bytes());
out[10..12].copy_from_slice(&self.kind.to_be_bytes());
key::write_u32(&mut out[12..], self.text.0);
key::write_u32(&mut out[16..], self.vector);
key::write_u32(&mut out[20..], self.revises.0);
key::write_u64(&mut out[24..], self.recorded_at);
key::write_u64(&mut out[32..], self.valid_from);
key::write_u64(&mut out[40..], self.valid_to);
}
fn read(bytes: &[u8]) -> Self {
Self {
id: FactId(key::read_u32(bytes)),
entity: EntityId(key::read_u32(&bytes[4..])),
flags: u16::from_be_bytes(bytes[8..10].try_into().unwrap()),
kind: u16::from_be_bytes(bytes[10..12].try_into().unwrap()),
text: BlobId(key::read_u32(&bytes[12..])),
vector: key::read_u32(&bytes[16..]),
revises: FactId(key::read_u32(&bytes[20..])),
recorded_at: key::read_u64(&bytes[24..]),
valid_from: key::read_u64(&bytes[32..]),
valid_to: key::read_u64(&bytes[40..]),
}
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct FactAux {
pub id: FactId,
pub tags: ListHandle,
pub meta: BlobId,
}
impl Slot for FactAux {
const SIZE: usize = 20;
const KEY_LEN: usize = 4;
fn write(&self, out: &mut [u8]) {
key::write_u32(out, self.id.0);
out[4..16].copy_from_slice(&self.tags.to_bytes());
key::write_u32(&mut out[16..], self.meta.0);
}
fn read(bytes: &[u8]) -> Self {
Self {
id: FactId(key::read_u32(bytes)),
tags: ListHandle::from_bytes(bytes[4..16].try_into().unwrap()),
meta: BlobId(key::read_u32(&bytes[16..])),
}
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct EntityRecord {
pub id: EntityId,
pub name: BlobId,
pub name_term: TermId,
pub created_at: u64,
pub flags: u32,
}
impl Slot for EntityRecord {
const SIZE: usize = 24;
const KEY_LEN: usize = 4;
fn write(&self, out: &mut [u8]) {
key::write_u32(out, self.id.0);
key::write_u32(&mut out[4..], self.name.0);
key::write_u32(&mut out[8..], self.name_term.0);
key::write_u64(&mut out[12..], self.created_at);
key::write_u32(&mut out[20..], self.flags);
}
fn read(bytes: &[u8]) -> Self {
Self {
id: EntityId(key::read_u32(bytes)),
name: BlobId(key::read_u32(&bytes[4..])),
name_term: TermId(key::read_u32(&bytes[8..])),
created_at: key::read_u64(&bytes[12..]),
flags: key::read_u32(&bytes[20..]),
}
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct EntityByName {
pub name_term: TermId,
pub id: EntityId,
}
impl Slot for EntityByName {
const SIZE: usize = 8;
const KEY_LEN: usize = 8;
fn write(&self, out: &mut [u8]) {
key::write_u32(out, self.name_term.0);
key::write_u32(&mut out[4..], self.id.0);
}
fn read(bytes: &[u8]) -> Self {
Self {
name_term: TermId(key::read_u32(bytes)),
id: EntityId(key::read_u32(&bytes[4..])),
}
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct EdgeSlot {
pub a: EntityId,
pub rel: TermId,
pub b: EntityId,
pub fact: FactId,
}
impl Slot for EdgeSlot {
const SIZE: usize = 16;
const KEY_LEN: usize = 12;
fn write(&self, out: &mut [u8]) {
key::write_u32(out, self.a.0);
key::write_u32(&mut out[4..], self.rel.0);
key::write_u32(&mut out[8..], self.b.0);
key::write_u32(&mut out[12..], self.fact.0);
}
fn read(bytes: &[u8]) -> Self {
Self {
a: EntityId(key::read_u32(bytes)),
rel: TermId(key::read_u32(&bytes[4..])),
b: EntityId(key::read_u32(&bytes[8..])),
fact: FactId(key::read_u32(&bytes[12..])),
}
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct TemporalSlot {
pub recorded_at: u64,
pub fact: FactId,
}
impl Slot for TemporalSlot {
const SIZE: usize = 12;
const KEY_LEN: usize = 12;
fn write(&self, out: &mut [u8]) {
key::write_pair(out, self.recorded_at, self.fact.0);
}
fn read(bytes: &[u8]) -> Self {
let (recorded_at, fact) = key::read_pair(bytes);
Self {
recorded_at,
fact: FactId(fact),
}
}
}
const _: () = {
assert!(FactRecord::SIZE == 48 && FactRecord::KEY_LEN == 4);
assert!(FactAux::SIZE == 20 && FactAux::KEY_LEN == 4);
assert!(EntityRecord::SIZE == 24 && EntityRecord::KEY_LEN == 4);
assert!(EntityByName::SIZE == 8 && EntityByName::KEY_LEN == 8);
assert!(EdgeSlot::SIZE == 16 && EdgeSlot::KEY_LEN == 12);
assert!(TemporalSlot::SIZE == 12 && TemporalSlot::KEY_LEN == 12);
assert!(NONE_U32 == u32::MAX);
};