Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 45 additions & 8 deletions vortex-file/src/writer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -391,16 +391,25 @@ fn new_array_context(session: &VortexSession, enforce_editions: bool) -> ArrayCo
// serialised array order is deterministic. The serialisation of arrays are done
// parallel and with an empty context they can register their encodings to the context
// in different order, changing the written bytes from run to run.
//
// The seeded IDs are also what the writer may emit: callers read them back with
// `ArrayContext::to_ids` to restrict compression to the same set.

// The registry keys are exactly the serialized IDs that can be produced by the plugins
// registered in the session. Intersected with the serialized IDs the enabled editions permit,
// this is the set of IDs that can be written. Only seed the array context with these IDs, and
// only allow compressor schemes that produce arrays with serialized IDs within this set.
let registered: HashSet<ArrayId> = session
.arrays()
.registry()
.read(|registry| registry.keys().copied().collect());
let serialized_ids: Vec<ArrayId> = if enforce_editions {
session.enabled_component_ids(ComponentKind::Array)
} else {
// Must filter by the set of serialized IDs supported by registered plugins. Otherwise,
// we could enable an ID that will never be written.
session
.arrays()
.registry()
.read(|registry| registry.keys().copied().collect())
.enabled_component_ids(ComponentKind::Array)
.into_iter()
.filter(|id| registered.contains(id))
Comment thread
robert3005 marked this conversation as resolved.
.collect()
} else {
registered.into_iter().collect()
};
let array_ctx = ArrayContext::new(serialized_ids.iter().copied().sorted().collect());
if enforce_editions {
Expand Down Expand Up @@ -764,6 +773,7 @@ mod tests {
use vortex_edition::EditionMember;
use vortex_edition::EditionSession;
use vortex_edition::EditionSessionExt;
use vortex_session::registry::CachedId;

use super::*;

Expand All @@ -788,6 +798,33 @@ mod tests {
Ok(())
}

/// An edition may enable an encoding whose plugin is not registered on the session. Nothing
/// could serialize it, so it is neither seeded into the table nor offered to the compressor.
#[test]
fn array_context_skips_enabled_but_unregistered_encodings() -> VortexResult<()> {
const EDITION: EditionId = EditionId::new("test", 2026, 9, 0);
static DECLARATION: EditionDeclaration = EditionDeclaration {
edition: Edition {
id: EDITION,
min_library_version: None,
},
added: &[
EditionMember::array(&"vortex.primitive"),
EditionMember::array(&"vortex.alp"),
],
};

let session = array_session().with::<EditionSession>();
session.register_edition(&DECLARATION)?;
session.enable_edition(EDITION)?;

let ctx = new_array_context(&session, true);
assert_eq!(ctx.to_ids(), [Primitive.id()]);
static ALP: CachedId = CachedId::new("vortex.alp");
assert!(ctx.intern(&ALP).is_none());
Ok(())
}

#[test]
fn disabling_editions_allows_all_registered_array_ids() {
let session = array_session();
Expand Down
Loading