use oxgraph_snapshot::{PlanError, Snapshot, SnapshotBuilder, SnapshotError};
use zerocopy::{
FromBytes, Immutable, IntoBytes, KnownLayout,
byteorder::{LE, U32, U64},
};
pub const SNAPSHOT_KIND_PG_CATALOG: u32 = 0x0200;
pub const SNAPSHOT_KIND_PG_INBOUND_OFFSETS_U32: u32 = 0x0201;
pub const SNAPSHOT_KIND_PG_INBOUND_TARGETS_U32: u32 = 0x0202;
pub const SNAPSHOT_KIND_PG_METADATA: u32 = 0x0203;
#[derive(Clone, Copy, Debug, PartialEq, Eq, FromBytes, Immutable, IntoBytes, KnownLayout)]
#[repr(C)]
pub struct PostgresMetadata {
pub version: U32<LE>,
pub flags: U32<LE>,
pub built_at_unix: U64<LE>,
pub node_count: U32<LE>,
pub edge_count: U32<LE>,
}
impl PostgresMetadata {
pub const VERSION: u32 = 1;
pub const FLAG_READ_ONLY: u32 = 1;
pub const FLAG_HAS_REVERSE_INDEX: u32 = 2;
#[must_use]
pub const fn new(
node_count: u32,
edge_count: u32,
built_at_unix: u64,
read_only: bool,
) -> Self {
let mut flags = 0_u32;
if read_only {
flags |= Self::FLAG_READ_ONLY;
}
Self {
version: U32::new(Self::VERSION),
flags: U32::new(flags),
built_at_unix: U64::new(built_at_unix),
node_count: U32::new(node_count),
edge_count: U32::new(edge_count),
}
}
#[must_use]
pub const fn with_reverse_index(mut self) -> Self {
self.flags = U32::new(self.flags.get() | Self::FLAG_HAS_REVERSE_INDEX);
self
}
#[must_use]
pub const fn is_read_only(self) -> bool {
self.flags.get() & Self::FLAG_READ_ONLY != 0
}
#[must_use]
pub const fn has_reverse_index(self) -> bool {
self.flags.get() & Self::FLAG_HAS_REVERSE_INDEX != 0
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum PostgresSectionError {
Snapshot(SnapshotError),
MissingSection,
Malformed(alloc::string::String),
}
pub(super) fn read_postgres_metadata(
snapshot: &Snapshot<'_>,
) -> Result<PostgresMetadata, PostgresSectionError> {
let section = snapshot
.section(SNAPSHOT_KIND_PG_METADATA)
.ok_or(PostgresSectionError::MissingSection)?;
PostgresMetadata::ref_from_bytes(section.bytes())
.map_err(|error| {
PostgresSectionError::Malformed(alloc::format!("postgres metadata layout: {error}"))
})
.copied()
}
pub(super) fn write_postgres_metadata_section(
builder: &mut SnapshotBuilder,
metadata: &PostgresMetadata,
) -> Result<(), PlanError> {
builder.add_section_typed(
SNAPSHOT_KIND_PG_METADATA,
PostgresMetadata::VERSION,
core::slice::from_ref(metadata),
)?;
Ok(())
}