pub struct PackWriter { /* private fields */ }Expand description
Writer for the multi-object packed format.
Consumes an (id, payload) stream like ArchiveWriter,
buffering every tile until finalize. At finalize it
reuses the buffered-writer pipeline — resolve BlobOrdering::Auto, sort by
the space-time curve key, per-blob zstd (NO shared dictionary, so the fzstd
TS reader can decode), byte-identical dedup via blake3 — then cuts the
ordered/deduped blob stream into packs of ≤ pack_target_bytes, never
splitting a blob, and writes content-addressed packs/*.sttp +
index/*.sttd + manifest.json.
Implementations§
Source§impl PackWriter
impl PackWriter
Sourcepub fn create<P: AsRef<Path>>(
out_dir: P,
ordering: BlobOrdering,
pack_target_bytes: u64,
) -> Result<Self>
pub fn create<P: AsRef<Path>>( out_dir: P, ordering: BlobOrdering, pack_target_bytes: u64, ) -> Result<Self>
Create a packed-format writer targeting out_dir.
out_dir (and its index/ + packs/ subdirs) are created on
finalize. ordering controls the on-disk blob byte
order (BlobOrdering::Auto resolves per-dataset at finalize);
pack_target_bytes is the soft per-pack size cap — a single blob larger
than the target gets its own pack rather than being split.
Sourcepub fn with_memory_budget(self, bytes: u64) -> Self
pub fn with_memory_budget(self, bytes: u64) -> Self
Cap the UNCOMPRESSED tile-payload bytes buffered in RAM between
add_tile_full and finalize.
Once the budget is reached, further payloads are appended to a temp
spill file inside out_dir (same rename-safe filesystem as the final
objects; removed on success, error and drop alike) while the ~100 B of
per-tile directory metadata stays in RAM. Finalize reads spilled
payloads back record-by-record inside its existing chunked
parallel-compression pass, so the sort keys, dedup and pack-cut logic —
and therefore every output byte — are identical to an unbounded build.
0 (the default) = unlimited / legacy all-in-RAM behaviour.
Sourcepub fn memory_budget(&self) -> u64
pub fn memory_budget(&self) -> u64
The configured in-RAM payload budget in bytes (0 = unlimited).
Encode drivers (the stt-build tiler) read this so the ENCODED-but-not-
yet-added payloads of a parallel encode batch honor the same cap as
the writer’s own buffered payloads.
Sourcepub fn with_seeded_templates(self, templates: &TemplateRegistry) -> Self
pub fn with_seeded_templates(self, templates: &TemplateRegistry) -> Self
Seed the writer’s schema-template collector from an existing dataset’s
registry — the VERBATIM-repack path (pack-cover, repair tools). Copied
v2 payloads reference templates by 16-byte hash but are never
re-encoded, so nothing records their templates; without seeding, the
repacked manifest.schemas comes out empty and every tile read fails
template resolution. Recording is content-addressed (sorted + deduped
at finalize), so seeding order is irrelevant and templates the subset
no longer references ride along harmlessly.
Sourcepub fn with_format_version(self, format_version: u32) -> Self
pub fn with_format_version(self, format_version: u32) -> Self
Select the packed format version to emit (1 | 2; default 2 =
PACKED_FORMAT_VERSION). v1 is the one-release transitional kill
switch (stt-build --format-version 1) and reproduces the 0.3.x
output byte-for-byte. Anything else errors at
finalize. The caller is responsible for feeding
payloads of the MATCHING frame version — readers hard-reject
mixed-version datasets (design §1 ★F6).
Sourcepub fn format_version(&self) -> u32
pub fn format_version(&self) -> u32
The packed format version this writer will emit (1 | 2). Encode
callers derive their frame version from this so a dataset can never
mix frame and manifest versions (design §1 ★F6).
Sourcepub fn template_collector(&self) -> Arc<TemplateCollector>
pub fn template_collector(&self) -> Arc<TemplateCollector>
The writer’s schema-template sink for a v2 build. Install it on the
encoder (crate::arrow_tile::EncoderConfig::template_collector, or
process-wide via crate::arrow_tile::set_template_collector) so
every template a v2 frame references ends up in manifest.schemas at
finalize. Unused (and empty) under v1.
Sourcepub fn with_paging(self, page_entries: Option<usize>) -> Self
pub fn with_paging(self, page_entries: Option<usize>) -> Self
Opt into a paged directory: the .sttd becomes a root page + leaf
pages of ≤ page_entries entries each, so a cold reader fetches only the
leaves its viewport/time-window touches (Wave 2). None (the default)
emits the single whole-load v5 directory — byte-identical output to a
pre-paging build. Some(0) is clamped to 1.
Sourcepub fn with_zstd_level(self, level: i32) -> Self
pub fn with_zstd_level(self, level: i32) -> Self
Set the zstd compression level for tile blobs and the directory.
The packed format is write-once / serve-many, so the higher build CPU of
a level like 19 is paid once while the smaller bytes are paid on every
fetch (measured −10..19% vs the level-3 default; decode is unaffected).
Clamped to zstd’s valid 1..=22 range. The default
(compression::ZSTD_LEVEL) reproduces byte-identical pre-existing builds.
Sourcepub fn with_capabilities(self, capabilities: Vec<String>) -> Self
pub fn with_capabilities(self, capabilities: Vec<String>) -> Self
Declare the required-to-understand features this build used
(manifest.capabilities, spec §3.1) — e.g. CAPABILITY_COORD_QUANT
when coordinate quantization re-types the geometry column. Canonicalized
(sorted + deduped) so the manifest bytes never depend on call order.
Empty (the default) omits the key entirely, keeping the manifest
byte-identical to a pre-capabilities build.
Sourcepub fn with_measured_ordering(self, on: bool) -> Self
pub fn with_measured_ordering(self, on: bool) -> Self
Opt into the measured ordering picker (--blob-ordering measured):
at finalize, resolve the concrete on-disk blob order by simulating
per-ordering range-read cost over the native-tier tiles
(crate::ordering_sim) instead of the auto cardinality heuristic.
When on, the ordering passed to create is ignored.
false (the default) reproduces byte-identical pre-existing builds.
Sourcepub fn add_tile_full(
&mut self,
id: &TileId,
time_start: i64,
time_end: i64,
cover_t_min: Option<i64>,
feature_count: u32,
temporal_bucket_ms: Option<u64>,
payload: &[u8],
) -> Result<()>
pub fn add_tile_full( &mut self, id: &TileId, time_start: i64, time_end: i64, cover_t_min: Option<i64>, feature_count: u32, temporal_bucket_ms: Option<u64>, payload: &[u8], ) -> Result<()>
Add a tile carrying the full directory metadata. Same shape as
ArchiveWriter::add_tile_full: cover_t_min is the
tight lower covering bound (None to omit), temporal_bucket_ms tags the
directory entry with the temporal bucket size the tile represents. The
payload is the uncompressed tile frame.
Sourcepub fn tile_count(&self) -> usize
pub fn tile_count(&self) -> usize
Number of tiles buffered so far.
Sourcepub fn finalize(self, metadata: &Metadata) -> Result<Manifest>
pub fn finalize(self, metadata: &Metadata) -> Result<Manifest>
Finalise: order + dedup + per-blob zstd, cut packs, write
packs/*.sttp + index/*.sttd + manifest.json into out_dir.
Mirrors ArchiveWriter::finalize_buffered: the same time-bucket calc,
BlobOrdering::Auto → BlobOrdering::choose resolution, space-time
sort key, per-blob compress_zstd_with_dict(_, None) (no shared dict),
and blake3 byte-identical dedup. THEN the ordered, deduped blob stream is
cut into packs.
Auto Trait Implementations§
impl Freeze for PackWriter
impl RefUnwindSafe for PackWriter
impl Send for PackWriter
impl Sync for PackWriter
impl Unpin for PackWriter
impl UnsafeUnpin for PackWriter
impl UnwindSafe for PackWriter
Blanket Implementations§
impl<T> Allocation for T
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more