|
1 | 1 | package io.github.dfa1.vortex.core.model; |
2 | 2 |
|
| 3 | +import java.io.Serializable; |
3 | 4 | import java.util.Map; |
4 | | -import java.util.Optional; |
| 5 | +import java.util.Objects; |
5 | 6 | import java.util.function.Function; |
6 | 7 | import java.util.stream.Collectors; |
7 | 8 | import java.util.stream.Stream; |
8 | 9 |
|
9 | | -/// Strongly-typed encoding identifier used in place of raw strings. |
10 | | -public enum EncodingId { |
11 | | - /// Canonical flat primitive encoding (`vortex.primitive`). |
12 | | - VORTEX_PRIMITIVE("vortex.primitive"), |
13 | | - /// Bit-packed boolean encoding (`vortex.bool`). |
14 | | - VORTEX_BOOL("vortex.bool"), |
15 | | - /// Dictionary encoding for low-cardinality columns (`vortex.dict`). |
16 | | - VORTEX_DICT("vortex.dict"), |
17 | | - /// Sparse encoding for columns with many nulls or zeros (`vortex.sparse`). |
18 | | - VORTEX_SPARSE("vortex.sparse"), |
19 | | - /// Sequence encoding (`vortex.sequence`). |
20 | | - VORTEX_SEQUENCE("vortex.sequence"), |
21 | | - /// Run-end encoding for sorted/repetitive columns (`vortex.runend`). |
22 | | - VORTEX_RUNEND("vortex.runend"), |
23 | | - /// Constant encoding — all elements share one value (`vortex.constant`). |
24 | | - VORTEX_CONSTANT("vortex.constant"), |
25 | | - /// ALP (Adaptive Lossless floating-Point) encoding for F32/F64 (`vortex.alp`). |
26 | | - VORTEX_ALP("vortex.alp"), |
27 | | - /// Variable-length binary encoding (`vortex.varbin`). |
28 | | - VORTEX_VARBIN("vortex.varbin"), |
29 | | - /// FSST compressed string encoding (`vortex.fsst`). |
30 | | - VORTEX_FSST("vortex.fsst"), |
31 | | - /// All-null encoding (`vortex.null`). |
32 | | - VORTEX_NULL("vortex.null"), |
33 | | - /// One-byte-per-boolean encoding (`vortex.bytebool`). |
34 | | - VORTEX_BYTEBOOL("vortex.bytebool"), |
35 | | - /// Zig-zag encoding for signed integers (`vortex.zigzag`). |
36 | | - VORTEX_ZIGZAG("vortex.zigzag"), |
37 | | - /// Extension type wrapper encoding (`vortex.ext`). |
38 | | - VORTEX_EXT("vortex.ext"), |
39 | | - /// Variable-length binary view encoding (`vortex.varbinview`). |
40 | | - VORTEX_VARBINVIEW("vortex.varbinview"), |
41 | | - /// pcodec (Pco) floating-point/integer encoding (`vortex.pco`). |
42 | | - VORTEX_PCO("vortex.pco"), |
43 | | - /// Canonical flat decimal storage (`vortex.decimal`). |
44 | | - VORTEX_DECIMAL("vortex.decimal"), |
45 | | - /// Decimal split into MSP + LSP children (`vortex.decimal_byte_parts`). |
46 | | - VORTEX_DECIMAL_BYTE_PARTS("vortex.decimal_byte_parts"), |
47 | | - /// Timestamp split into days/seconds/subseconds (`vortex.datetimeparts`). |
48 | | - VORTEX_DATETIMEPARTS("vortex.datetimeparts"), |
49 | | - /// Zstandard compressed encoding (`vortex.zstd`). |
50 | | - VORTEX_ZSTD("vortex.zstd"), |
51 | | - /// Fixed-size list encoding (`vortex.fixed_size_list`). |
52 | | - VORTEX_FIXED_SIZE_LIST("vortex.fixed_size_list"), |
53 | | - /// Variable-length list encoding (`vortex.list`). |
54 | | - VORTEX_LIST("vortex.list"), |
55 | | - /// List-view encoding (`vortex.listview`). |
56 | | - VORTEX_LISTVIEW("vortex.listview"), |
57 | | - /// ALP-RD (ALP with remainder dictionary) encoding (`vortex.alprd`). |
58 | | - VORTEX_ALPRD("vortex.alprd"), |
59 | | - |
60 | | - // Layout encoding IDs included so parser/registry can represent them safely |
61 | | - /// Chunked layout encoding (`vortex.chunked`). |
62 | | - VORTEX_CHUNKED("vortex.chunked"), |
63 | | - /// Struct layout encoding (`vortex.struct`). |
64 | | - VORTEX_STRUCT("vortex.struct"), |
65 | | - |
66 | | - /// FastLanes bit-packed encoding (`fastlanes.bitpacked`). |
67 | | - FASTLANES_BITPACKED("fastlanes.bitpacked"), |
68 | | - /// FastLanes frame-of-reference encoding (`fastlanes.for`). |
69 | | - FASTLANES_FOR("fastlanes.for"), |
70 | | - /// FastLanes delta encoding (`fastlanes.delta`). |
71 | | - FASTLANES_DELTA("fastlanes.delta"), |
72 | | - /// FastLanes run-length encoding (`fastlanes.rle`). |
73 | | - FASTLANES_RLE("fastlanes.rle"), |
74 | | - |
75 | | - /// Masked encoding (`vortex.masked`): payload child plus optional validity bitmap child. |
76 | | - VORTEX_MASKED("vortex.masked"), |
77 | | - /// Patched encoding (`vortex.patched`): base child with sparse positional patch overrides. |
78 | | - VORTEX_PATCHED("vortex.patched"), |
79 | | - /// Variant logical encoding: canonical container over `core_storage` plus an optional shredded child. |
80 | | - VORTEX_VARIANT("vortex.variant"), |
81 | | - ; |
82 | | - |
83 | | - // O(1) access to EncodingId by its string representation |
84 | | - private static final Map<String, EncodingId> LOOKUP = Stream.of(EncodingId.values()) |
85 | | - .collect(Collectors.toUnmodifiableMap(EncodingId::id, Function.identity())); |
86 | | - private final String id; |
87 | | - |
88 | | - EncodingId(String id) { |
89 | | - this.id = id; |
90 | | - } |
| 10 | +/// Identity of an array encoding — either a spec [WellKnown] constant or a third-party [Custom] id. |
| 11 | +/// |
| 12 | +/// The wire representation is always a string (e.g. `"vortex.flat"`); [#parse(String)] maps any |
| 13 | +/// such string to a typed value, and [#id()] recovers the wire string from a typed value. |
| 14 | +/// |
| 15 | +/// Extends [Serializable] so a [Custom] or [WellKnown] carried on a |
| 16 | +/// [io.github.dfa1.vortex.core.error.VortexException] survives serialization, matching the prior |
| 17 | +/// enum's implicit serializability. |
| 18 | +public sealed interface EncodingId extends Serializable permits EncodingId.WellKnown, EncodingId.Custom { |
91 | 19 |
|
92 | | - /// Parses a raw encoding id string into the matching constant. |
93 | | - /// Used by `ReadRegistry` to discriminate `KnownArrayNode` from `UnknownArrayNode`; |
94 | | - /// callers that demand a known id chain `.orElseThrow(...)`. |
| 20 | + /// Returns the wire string of this encoding id (e.g. `"vortex.flat"`). |
95 | 21 | /// |
96 | | - /// @param id raw encoding id string (e.g. `"vortex.primitive"`) |
97 | | - /// @return matching constant, or empty if not recognized |
98 | | - public static Optional<EncodingId> parse(String id) { |
99 | | - return Optional.ofNullable(LOOKUP.get(id)); |
100 | | - } |
| 22 | + /// @return the wire string of this encoding id |
| 23 | + String id(); |
101 | 24 |
|
102 | | - /// Returns the raw encoding id string for this constant (e.g. `"vortex.primitive"`). |
| 25 | + /// Total parse: every non-null string has a typed representation. |
| 26 | + /// Returns the matching [WellKnown] constant, else a [Custom] wrapping the raw string. |
103 | 27 | /// |
104 | | - /// @return the raw string encoding id |
105 | | - public String id() { |
106 | | - return id; |
| 28 | + /// @param raw the raw encoding id string (e.g. `"vortex.primitive"`) |
| 29 | + /// @return the matching [WellKnown] constant, or a [Custom] wrapping `raw` if none matches |
| 30 | + static EncodingId parse(String raw) { |
| 31 | + WellKnown known = WellKnown.byId(raw); |
| 32 | + return known != null ? known : new Custom(raw); |
107 | 33 | } |
108 | 34 |
|
109 | | - @Override |
110 | | - public String toString() { |
111 | | - return id; |
| 35 | + /// Encoding ids defined by the Vortex specification and understood by this build. |
| 36 | + enum WellKnown implements EncodingId { |
| 37 | + /// Canonical flat primitive encoding (`vortex.primitive`). |
| 38 | + VORTEX_PRIMITIVE("vortex.primitive"), |
| 39 | + /// Bit-packed boolean encoding (`vortex.bool`). |
| 40 | + VORTEX_BOOL("vortex.bool"), |
| 41 | + /// Dictionary encoding for low-cardinality columns (`vortex.dict`). |
| 42 | + VORTEX_DICT("vortex.dict"), |
| 43 | + /// Sparse encoding for columns with many nulls or zeros (`vortex.sparse`). |
| 44 | + VORTEX_SPARSE("vortex.sparse"), |
| 45 | + /// Sequence encoding (`vortex.sequence`). |
| 46 | + VORTEX_SEQUENCE("vortex.sequence"), |
| 47 | + /// Run-end encoding for sorted/repetitive columns (`vortex.runend`). |
| 48 | + VORTEX_RUNEND("vortex.runend"), |
| 49 | + /// Constant encoding — all elements share one value (`vortex.constant`). |
| 50 | + VORTEX_CONSTANT("vortex.constant"), |
| 51 | + /// ALP (Adaptive Lossless floating-Point) encoding for F32/F64 (`vortex.alp`). |
| 52 | + VORTEX_ALP("vortex.alp"), |
| 53 | + /// Variable-length binary encoding (`vortex.varbin`). |
| 54 | + VORTEX_VARBIN("vortex.varbin"), |
| 55 | + /// FSST compressed string encoding (`vortex.fsst`). |
| 56 | + VORTEX_FSST("vortex.fsst"), |
| 57 | + /// All-null encoding (`vortex.null`). |
| 58 | + VORTEX_NULL("vortex.null"), |
| 59 | + /// One-byte-per-boolean encoding (`vortex.bytebool`). |
| 60 | + VORTEX_BYTEBOOL("vortex.bytebool"), |
| 61 | + /// Zig-zag encoding for signed integers (`vortex.zigzag`). |
| 62 | + VORTEX_ZIGZAG("vortex.zigzag"), |
| 63 | + /// Extension type wrapper encoding (`vortex.ext`). |
| 64 | + VORTEX_EXT("vortex.ext"), |
| 65 | + /// Variable-length binary view encoding (`vortex.varbinview`). |
| 66 | + VORTEX_VARBINVIEW("vortex.varbinview"), |
| 67 | + /// pcodec (Pco) floating-point/integer encoding (`vortex.pco`). |
| 68 | + VORTEX_PCO("vortex.pco"), |
| 69 | + /// Canonical flat decimal storage (`vortex.decimal`). |
| 70 | + VORTEX_DECIMAL("vortex.decimal"), |
| 71 | + /// Decimal split into MSP + LSP children (`vortex.decimal_byte_parts`). |
| 72 | + VORTEX_DECIMAL_BYTE_PARTS("vortex.decimal_byte_parts"), |
| 73 | + /// Timestamp split into days/seconds/subseconds (`vortex.datetimeparts`). |
| 74 | + VORTEX_DATETIMEPARTS("vortex.datetimeparts"), |
| 75 | + /// Zstandard compressed encoding (`vortex.zstd`). |
| 76 | + VORTEX_ZSTD("vortex.zstd"), |
| 77 | + /// Fixed-size list encoding (`vortex.fixed_size_list`). |
| 78 | + VORTEX_FIXED_SIZE_LIST("vortex.fixed_size_list"), |
| 79 | + /// Variable-length list encoding (`vortex.list`). |
| 80 | + VORTEX_LIST("vortex.list"), |
| 81 | + /// List-view encoding (`vortex.listview`). |
| 82 | + VORTEX_LISTVIEW("vortex.listview"), |
| 83 | + /// ALP-RD (ALP with remainder dictionary) encoding (`vortex.alprd`). |
| 84 | + VORTEX_ALPRD("vortex.alprd"), |
| 85 | + |
| 86 | + // Layout encoding IDs included so parser/registry can represent them safely |
| 87 | + /// Chunked layout encoding (`vortex.chunked`). |
| 88 | + VORTEX_CHUNKED("vortex.chunked"), |
| 89 | + /// Struct layout encoding (`vortex.struct`). |
| 90 | + VORTEX_STRUCT("vortex.struct"), |
| 91 | + |
| 92 | + /// FastLanes bit-packed encoding (`fastlanes.bitpacked`). |
| 93 | + FASTLANES_BITPACKED("fastlanes.bitpacked"), |
| 94 | + /// FastLanes frame-of-reference encoding (`fastlanes.for`). |
| 95 | + FASTLANES_FOR("fastlanes.for"), |
| 96 | + /// FastLanes delta encoding (`fastlanes.delta`). |
| 97 | + FASTLANES_DELTA("fastlanes.delta"), |
| 98 | + /// FastLanes run-length encoding (`fastlanes.rle`). |
| 99 | + FASTLANES_RLE("fastlanes.rle"), |
| 100 | + |
| 101 | + /// Masked encoding (`vortex.masked`): payload child plus optional validity bitmap child. |
| 102 | + VORTEX_MASKED("vortex.masked"), |
| 103 | + /// Patched encoding (`vortex.patched`): base child with sparse positional patch overrides. |
| 104 | + VORTEX_PATCHED("vortex.patched"), |
| 105 | + /// Variant logical encoding: canonical container over `core_storage` plus an optional shredded child. |
| 106 | + VORTEX_VARIANT("vortex.variant"), |
| 107 | + ; |
| 108 | + |
| 109 | + // O(1) access to a WellKnown constant by its string representation |
| 110 | + private static final Map<String, WellKnown> LOOKUP = Stream.of(values()) |
| 111 | + .collect(Collectors.toUnmodifiableMap(WellKnown::id, Function.identity())); |
| 112 | + private final String id; |
| 113 | + |
| 114 | + WellKnown(String id) { |
| 115 | + this.id = id; |
| 116 | + } |
| 117 | + |
| 118 | + /// Returns the well-known constant whose wire string is `id`, or `null` if none matches. |
| 119 | + /// |
| 120 | + /// @param id the wire string to look up (may be `null`) |
| 121 | + /// @return the matching constant, or `null` if unrecognized |
| 122 | + static WellKnown byId(String id) { |
| 123 | + return LOOKUP.get(id); |
| 124 | + } |
| 125 | + |
| 126 | + @Override |
| 127 | + public String id() { |
| 128 | + return id; |
| 129 | + } |
| 130 | + |
| 131 | + @Override |
| 132 | + public String toString() { |
| 133 | + return id; |
| 134 | + } |
| 135 | + } |
| 136 | + |
| 137 | + /// A third-party encoding id whose wire string is not part of the [WellKnown] set. |
| 138 | + /// |
| 139 | + /// @param id the wire string of this encoding id; must be non-blank and must not collide |
| 140 | + /// with a [WellKnown] wire string |
| 141 | + record Custom(String id) implements EncodingId { |
| 142 | + |
| 143 | + /// Validates that `id` is a usable custom encoding id. |
| 144 | + /// |
| 145 | + /// @param id the wire string of this encoding id |
| 146 | + /// @throws NullPointerException if `id` is `null` |
| 147 | + /// @throws IllegalArgumentException if `id` is blank or matches a [WellKnown] wire string |
| 148 | + public Custom { |
| 149 | + Objects.requireNonNull(id, "id"); |
| 150 | + if (id.isBlank()) { |
| 151 | + throw new IllegalArgumentException("encoding id must not be blank"); |
| 152 | + } |
| 153 | + WellKnown wellKnown = WellKnown.byId(id); |
| 154 | + if (wellKnown != null) { |
| 155 | + throw new IllegalArgumentException( |
| 156 | + "\"" + id + "\" is a well-known encoding id; use EncodingId." + wellKnown.name() + " instead"); |
| 157 | + } |
| 158 | + } |
| 159 | + |
| 160 | + @Override |
| 161 | + public String toString() { |
| 162 | + return id; |
| 163 | + } |
112 | 164 | } |
| 165 | + |
| 166 | + // Re-export every WellKnown constant, typed as WellKnown, so existing `EncodingId.VORTEX_FOO` |
| 167 | + // call sites keep compiling and remain usable wherever a WellKnown is required. |
| 168 | + |
| 169 | + /// Well-known `vortex.primitive` id. |
| 170 | + WellKnown VORTEX_PRIMITIVE = WellKnown.VORTEX_PRIMITIVE; |
| 171 | + /// Well-known `vortex.bool` id. |
| 172 | + WellKnown VORTEX_BOOL = WellKnown.VORTEX_BOOL; |
| 173 | + /// Well-known `vortex.dict` id. |
| 174 | + WellKnown VORTEX_DICT = WellKnown.VORTEX_DICT; |
| 175 | + /// Well-known `vortex.sparse` id. |
| 176 | + WellKnown VORTEX_SPARSE = WellKnown.VORTEX_SPARSE; |
| 177 | + /// Well-known `vortex.sequence` id. |
| 178 | + WellKnown VORTEX_SEQUENCE = WellKnown.VORTEX_SEQUENCE; |
| 179 | + /// Well-known `vortex.runend` id. |
| 180 | + WellKnown VORTEX_RUNEND = WellKnown.VORTEX_RUNEND; |
| 181 | + /// Well-known `vortex.constant` id. |
| 182 | + WellKnown VORTEX_CONSTANT = WellKnown.VORTEX_CONSTANT; |
| 183 | + /// Well-known `vortex.alp` id. |
| 184 | + WellKnown VORTEX_ALP = WellKnown.VORTEX_ALP; |
| 185 | + /// Well-known `vortex.varbin` id. |
| 186 | + WellKnown VORTEX_VARBIN = WellKnown.VORTEX_VARBIN; |
| 187 | + /// Well-known `vortex.fsst` id. |
| 188 | + WellKnown VORTEX_FSST = WellKnown.VORTEX_FSST; |
| 189 | + /// Well-known `vortex.null` id. |
| 190 | + WellKnown VORTEX_NULL = WellKnown.VORTEX_NULL; |
| 191 | + /// Well-known `vortex.bytebool` id. |
| 192 | + WellKnown VORTEX_BYTEBOOL = WellKnown.VORTEX_BYTEBOOL; |
| 193 | + /// Well-known `vortex.zigzag` id. |
| 194 | + WellKnown VORTEX_ZIGZAG = WellKnown.VORTEX_ZIGZAG; |
| 195 | + /// Well-known `vortex.ext` id. |
| 196 | + WellKnown VORTEX_EXT = WellKnown.VORTEX_EXT; |
| 197 | + /// Well-known `vortex.varbinview` id. |
| 198 | + WellKnown VORTEX_VARBINVIEW = WellKnown.VORTEX_VARBINVIEW; |
| 199 | + /// Well-known `vortex.pco` id. |
| 200 | + WellKnown VORTEX_PCO = WellKnown.VORTEX_PCO; |
| 201 | + /// Well-known `vortex.decimal` id. |
| 202 | + WellKnown VORTEX_DECIMAL = WellKnown.VORTEX_DECIMAL; |
| 203 | + /// Well-known `vortex.decimal_byte_parts` id. |
| 204 | + WellKnown VORTEX_DECIMAL_BYTE_PARTS = WellKnown.VORTEX_DECIMAL_BYTE_PARTS; |
| 205 | + /// Well-known `vortex.datetimeparts` id. |
| 206 | + WellKnown VORTEX_DATETIMEPARTS = WellKnown.VORTEX_DATETIMEPARTS; |
| 207 | + /// Well-known `vortex.zstd` id. |
| 208 | + WellKnown VORTEX_ZSTD = WellKnown.VORTEX_ZSTD; |
| 209 | + /// Well-known `vortex.fixed_size_list` id. |
| 210 | + WellKnown VORTEX_FIXED_SIZE_LIST = WellKnown.VORTEX_FIXED_SIZE_LIST; |
| 211 | + /// Well-known `vortex.list` id. |
| 212 | + WellKnown VORTEX_LIST = WellKnown.VORTEX_LIST; |
| 213 | + /// Well-known `vortex.listview` id. |
| 214 | + WellKnown VORTEX_LISTVIEW = WellKnown.VORTEX_LISTVIEW; |
| 215 | + /// Well-known `vortex.alprd` id. |
| 216 | + WellKnown VORTEX_ALPRD = WellKnown.VORTEX_ALPRD; |
| 217 | + /// Well-known `vortex.chunked` id. |
| 218 | + WellKnown VORTEX_CHUNKED = WellKnown.VORTEX_CHUNKED; |
| 219 | + /// Well-known `vortex.struct` id. |
| 220 | + WellKnown VORTEX_STRUCT = WellKnown.VORTEX_STRUCT; |
| 221 | + /// Well-known `fastlanes.bitpacked` id. |
| 222 | + WellKnown FASTLANES_BITPACKED = WellKnown.FASTLANES_BITPACKED; |
| 223 | + /// Well-known `fastlanes.for` id. |
| 224 | + WellKnown FASTLANES_FOR = WellKnown.FASTLANES_FOR; |
| 225 | + /// Well-known `fastlanes.delta` id. |
| 226 | + WellKnown FASTLANES_DELTA = WellKnown.FASTLANES_DELTA; |
| 227 | + /// Well-known `fastlanes.rle` id. |
| 228 | + WellKnown FASTLANES_RLE = WellKnown.FASTLANES_RLE; |
| 229 | + /// Well-known `vortex.masked` id. |
| 230 | + WellKnown VORTEX_MASKED = WellKnown.VORTEX_MASKED; |
| 231 | + /// Well-known `vortex.patched` id. |
| 232 | + WellKnown VORTEX_PATCHED = WellKnown.VORTEX_PATCHED; |
| 233 | + /// Well-known `vortex.variant` id. |
| 234 | + WellKnown VORTEX_VARIANT = WellKnown.VORTEX_VARIANT; |
113 | 235 | } |
0 commit comments