oxgraph_postgres/artifact/
sections.rs1use oxgraph_csr::CsrSnapshotIndex;
4use oxgraph_layout_util::crc32c_append;
5use oxgraph_snapshot::{Snapshot, SnapshotWriter};
6
7use super::metadata::{
8 PostgresMetadata, SNAPSHOT_KIND_PG_INBOUND_OFFSETS_U32, SNAPSHOT_KIND_PG_INBOUND_TARGETS_U32,
9 write_postgres_metadata_section,
10};
11use crate::error::{BuildError, PostgresGraphError};
12
13pub fn attach_postgres_sections(
29 forward_topology_bytes: &[u8],
30 inbound_topology_bytes: Option<&[u8]>,
31 metadata: &PostgresMetadata,
32) -> Result<Vec<u8>, PostgresGraphError> {
33 let forward = Snapshot::open(forward_topology_bytes)?;
34 let inbound = inbound_topology_bytes.map(Snapshot::open).transpose()?;
35 let copied = forward
36 .sections()
37 .filter(|section| !is_postgres_owned_kind(section.kind()))
38 .count();
39 let inbound_count = if inbound.is_some() { 2 } else { 0 };
40 let mut writer = SnapshotWriter::new(copied + inbound_count + 1, crc32c_append)?;
41 for section in forward.sections() {
42 if is_postgres_owned_kind(section.kind()) {
43 continue;
44 }
45 writer.section_bytes(
46 section.kind(),
47 section.version(),
48 alignment_log2_from_section(§ion),
49 section.bytes(),
50 )?;
51 }
52 if let Some(inbound_snapshot) = inbound.as_ref() {
53 copy_csr_section(
54 inbound_snapshot,
55 u32::OFFSETS_KIND,
56 SNAPSHOT_KIND_PG_INBOUND_OFFSETS_U32,
57 &mut writer,
58 )?;
59 copy_csr_section(
60 inbound_snapshot,
61 u32::TARGETS_KIND,
62 SNAPSHOT_KIND_PG_INBOUND_TARGETS_U32,
63 &mut writer,
64 )?;
65 }
66 write_postgres_metadata_section(&mut writer, metadata)?;
67 writer.finish().map_err(PostgresGraphError::from)
68}
69
70pub fn attach_metadata(
83 base_bytes: &[u8],
84 metadata: &PostgresMetadata,
85) -> Result<Vec<u8>, PostgresGraphError> {
86 attach_postgres_sections(base_bytes, None, metadata)
87}
88
89fn copy_csr_section(
91 snapshot: &Snapshot<'_>,
92 source_kind: u32,
93 dest_kind: u32,
94 writer: &mut SnapshotWriter,
95) -> Result<(), PostgresGraphError> {
96 let section = snapshot
97 .section(source_kind)
98 .ok_or(PostgresGraphError::Build(BuildError::MissingCsrSection {
99 kind: source_kind,
100 }))?;
101 writer.section_bytes(
102 dest_kind,
103 section.version(),
104 alignment_log2_from_section(§ion),
105 section.bytes(),
106 )?;
107 Ok(())
108}
109
110fn is_postgres_owned_kind(kind: u32) -> bool {
112 (0x0200..0x0300).contains(&kind)
113}
114
115fn alignment_log2_from_section(section: &oxgraph_snapshot::Section<'_>) -> u8 {
117 let alignment = section.declared_alignment();
118 if alignment <= 1 {
119 0
120 } else {
121 u8::try_from(alignment.trailing_zeros()).unwrap_or(u8::MAX)
122 }
123}