Skip to content
Merged
Show file tree
Hide file tree
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
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ line-by-line diff is zero.
<dependency>
<groupId>io.github.dfa1.vortex</groupId>
<artifactId>vortex-reader</artifactId>
<version>0.12.2</version>
<version>0.13.0</version>
</dependency>
```

Expand Down Expand Up @@ -102,7 +102,7 @@ try (VortexReader vf = VortexReader.open(Path.of("data/example.vortex"));
<dependency>
<groupId>io.github.dfa1.vortex</groupId>
<artifactId>vortex-writer</artifactId>
<version>0.12.2</version>
<version>0.13.0</version>
</dependency>
```

Expand Down
5 changes: 3 additions & 2 deletions cli/src/test/java/io/github/dfa1/vortex/cli/CliIT.java
Original file line number Diff line number Diff line change
Expand Up @@ -239,8 +239,9 @@ void importRejectsMultiCharacterDelimiter(@TempDir Path tmp) throws Exception {
() -> ImportCommand.run(new String[]{"import", "--delimiter", "::", csvIn.toString()}));

// Then
assertThat(stderr).contains("--delimiter must be exactly one character");
assertThat(stderr).contains("usage: import [--delimiter <char>]");
assertThat(stderr)
.contains("--delimiter must be exactly one character")
.contains("usage: import [--delimiter <char>]");
assertThat(tmp.resolve("data.vortex")).doesNotExist();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -248,9 +248,10 @@ void rendersFullRowWithAsciiGutter() {
String row = InspectorRender.formatHexRow(data, 0);

// Then — offset, hex columns, ASCII gutter
assertThat(row).startsWith("00000000 ");
assertThat(row).contains("41 42 43"); // A B C
assertThat(row).contains("|ABCDEFGHIJKLMNOP|");
assertThat(row)
.startsWith("00000000 ")
.contains("41 42 43") // A B C
.contains("|ABCDEFGHIJKLMNOP|");
}

@Test
Expand All @@ -262,9 +263,10 @@ void padsShortTrailingRowAndDotsNonPrintable() {
String row = InspectorRender.formatHexRow(data, 0);

// Then — non-printable shows as '.', missing columns are padded
assertThat(row).startsWith("00000000 ");
assertThat(row).contains("78 00 79");
assertThat(row).contains("|x.y");
assertThat(row)
.startsWith("00000000 ")
.contains("78 00 79")
.contains("|x.y");
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,11 @@ void navigatesAndRendersGrid() throws Exception {

// Then — title, column header, and at least one decoded cell rendered
String out = term.output();
assertThat(out).contains("Vortex View");
assertThat(out).contains("grid.vortex");
assertThat(out).contains("q quit");
assertThat(out).contains("a").contains("b").contains("c");
assertThat(out)
.contains("Vortex View")
.contains("grid.vortex")
.contains("q quit")
.contains("a").contains("b").contains("c");
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,10 @@ void navigatesAndRendersInspector() throws Exception {

// Then — header chrome and tree content rendered
String out = term.output();
assertThat(out).contains("vortex-inspect");
assertThat(out).contains("struct");
assertThat(out).contains("quit");
assertThat(out)
.contains("vortex-inspect")
.contains("struct")
.contains("quit");
}

@Test
Expand Down Expand Up @@ -88,9 +89,10 @@ void deepExpand_rendersDictStatsAndDataPanes_synchronously() throws Exception {

// Then — the dictionary, per-chunk stats, and data preview panes all rendered
String out = term.output();
assertThat(out).contains("Dictionary");
assertThat(out).contains("Per-chunk stats");
assertThat(out).contains("Data (column");
assertThat(out)
.contains("Dictionary")
.contains("Per-chunk stats")
.contains("Data (column");
}

@Test
Expand Down
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -315,8 +315,7 @@ void recordsWithEqualByteArraysAreEqual() {
ProtoScalarValue b = ProtoScalarValue.ofBytesValue(new byte[]{1, 2, 3});

// When + Then
assertThat(a).isEqualTo(b);
assertThat(a).hasSameHashCodeAs(b);
assertThat(a).isEqualTo(b).hasSameHashCodeAs(b);
}

@Test
Expand Down
4 changes: 2 additions & 2 deletions docs/compatibility.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,14 @@ A consumer that only needs to read Vortex files can depend on a strict subset:
<dependency>
<groupId>io.github.dfa1.vortex</groupId>
<artifactId>vortex-reader</artifactId>
<version>0.12.2</version>
<version>0.13.0</version>
</dependency>

<!-- optional: inspector for layout-tree introspection -->
<dependency>
<groupId>io.github.dfa1.vortex</groupId>
<artifactId>vortex-inspector</artifactId>
<version>0.12.2</version>
<version>0.13.0</version>
</dependency>
```

Expand Down
4 changes: 2 additions & 2 deletions docs/reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -130,11 +130,11 @@ Accepted array types per column `DType`:

### `WriteOptions` (`io.github.dfa1.vortex.writer.WriteOptions`)

Record: `(int chunkSize, boolean enableZoneMaps, double compressionRatioThreshold, int allowedCascading, boolean globalDict, boolean enableZstd, long globalDictMaxRetainedBytes, Map<EditionFamily, Edition> editions)`.
Record: `(int chunkSize, boolean enableZoneMaps, double compressionRatioThreshold, int allowedCascading, boolean globalDict, boolean enableZstd, MemorySize globalDictMaxRetainedBytes, Map<EditionFamily, Edition> editions)`.

| Factory | Defaults |
|---------------------------------|---------------------------------------------------------------------------------------------------|
| `WriteOptions.defaults()` | `chunkSize=65_536`, `enableZoneMaps=true`, `compressionRatioThreshold=0.90`, `allowedCascading=0`, `globalDict=true`, `enableZstd=false`, `globalDictMaxRetainedBytes=2 GB`, `editions={CORE: Editions.CORE_2026_07_0}` |
| `WriteOptions.defaults()` | `chunkSize=65_536`, `enableZoneMaps=true`, `compressionRatioThreshold=0.90`, `allowedCascading=0`, `globalDict=true`, `enableZstd=false`, `globalDictMaxRetainedBytes=MemorySize.ofGiB(2)`, `editions={CORE: Editions.CORE_2026_07_0}` |
| `WriteOptions.cascading(depth)` | Same defaults, `allowedCascading=depth` |

| Method | Notes |
Expand Down
2 changes: 1 addition & 1 deletion docs/tutorial.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ Add the dependency to `pom.xml` (inside `<dependencies>`):
<dependency>
<groupId>io.github.dfa1.vortex</groupId>
<artifactId>vortex-reader</artifactId>
<version>0.12.2</version>
<version>0.13.0</version>
</dependency>
```

Expand Down
55 changes: 30 additions & 25 deletions fbs-gen/src/test/java/io/github/dfa1/vortex/fbsgen/CodeGenTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -53,15 +53,16 @@ void emitsScalarVectorAndChildAccessorsForTable() throws IOException {
String src = generateOne("FbsLayout.java");

// Then — accessors match the flatc read shapes (widened unsigned types).
assertThat(src).contains("extends FbsTable");
assertThat(src).contains("public int encoding() {");
assertThat(src).contains("public long rowCount() {");
assertThat(src).contains("public MemorySegment metadataAsSegment() {");
assertThat(src).contains("public int childrenLength() {");
assertThat(src).contains("public FbsLayout children(int j) {");
assertThat(src).contains("indirect(vectorElements(o) + (long) j * 4)");
assertThat(src).contains("public long segments(int j) {");
assertThat(src).contains("readInt(vectorElements(o) + (long) j * 4) & 0xFFFFFFFFL");
assertThat(src)
.contains("extends FbsTable")
.contains("public int encoding() {")
.contains("public long rowCount() {")
.contains("public MemorySegment metadataAsSegment() {")
.contains("public int childrenLength() {")
.contains("public FbsLayout children(int j) {")
.contains("indirect(vectorElements(o) + (long) j * 4)")
.contains("public long segments(int j) {")
.contains("readInt(vectorElements(o) + (long) j * 4) & 0xFFFFFFFFL");
}

@Test
Expand All @@ -71,12 +72,13 @@ void emitsInlineOffsetsForStruct() throws IOException {
String src = generateOne("FbsBuffer.java");

// Then
assertThat(src).contains("extends FbsMemorySegment");
assertThat(src).contains("8 bytes");
assertThat(src).contains("public int padding() {\n return readShort(0) & 0xFFFF;");
assertThat(src).contains("public int alignmentExponent() {\n return readByte(2) & 0xFF;");
assertThat(src).contains("public int compression() {\n return readByte(3) & 0xFF;");
assertThat(src).contains("public long length() {\n return readInt(4) & 0xFFFFFFFFL;");
assertThat(src)
.contains("extends FbsMemorySegment")
.contains("8 bytes")
.contains("public int padding() {\n return readShort(0) & 0xFFFF;")
.contains("public int alignmentExponent() {\n return readByte(2) & 0xFF;")
.contains("public int compression() {\n return readByte(3) & 0xFF;")
.contains("public long length() {\n return readInt(4) & 0xFFFFFFFFL;");
}

@Test
Expand All @@ -85,11 +87,12 @@ void emitsDiscriminatorAndMemberPositionForUnionField() throws IOException {
String src = generateOne("FbsDType.java");

// Then — discriminator at vtable slot 4, value (member) projected from slot 6.
assertThat(src).contains("public int typeType() {");
assertThat(src).contains("fieldOffset(4)");
assertThat(src).contains("public <T extends FbsTable> T type(T obj) {");
assertThat(src).contains("locate(obj, unionMemberPosition(o))");
assertThat(src).contains("fieldOffset(6)");
assertThat(src)
.contains("public int typeType() {")
.contains("fieldOffset(4)")
.contains("public <T extends FbsTable> T type(T obj) {")
.contains("locate(obj, unionMemberPosition(o))")
.contains("fieldOffset(6)");
}

@Test
Expand All @@ -98,9 +101,10 @@ void emitsUnionConstantsHolder() throws IOException {
String src = generateOne("FbsType.java");

// Then — NONE plus members with explicit discriminators (byte, like flatc).
assertThat(src).contains("public static final byte NONE = 0;");
assertThat(src).contains("public static final byte FbsNull = (byte) 1;");
assertThat(src).contains("public static final byte FbsUnion = (byte) 12;");
assertThat(src)
.contains("public static final byte NONE = 0;")
.contains("public static final byte FbsNull = (byte) 1;")
.contains("public static final byte FbsUnion = (byte) 12;");
}

@Test
Expand All @@ -109,8 +113,9 @@ void emitsEnumConstantsOverUnderlyingType() throws IOException {
String src = generateOne("FbsPType.java");

// Then — byte constants, auto-numbered from 0.
assertThat(src).contains("public static final byte U8 = (byte) 0;");
assertThat(src).contains("public static final byte F64 = (byte) 10;");
assertThat(src)
.contains("public static final byte U8 = (byte) 0;")
.contains("public static final byte F64 = (byte) 10;");
}

private static void generate(Path out) throws IOException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ void lookup_realThreeByteSymbol_resolvesCode() {

// Then — packed as code << 8 | length; a hit is never 0.
assertThat(result).isNotZero();
assertThat(result >>> 8).isEqualTo(0);
assertThat(result >>> 8).isZero();
assertThat(result & 0xFF).isEqualTo(3);
}

Expand Down Expand Up @@ -71,7 +71,7 @@ void lookup_hashCollisionInGainOrder_higherGainWinsSlotLowerGainMisses() {
// Then — the higher-gain (first-inserted) symbol wins; the lower-gain one correctly misses
// and does not corrupt or masquerade as the winner.
assertThat(higher).isNotZero();
assertThat(higher >>> 8).isEqualTo(0);
assertThat(higher >>> 8).isZero();
assertThat(lower).isZero();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ void longestMatch_eightByteSymbol_picksHashTableMatch() {
int result = sut.longestMatch(wordOf("ABCDEFGH"));

// Then — the longest (8-byte) symbol wins.
assertThat(Matcher.codeOf(result)).isEqualTo(0);
assertThat(Matcher.codeOf(result)).isZero();
assertThat(Matcher.lengthOf(result)).isEqualTo(8);
}

Expand Down Expand Up @@ -81,7 +81,7 @@ void longestMatch_unmatchedByte_signalsNoMatch() {
int result = sut.longestMatch(wordOf("zzzzzzzz"));

// Then
assertThat(Matcher.lengthOf(result)).isEqualTo(0);
assertThat(Matcher.lengthOf(result)).isZero();
assertThat(Matcher.codeOf(result)).isEqualTo(ShortCodeTable.NO_CODE);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ void codeFor_singleByteSymbol_resolvesLengthOne() {
int length = sut.lengthFor(word);

// Then
assertThat(code).isEqualTo(0);
assertThat(code).isZero();
assertThat(length).isEqualTo(1);
}

Expand Down Expand Up @@ -57,7 +57,7 @@ void codeFor_singleByteFallbackWhenTwoByteDiffers() {
int length = sut.lengthFor(word);

// Then
assertThat(code).isEqualTo(0);
assertThat(code).isZero();
assertThat(length).isEqualTo(1);
}

Expand All @@ -74,7 +74,7 @@ void codeFor_byteWithNoSymbol_resolvesNoMatch() {

// Then — the caller must escape this byte.
assertThat(code).isEqualTo(ShortCodeTable.NO_CODE);
assertThat(length).isEqualTo(0);
assertThat(length).isZero();
}

@Test
Expand All @@ -88,7 +88,7 @@ void codeFor_longSymbolsIgnored() {
int length = sut.lengthFor(word);

// Then
assertThat(length).isEqualTo(0);
assertThat(length).isZero();
}

/// Packs the low bytes of `s` LSB-first into a word, matching the reader's little-endian
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,7 @@ void render_nonStruct_inlinesSingleColumnLayout() {
String result = VortexInspector.render(sut);

// Then
assertThat(result).contains("vortex.flat(100 rows)");
assertThat(result).doesNotContain("struct (");
assertThat(result).contains("vortex.flat(100 rows)").doesNotContain("struct (");
}

@Test
Expand Down Expand Up @@ -163,8 +162,7 @@ void render_columnWithoutStats_omitsMinMax() {
String result = VortexInspector.render(sut);

// Then
assertThat(result).doesNotContain("min=");
assertThat(result).doesNotContain("max=");
assertThat(result).doesNotContain("min=").doesNotContain("max=");
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -201,11 +201,10 @@ void fileSizeComparison(@TempDir Path tmp) throws IOException {
(double) javaSize / jniSize,
(double) csvSize / javaSize);

// Then — Java beats CSV
assertThat(javaSize).isLessThan(csvSize);

// Then — Java within 2x of JNI (both use cascading(3))
assertThat(javaSize).isLessThan(jniSize * 2);
// Then — Java beats CSV, and stays within 2x of JNI (both use cascading(3))
assertThat(javaSize)
.isLessThan(csvSize)
.isLessThan(jniSize * 2);

// Then — Java file is readable with correct row count
var totalRows = new java.util.concurrent.atomic.AtomicLong();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,8 +132,7 @@ void inspect_ohlcFile_showsColumnEncodings(@TempDir Path tmp) throws IOException

// Then
System.out.println(result);
assertThat(result).contains("volume");
assertThat(result).contains("Used encodings:");
assertThat(result).contains("volume").contains("Used encodings:");
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,11 +81,12 @@ void inspect_showsFileInfoAndEncodings(@TempDir Path tmp) throws IOException {

// Then
System.out.println(result);
assertThat(result).contains("Vortex v");
assertThat(result).contains("id");
assertThat(result).contains("value");
assertThat(result).contains("Registered encodings:");
assertThat(result).contains("Used encodings:");
assertThat(result).contains("Layout:");
assertThat(result)
.contains("Vortex v")
.contains("id")
.contains("value")
.contains("Registered encodings:")
.contains("Used encodings:")
.contains("Layout:");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,13 @@ void generatedBitPackedMetadataHasExpectedComponents(@TempDir Path tmp) throws I
String src = Files.readString(tmp.resolve("ProtoBitPackedMetadata.java"));

// Then
assertThat(src).contains("public record ProtoBitPackedMetadata(");
assertThat(src).contains("int bit_width");
assertThat(src).contains("int offset");
assertThat(src).contains("ProtoPatchesMetadata patches");
assertThat(src).contains("public static ProtoBitPackedMetadata decode(MemorySegment __seg, long __off, long __len)");
assertThat(src).contains("public byte[] encode()");
assertThat(src)
.contains("public record ProtoBitPackedMetadata(")
.contains("int bit_width")
.contains("int offset")
.contains("ProtoPatchesMetadata patches")
.contains("public static ProtoBitPackedMetadata decode(MemorySegment __seg, long __off, long __len)")
.contains("public byte[] encode()");
}

private static Ast.ProtoFile parse(Path p) throws IOException {
Expand Down
Loading