oxgraph_postgres/artifact/
metadata.rs1use oxgraph_snapshot::{PlanError, Snapshot, SnapshotBuilder, SnapshotError};
4use zerocopy::{
5 FromBytes, Immutable, IntoBytes, KnownLayout,
6 byteorder::{LE, U32, U64},
7};
8
9pub const SNAPSHOT_KIND_PG_CATALOG: u32 = 0x0200;
11
12pub const SNAPSHOT_KIND_PG_METADATA: u32 = 0x0203;
14
15#[derive(Clone, Copy, Debug, PartialEq, Eq, FromBytes, Immutable, IntoBytes, KnownLayout)]
17#[repr(C)]
18pub struct PostgresMetadata {
19 pub version: U32<LE>,
21 pub flags: U32<LE>,
23 pub built_at_unix: U64<LE>,
25 pub node_count: U32<LE>,
27 pub edge_count: U32<LE>,
29}
30
31impl PostgresMetadata {
32 pub const VERSION: u32 = 1;
34
35 pub const FLAG_READ_ONLY: u32 = 1;
37
38 pub const FLAG_HAS_REVERSE_INDEX: u32 = 2;
40
41 #[must_use]
43 pub const fn new(
44 node_count: u32,
45 edge_count: u32,
46 built_at_unix: u64,
47 read_only: bool,
48 ) -> Self {
49 let mut flags = 0_u32;
50 if read_only {
51 flags |= Self::FLAG_READ_ONLY;
52 }
53 Self {
54 version: U32::new(Self::VERSION),
55 flags: U32::new(flags),
56 built_at_unix: U64::new(built_at_unix),
57 node_count: U32::new(node_count),
58 edge_count: U32::new(edge_count),
59 }
60 }
61
62 #[must_use]
64 pub const fn with_reverse_index(mut self) -> Self {
65 self.flags = U32::new(self.flags.get() | Self::FLAG_HAS_REVERSE_INDEX);
66 self
67 }
68
69 #[must_use]
71 pub const fn is_read_only(self) -> bool {
72 self.flags.get() & Self::FLAG_READ_ONLY != 0
73 }
74
75 #[must_use]
77 pub const fn has_reverse_index(self) -> bool {
78 self.flags.get() & Self::FLAG_HAS_REVERSE_INDEX != 0
79 }
80}
81
82#[derive(Debug, Clone, PartialEq, Eq)]
84pub enum PostgresSectionError {
85 Snapshot(SnapshotError),
87 MissingSection,
89 Malformed(alloc::string::String),
91}
92
93pub(super) fn read_postgres_metadata(
103 snapshot: &Snapshot<'_>,
104) -> Result<PostgresMetadata, PostgresSectionError> {
105 let section = snapshot
106 .section(SNAPSHOT_KIND_PG_METADATA)
107 .ok_or(PostgresSectionError::MissingSection)?;
108 PostgresMetadata::ref_from_bytes(section.bytes())
109 .map_err(|error| {
110 PostgresSectionError::Malformed(alloc::format!("postgres metadata layout: {error}"))
111 })
112 .copied()
113}
114
115pub(super) fn write_postgres_metadata_section(
125 builder: &mut SnapshotBuilder,
126 metadata: &PostgresMetadata,
127) -> Result<(), PlanError> {
128 builder.add_section_typed(
129 SNAPSHOT_KIND_PG_METADATA,
130 PostgresMetadata::VERSION,
131 core::slice::from_ref(metadata),
132 )?;
133 Ok(())
134}