use crate::dict::{DictKind, Dicts};
use crate::error::TopoError;
use crate::ids::{EdgeId, NodeId, Scope};
use crate::props::PropValue;
use crate::scopes::ScopeRegistry;
use crate::state::{EdgeRecord, NodeRecord};
use redb::{ReadableTable, Table};
use serde::{Deserialize, Serialize};
use std::collections::BTreeMap;
#[derive(Debug, Serialize, Deserialize)]
pub(crate) struct NodeRecordDisk {
pub id: NodeId,
pub scope: Scope,
pub label: u32,
pub props: BTreeMap<u32, PropValue>,
}
#[derive(Debug, Serialize, Deserialize)]
pub(crate) struct EdgeRecordDisk {
pub id: EdgeId,
pub scope: Scope,
pub ty: u32,
pub from: NodeId,
pub to: NodeId,
pub props: BTreeMap<u32, PropValue>,
pub valid_from: i64,
pub valid_to: Option<i64>,
}
pub(crate) fn node_to_disk(
r: &NodeRecord,
t: &mut Table<'_, &'static [u8], &'static str>,
d: &mut Dicts,
) -> Result<NodeRecordDisk, TopoError> {
let mut p = BTreeMap::new();
for (k, v) in &r.props {
p.insert(d.intern(t, DictKind::PropKey, k)?, v.clone());
}
Ok(NodeRecordDisk {
id: r.id,
scope: r.scope,
label: d.intern(t, DictKind::Label, r.label.as_str())?,
props: p,
})
}
pub(crate) fn edge_to_disk(
r: &EdgeRecord,
t: &mut Table<'_, &'static [u8], &'static str>,
d: &mut Dicts,
) -> Result<EdgeRecordDisk, TopoError> {
let mut p = BTreeMap::new();
for (k, v) in &r.props {
p.insert(d.intern(t, DictKind::PropKey, k)?, v.clone());
}
Ok(EdgeRecordDisk {
id: r.id,
scope: r.scope,
ty: d.intern(t, DictKind::EdgeType, r.ty.as_str())?,
from: r.from,
to: r.to,
props: p,
valid_from: r.valid_from,
valid_to: r.valid_to,
})
}
#[derive(Debug, Serialize, Deserialize)]
pub(crate) struct NodeRecordDiskV3 {
pub id: NodeId,
pub scope: u32,
pub label: u32,
pub props: BTreeMap<u32, PropValue>,
}
#[derive(Debug, Serialize, Deserialize)]
pub(crate) struct EdgeRecordDiskV3 {
pub id: EdgeId,
pub scope: u32,
pub ty: u32,
pub from: u64,
pub to: u64,
pub props: BTreeMap<u32, PropValue>,
pub valid_from: i64,
pub valid_to: Option<i64>,
}
pub(crate) fn node_to_disk_v3(
r: &NodeRecord,
t: &mut Table<'_, &'static [u8], &'static str>,
d: &mut Dicts,
scopes_table: &mut Table<'_, &'static [u8], &'static [u8]>,
scopes: &mut ScopeRegistry,
) -> Result<NodeRecordDiskV3, TopoError> {
let mut p = BTreeMap::new();
for (k, v) in &r.props {
p.insert(d.intern(t, DictKind::PropKey, k)?, v.clone());
}
Ok(NodeRecordDiskV3 {
id: r.id,
scope: scopes.intern(scopes_table, r.scope)?,
label: d.intern(t, DictKind::Label, r.label.as_str())?,
props: p,
})
}
pub(crate) fn node_from_disk_v3(
r: NodeRecordDiskV3,
d: &Dicts,
scopes: &ScopeRegistry,
) -> Result<NodeRecord, TopoError> {
let mut p = crate::props::Props::new();
for (k, v) in r.props {
p.insert(d.resolve(DictKind::PropKey, k)?.to_string(), v);
}
Ok(NodeRecord {
id: r.id,
scope: scopes.resolve(r.scope)?,
label: d.resolve(DictKind::Label, r.label)?,
props: p,
embedding: None,
})
}
#[allow(clippy::too_many_arguments)]
pub(crate) fn edge_to_disk_v3(
r: &EdgeRecord,
t: &mut Table<'_, &'static [u8], &'static str>,
d: &mut Dicts,
scopes_table: &mut Table<'_, &'static [u8], &'static [u8]>,
scopes: &mut ScopeRegistry,
node_slots: &impl ReadableTable<&'static [u8], &'static [u8]>,
) -> Result<EdgeRecordDiskV3, TopoError> {
let mut p = BTreeMap::new();
for (k, v) in &r.props {
p.insert(d.intern(t, DictKind::PropKey, k)?, v.clone());
}
let from = crate::slots::node_slot(node_slots, r.from)?
.ok_or_else(|| TopoError::Encoding("edge_to_disk_v3: missing from slot".into()))?;
let to = crate::slots::node_slot(node_slots, r.to)?
.ok_or_else(|| TopoError::Encoding("edge_to_disk_v3: missing to slot".into()))?;
Ok(EdgeRecordDiskV3 {
id: r.id,
scope: scopes.intern(scopes_table, r.scope)?,
ty: d.intern(t, DictKind::EdgeType, r.ty.as_str())?,
from,
to,
props: p,
valid_from: r.valid_from,
valid_to: r.valid_to,
})
}
pub(crate) fn edge_from_disk_v3(
r: EdgeRecordDiskV3,
d: &Dicts,
scopes: &ScopeRegistry,
node_ids: &impl ReadableTable<&'static [u8], &'static [u8]>,
) -> Result<EdgeRecord, TopoError> {
let mut p = crate::props::Props::new();
for (k, v) in r.props {
p.insert(d.resolve(DictKind::PropKey, k)?.to_string(), v);
}
let from = crate::slots::node_ulid(node_ids, r.from)?
.ok_or_else(|| TopoError::Encoding("edge_from_disk_v3: missing from ulid".into()))?;
let to = crate::slots::node_ulid(node_ids, r.to)?
.ok_or_else(|| TopoError::Encoding("edge_from_disk_v3: missing to ulid".into()))?;
Ok(EdgeRecord {
id: r.id,
scope: scopes.resolve(r.scope)?,
ty: d.resolve(DictKind::EdgeType, r.ty)?,
from,
to,
props: p,
valid_from: r.valid_from,
valid_to: r.valid_to,
})
}